Agents API
Create, manage, and interact with agents.
List agents
Returns all agents owned by the authenticated user. When no session is present, returns an empty list instead of a 401 error.
Response
{
"agents": [
{
"id": "agent_123",
"name": "My Agent",
"model": "claude-opus-4-6",
"status": "running",
"websocketUrl": "ws://openclaw-gateway:10000/agent/user_123",
"createdAt": "2026-03-01T00:00:00Z",
"updatedAt": "2026-03-18T00:00:00Z"
}
],
"count": 1,
"status": "ok"
}
Create agent
Get agent
Requires authentication and ownership of the agent.
Response
{
"agent": {
"id": "agent_123",
"status": "active",
"startedAt": "2026-03-01T00:00:00Z",
"plan": "starter",
"subdomain": "agent_123.agents.localhost",
"url": "https://agent_123.agents.localhost",
"openclawVersion": "2026.3.13",
"verified": false,
"verificationType": null,
"attestationUid": null,
"verifiedAt": null
},
"status": "ok"
}
| Code | Description |
|---|
| 401 | Unauthorized |
| 404 | Agent not found or not owned by user |
| 500 | Failed to fetch agent |
Update agent
Delete agent
Provision agent
POST /api/agents/provision
Provisions a new agent. Requires an active subscription unless the caller is an admin or designated tester.
Provisioning requests may be processed asynchronously through the background task queue. The agent is created immediately with a provisioning status and transitions to running once the gateway confirms the deployment. If gateway provisioning fails, the status changes to error.
Request body
| Field | Type | Required | Description |
|---|
name | string | Yes | Agent name |
model | string | No | AI model (default: claude-opus-4-6). Options: claude-opus-4-6, gpt-4, custom |
config | object | No | Agent configuration |
tier | string | No | Subscription tier hint. Options: starter, pro, enterprise |
The agent limit is determined by the subscription plan on the authenticated user’s account (starter: 1, pro: 3, enterprise: 100). It cannot be overridden in the request body.
Admin and tester bypass
Admin users (configured via ADMIN_EMAILS) and tester users (configured via TESTER_EMAILS) are exempt from the following restrictions:
- Subscription requirement — admins and testers can provision agents without an active subscription (the
402 error is not returned).
- Agent limit — admins receive an elevated agent slot limit instead of the plan-based cap.
Response (201 Created)
{
"success": true,
"agent": {
"id": "agent_789",
"name": "My Agent",
"status": "running",
"websocketUrl": "ws://openclaw-gateway:10000/agent/user_123",
"model": "claude-opus-4-6",
"createdAt": "2026-03-19T00:00:00Z"
}
}
| Code | Description |
|---|
| 400 | Agent name is required |
| 401 | Unauthorized |
| 402 | Active subscription required to provision agents |
| 429 | Agent limit reached for your plan. Response includes current (agent count) and limit fields. Limits: starter 1, pro 3, enterprise 100. Users without a recognized plan default to a limit of 1. |
| 500 | Failed to provision agent |
List provisioned agents
GET /api/agents/provision
Requires session authentication.
Response
{
"success": true,
"agents": [
{
"id": "agent_789",
"name": "My Agent",
"model": "claude-opus-4-6",
"status": "running",
"websocketUrl": "ws://openclaw-gateway:10000/agent/user_123",
"createdAt": "2026-03-19T00:00:00Z",
"updatedAt": "2026-03-19T00:00:00Z"
}
],
"count": 1
}
| Code | Description |
|---|
| 401 | Unauthorized |
| 500 | Failed to list agents |
Get agent configuration
GET /api/agents/:id/config
Returns the current configuration for an agent. Requires authentication and ownership.
Response
| Code | Description |
|---|
| 401 | Unauthorized |
| 502 | Backend service unavailable |
Update agent configuration
PUT /api/agents/:id/config
Updates the configuration for an agent. Requires authentication and ownership. The request body is forwarded to the backend.
| Code | Description |
|---|
| 401 | Unauthorized |
| 502 | Backend service unavailable |
Get agent logs
GET /api/agents/:id/logs is deprecated. This endpoint is not currently implemented and may be removed in a future release.
Get agent messages
GET /api/agents/:id/messages
Returns paginated messages for an agent. Requires authentication and ownership.
Query parameters
| Parameter | Type | Description |
|---|
limit | number | Maximum messages to return (default: 50) |
offset | number | Offset for pagination (default: 0) |
Response
{
"messages": [],
"total": 0,
"limit": 50,
"offset": 0,
"status": "ok"
}
| Code | Description |
|---|
| 401 | Unauthorized |
| 502 | Backend service unavailable |
Get agent stats
GET /api/agents/:id/stats
Returns live container metrics when available, with a mock fallback.
Response (live)
{
"stats": {
"agentId": "agent_123",
"cpu": "0.15%",
"memory": "128MiB / 2GiB",
"memoryPercent": "6.25%",
"network": "1.2kB / 3.4kB",
"uptime": 86400000,
"uptimeFormatted": "1d 0h",
"status": "running",
"pids": "12",
"messagesProcessed": "N/A",
"messagesPerHour": "N/A",
"averageResponseTime": "N/A",
"successRate": "N/A",
"errorRate": "N/A"
},
"status": "ok"
}
Response (mock fallback)
When the backend is unavailable, mock data is returned with "status": "mock":
{
"stats": {
"agentId": "agent_123",
"messagesProcessed": 1234,
"messagesPerHour": 456,
"averageResponseTime": 789,
"uptime": 12345,
"successRate": "95.42",
"errorRate": "4.58",
"timestamp": "2026-03-19T00:00:00Z"
},
"status": "mock"
}
Agent lifecycle
Lifecycle operations use the /api/instance/:userId endpoint pattern. These endpoints require session authentication and proxy to the backend agent management service.
Start agent
POST /api/instance/:userId/start
{
"success": true,
"status": "running"
}
Stop agent
POST /api/instance/:userId/stop
{
"success": true,
"status": "stopped"
}
Restart agent
POST /api/instance/:userId/restart
Restarts the agent. Before restarting, the backend automatically heals any deprecated AI model references in the agent configuration.
{
"success": true,
"status": "running"
}
Update agent image
POST /api/instance/:userId/update
Triggers an image update on the backend. The backend backs up the agent’s data before updating. If the new image fails to start, the backend rolls back to the previous image automatically.
{
"success": true,
"status": "running"
}
Repair agent
POST /api/instance/:userId/repair
Heals deprecated AI model references and recreates the agent container. Returns the backend response directly.
{
"success": true,
"message": "Agent repaired successfully"
}
Reset agent memory
POST /api/instance/:userId/reset-memory
Returns the backend response directly.
{
"success": true,
"message": "Memory reset successfully"
}
Lifecycle error responses
All lifecycle endpoints return the following shape on failure:
{
"success": false,
"status": "error"
}
| Code | Description |
|---|
| 403 | Forbidden — authenticated user does not own this agent instance |
| 502 | Backend service unavailable |
| 500 | Internal server error |
Get instance details
GET /api/instance/:userId
Returns the current status and metadata for an agent instance.
Response
{
"userId": "user_123",
"status": "running",
"startedAt": "2026-03-01T00:00:00Z",
"subdomain": "user_123.agents.localhost",
"url": "https://user_123.agents.localhost",
"plan": "free",
"openclawVersion": "2026.2.17"
}
Get instance stats
GET /api/instance/:userId/stats
Returns resource usage statistics for an agent instance.
Response
{
"userId": "user_123",
"cpu": "0.15%",
"memory": "128MiB",
"status": "running",
"plan": "starter",
"openclawVersion": "2026.3.13"
}
Get agent gateway token
GET /api/instance/:userId/token
Returns an auto-generated gateway token for the agent. A new token is created if none exists.
{
"token": "abc123def456"
}
| Code | Description |
|---|
| 502 | Backend service unavailable |
| 500 | Failed to get token |
Agent verification
Agents can be verified using multiple verification types: eas (Ethereum Attestation Service), coinbase, ens, or webauthn.
Get verification status
GET /api/agents/:id/verify
{
"verified": false,
"verificationType": null,
"attestationUid": null,
"verifierAddress": null,
"verifiedAt": null,
"metadata": null
}
Verify agent
POST /api/agents/:id/verify
Request body
| Field | Type | Required | Description |
|---|
verificationType | string | Yes | One of: eas, coinbase, ens, webauthn |
attestationUid | string | For eas | Attestation UID from EAS |
walletAddress | string | No | Address of the verifying wallet |
signature | string | Conditional | Cryptographic signature. Required for coinbase, ens, and webauthn verification types. |
Response
{
"success": true,
"verified": true,
"verificationType": "eas",
"attestationUid": "0x123...",
"verifiedAt": "2026-03-19T00:00:00Z"
}
| Code | Description |
|---|
| 400 | Invalid verification type or missing required fields |
| 401 | Unauthorized |
Remove verification
DELETE /api/agents/:id/verify
Provision with channel tokens
Provisions a new agent with messaging channel tokens. No authentication is required. Rate-limited per IP. At least one channel token is required.
The request is proxied to the backend provisioning service. A dedicated Mux live stream is automatically created for the agent. The backend may enqueue the provisioning job to the provision queue for asynchronous processing.
Kill switch
When the platform kill switch is enabled, all provisioning requests are rejected with a 503 Service Unavailable response. Existing agent instances continue running but no new agents can be created.
{
"error": "PLATFORM_DISABLED",
"message": "New provisioning is temporarily disabled. Existing instances continue running."
}
Request body
| Field | Type | Required | Description |
|---|
telegramToken | string | Conditional | Telegram bot token. At least one channel token is required. |
telegramUserId | string | No | Telegram user ID for owner binding |
whatsappToken | string | Conditional | WhatsApp API token. At least one channel token is required. |
discordBotToken | string | Conditional | Discord bot token. At least one channel token is required. |
aiProvider | string | No | AI provider (default: openrouter). Options: openrouter, gemini, groq, anthropic, openai |
apiKey | string | No | API key for the AI provider |
plan | string | No | Plan tier (default: free). Options: free, label, solo, collective, network |
email | string | No | Email address for the account |
stripeSubscriptionId | string | No | Stripe subscription ID. Required for paid plans unless the caller is an admin or tester. |
The following request fields are deprecated and no longer accepted: whatsappPhoneNumberId, whatsappBusinessAccountId, discordGuildId, discordChannelId.
Payment enforcement
Paid plans require a valid stripeSubscriptionId unless the caller’s email is in the admin or tester allow list:
- Free plan: Always returns
402 with code UPGRADE_REQUIRED. The free tier provides dashboard access only with zero compute.
- Paid plans without Stripe: Returns
402 with code PAYMENT_REQUIRED unless the caller is an admin or designated tester.
- Admin bypass: Users configured via
ADMIN_EMAILS skip the Stripe subscription check.
- Tester bypass: Users configured via
TESTER_EMAILS skip the Stripe subscription check.
Plan limits
| Plan | Max agents |
|---|
free | 0 (dashboard only) |
label | 1 |
solo | 3 |
collective | 10 |
network | 100 |
Response
The proxy returns a filtered subset of the backend response:
{
"success": true,
"userId": "a1b2c3d4e5",
"subdomain": "dj-a1b2c3d4e5.agentbot.raveculture.xyz",
"url": "https://dj-a1b2c3d4e5.agentbot.raveculture.xyz",
"streamKey": "sk-ab12-cd34-ef56",
"liveStreamId": "x7k9m2p4q1"
}
The /api/provision proxy returns only success, userId, subdomain, url, streamKey, and liveStreamId. Additional fields such as aiProvider, plan, and playbackUrl are available when calling the backend provisioning service directly.
| Code | Description |
|---|
| 400 | At least one channel token required (Telegram, WhatsApp, or Discord), invalid AI provider, or invalid plan |
| 402 | Payment required. Returns UPGRADE_REQUIRED for the free plan or PAYMENT_REQUIRED for paid plans without a valid Stripe subscription. |
| 429 | Too many requests |
| 500 | Internal server error |
| 502 | Provisioning service unavailable or returned an error |
| 503 | Platform kill switch is active. Provisioning is temporarily disabled. |
Agent interaction
GET /api/agent
POST /api/agent
Unified endpoint for interacting with agents. All requests require session authentication. The userId is always bound to the authenticated session and cannot be overridden by the client.
GET actions
Pass the action query parameter to select the operation.
List endpoints
Returns available endpoints and version information when no action is specified.
{
"apiVersion": "1.0.0",
"agentbotVersion": "2026.3.1",
"endpoints": {
"GET /api/agent": "List endpoints",
"GET /api/agent?action=health": "Health status",
"GET /api/agent?action=sessions": "List sessions",
"GET /api/agent?action=session&sessionId=xxx": "Get session details",
"GET /api/agent?action=memory": "Get agent memory",
"GET /api/agent?action=skills": "List available skills",
"GET /api/agent?action=credentials": "List configured credentials",
"POST /api/agent": "Send message to agent",
"POST /api/agent?action=create-session": "Create new session",
"POST /api/agent?action=update-skill": "Enable/disable skill"
}
}
GET /api/agent?action=health
{
"status": "running",
"version": "2026.3.1",
"apiVersion": "1.0.0",
"uptime": 86400,
"model": "claude-sonnet-4-20250514",
"channels": ["telegram"],
"skills": [],
"lastSeen": 1710806400000
}
List sessions
GET /api/agent?action=sessions
{
"sessions": [
{
"id": "sess_abc123",
"status": "active",
"messageCount": 5,
"createdAt": 1710806400000,
"lastActivity": 1710810000000
}
]
}
Get session
GET /api/agent?action=session&sessionId=sess_abc123
Returns the full session including messages.
GET /api/agent?action=memory
Returns the last 10 messages from the active session (truncated to 100 characters each).
{
"memory": [
{ "role": "user", "content": "Hello, can you help me with..." },
{ "role": "assistant", "content": "Of course! Let me..." }
]
}
GET /api/agent?action=skills
Returns skills available on the agent instance.
Credentials
GET /api/agent?action=credentials
Returns which credentials are configured for the agent.
{
"credentials": {
"anthropic": false,
"openai": false,
"openrouter": true,
"google": false,
"telegram": true,
"discord": false,
"whatsapp": false
}
}
POST actions
Pass the action field in the request body.
| Field | Type | Required | Description |
|---|
action | string | No | Set to chat or omit (default action) |
message | string | Yes | Message to send to the agent |
sessionId | string | No | Session ID to continue. A new session is created if omitted and no active session exists. |
{
"sessionId": "sess_abc123",
"reply": "Agent is processing your request...",
"timestamp": 1710810000000
}
Create session
| Field | Type | Required | Description |
|---|
action | string | Yes | create-session |
{
"sessionId": "sess_abc123",
"status": "active"
}
Update skill
| Field | Type | Required | Description |
|---|
action | string | Yes | update-skill |
skillId | string | Yes | Skill ID to enable or disable |
enabled | boolean | No | Whether to enable or disable the skill. Defaults to false (removes the skill) when omitted. |
{
"success": true,
"skillId": "browser",
"enabled": true
}
Set credential
| Field | Type | Required | Description |
|---|
action | string | Yes | set-credential |
key | string | Yes | Credential key (for example, anthropic, telegram) |
value | string | No | Credential value. When omitted, the credential is marked as unconfigured. |
{
"success": true,
"key": "anthropic",
"configured": true
}
| Code | Description |
|---|
| 400 | Invalid action or missing required fields |
| 401 | Unauthorized |
| 404 | Session not found |
| 500 | Internal error |
Send message
Requires session authentication.
Request body
| Field | Type | Required | Description |
|---|
message | string | Yes | Message to send |
topic | string | No | Conversation topic |
{
"message": "Hello!",
"topic": "general"
}
Response
{
"id": "msg_123",
"message": "Hello!",
"topic": "general",
"status": "sent",
"timestamp": "2026-03-19T00:00:00Z",
"reply": "Hi! How can I help?"
}
| Code | Description |
|---|
| 400 | Message required |
| 401 | Unauthorized |
| 500 | Failed to send message |
List messages
Returns the message history. Requires session authentication.
Response
{
"messages": [],
"count": 0
}
| Code | Description |
|---|
| 401 | Unauthorized |