Skip to content

Agent API

Each agent VM runs a FastAPI server with the endpoints documented below. All endpoints except /health require authentication via the Authorization: Bearer <agent_secret> header.

In normal operation, these endpoints are called by the LiberClaw API proxy — not by end users directly. This reference is for developers building integrations or debugging agent behavior.

Every request (except GET /health) must include:

Authorization: Bearer <agent_secret>

The agent stores a SHA-256 hash of the secret and validates using constant-time comparison. Requests without a valid token receive a 401 Unauthorized response.

Health check endpoint. No authentication required.

Response:

{
"status": "ok",
"agent_name": "MyAgent",
"version": "1.0.0"
}
Terminal window
curl https://agent.example.com/health

Send a message and receive an SSE stream of events as the agent processes it. If there is an existing active run for the same chat_id, it is automatically cancelled before starting the new one.

Request body:

{
"message": "Hello, what can you do?",
"chat_id": "conv_abc123"
}

Response: text/event-stream (Server-Sent Events)

Each event is a JSON object on a data: line:

Event typeFieldsDescription
textcontentText output from the model
tool_usename, inputTool call being executed
filepath, captionFile being sent to the user
errorcontentError message
keepalive(none)Connection keepalive (sent every 15s during long operations)
done(none)Stream is complete
Terminal window
curl -N -X POST https://agent.example.com/chat \
-H "Authorization: Bearer $SECRET" \
-H "Content-Type: application/json" \
-d '{"message": "List files in the workspace", "chat_id": "test"}'

Example SSE output:

data: {"type": "tool_use", "name": "list_dir", "input": "{\"path\": \".\"}"}
data: {"type": "text", "content": "Here are the files in your workspace:\n..."}
data: {"type": "done"}

Check if there is an active (in-progress) chat run for a given chat ID.

Response:

{
"active": true,
"user_message": "List files in the workspace"
}

If no active run exists:

{
"active": false,
"user_message": ""
}
Terminal window
curl https://agent.example.com/chat/test/active \
-H "Authorization: Bearer $SECRET"

Reconnect to an active chat run’s SSE stream. Replays all buffered events from the beginning, then continues streaming live events. The first event is a stream_meta with the original user_message.

If no active run exists, returns a single done event.

Terminal window
curl -N https://agent.example.com/chat/test/stream \
-H "Authorization: Bearer $SECRET"

Example output on reconnect:

data: {"type": "stream_meta", "user_message": "List files in the workspace"}
data: {"type": "tool_use", "name": "list_dir", "input": "{\"path\": \".\"}"}
data: {"type": "text", "content": "Here are the files..."}
data: {"type": "done"}

Return conversation history as a list of chat events.

Query parameters:

ParameterTypeDefaultDescription
limitinteger50Maximum number of messages

Response:

{
"messages": [
{"type": "text", "content": "Hello", "name": "user"},
{"type": "text", "content": "Hi! How can I help?"},
{"type": "tool_use", "name": "bash", "input": "{\"command\": \"ls\"}"},
{"type": "file", "path": "images/chart.png"}
]
}

User messages include "name": "user". Assistant messages omit the name field.

Terminal window
curl https://agent.example.com/chat/test/history?limit=20 \
-H "Authorization: Bearer $SECRET"

Clear conversation history for a chat.

Response:

{
"status": "ok",
"deleted": 42
}
Terminal window
curl -X DELETE https://agent.example.com/chat/test \
-H "Authorization: Bearer $SECRET"

Return pending proactive messages (from heartbeat, subagents) and clear them.

Response:

{
"messages": [
{
"chat_id": "owner_123",
"content": "[Heartbeat] Updated the daily report.",
"source": "heartbeat",
"created_at": "2026-02-23T10:30:00"
}
]
}
Terminal window
curl https://agent.example.com/pending \
-H "Authorization: Bearer $SECRET"

Serve a file from the workspace. The path is relative to the workspace root. Protected by workspace boundary checks and the sensitive file blocklist.

Terminal window
curl https://agent.example.com/files/images/chart.png \
-H "Authorization: Bearer $SECRET" \
--output chart.png

Returns 403 Forbidden for paths that escape the workspace or match sensitive filenames (.env, agent.db).


Upload a file to the agent workspace.

Request: multipart/form-data

FieldTypeRequiredDescription
filefileyesThe file to upload
pathstringnoTarget directory (default: "uploads")

Response:

{
"path": "uploads/data.csv",
"size": 1024,
"name": "data.csv"
}

Maximum file size: 50 MB.

Terminal window
curl -X POST https://agent.example.com/files/upload \
-H "Authorization: Bearer $SECRET" \
-F "file=@data.csv" \
-F "path=uploads"

Return a recursive file tree of the workspace.

Query parameters:

ParameterTypeDefaultDescription
max_depthinteger5Maximum directory depth

Response:

{
"tree": [
{
"name": "memory",
"path": "memory",
"type": "dir",
"children": [
{"name": "MEMORY.md", "path": "memory/MEMORY.md", "type": "file", "size": 256}
]
},
{"name": "HEARTBEAT.md", "path": "HEARTBEAT.md", "type": "file", "size": 0}
]
}

Directories are listed before files. Sensitive files (.env, agent.db, .git, __pycache__, node_modules) are excluded.

Terminal window
curl https://agent.example.com/workspace/tree?max_depth=3 \
-H "Authorization: Bearer $SECRET"

List all subagent runs. Running subagents are listed first, then sorted by start time (newest first). Completed runs are retained for 1 hour.

Response:

{
"subagents": [
{
"id": "a1b2c3d4",
"label": "Research task",
"task": "Find the latest pricing for...",
"status": "running",
"chat_id": "conv_abc123",
"started_at": 1708700000.0,
"completed_at": null,
"result_preview": null,
"error": null,
"duration": 12.5
}
]
}

Subagent statuses: running, completed, failed, timeout.

Terminal window
curl https://agent.example.com/subagents \
-H "Authorization: Bearer $SECRET"

Get full details of a single subagent run, including the complete task, result, and persona.

Response:

{
"id": "a1b2c3d4",
"label": "Research task",
"task": "Find the latest pricing for cloud VMs across providers",
"persona": "You are a cloud infrastructure researcher",
"status": "completed",
"chat_id": "conv_abc123",
"started_at": 1708700000.0,
"completed_at": 1708700045.0,
"result": "Based on my research, here are the current prices...",
"error": null,
"duration": 45.0
}
Terminal window
curl https://agent.example.com/subagents/a1b2c3d4 \
-H "Authorization: Bearer $SECRET"

Cancel a running subagent. Returns an error if the subagent is not in the running state.

Response:

{
"status": "ok",
"run_id": "a1b2c3d4",
"message": "Subagent 'Research task' cancelled"
}
Terminal window
curl -X POST https://agent.example.com/subagents/a1b2c3d4/stop \
-H "Authorization: Bearer $SECRET"

Return Telegram bot connection status for agents with Telegram integration enabled.

Response (connected):

{
"connected": true,
"bot_username": "my_agent_bot",
"bot_name": "My Agent"
}

Response (not connected):

{
"connected": false,
"bot_username": "",
"bot_name": ""
}
Terminal window
curl https://agent.example.com/telegram/status \
-H "Authorization: Bearer $SECRET"

List Telegram contacts, optionally filtered by status.

Query parameters:

ParameterTypeRequiredDescription
statusstringnoFilter by status: allowed, pending, or blocked

Response:

{
"contacts": [
{
"telegram_id": "123456789",
"username": "johndoe",
"display_name": "John Doe",
"status": "allowed"
}
]
}
Terminal window
curl "https://agent.example.com/telegram/contacts?status=pending" \
-H "Authorization: Bearer $SECRET"

Update a Telegram contact’s status.

Request body:

{
"status": "allowed"
}

Valid statuses: allowed, pending, blocked.

Terminal window
curl -X PATCH https://agent.example.com/telegram/contacts/123456789 \
-H "Authorization: Bearer $SECRET" \
-H "Content-Type: application/json" \
-d '{"status": "allowed"}'

Remove a Telegram contact.

Response:

{
"status": "ok",
"telegram_id": "123456789"
}
Terminal window
curl -X DELETE https://agent.example.com/telegram/contacts/123456789 \
-H "Authorization: Bearer $SECRET"