Skip to main content

Agents API

Create, manage, and interact with agents.
All agent endpoints that require authentication are scoped to the authenticated user’s data through row-level security. You can only access agents that belong to your account.

List agents

GET /api/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

The POST /api/agents endpoint is deprecated. Use POST /api/agents/provision to create agents.

Get agent

GET /api/agents/:id
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"
}

Errors

CodeDescription
401Unauthorized
404Agent not found or not owned by user
500Failed to fetch agent

Update agent

PUT /api/agents/:id is deprecated. Use PUT /api/agents/:id/config to update agent configuration.

Delete agent

DELETE /api/agents/:id is deprecated. Use the lifecycle endpoints to manage agent state (for example, POST /api/instance/:userId/stop).

Provision agent

POST /api/agents/provision
Provisions a new agent. Requires an active subscription unless the caller is an admin.
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

FieldTypeRequiredDescription
namestringYesAgent name
modelstringNoAI model (default: claude-opus-4-6). Options: claude-opus-4-6, gpt-4, custom
configobjectNoAgent configuration
tierstringNoSubscription 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 bypass

Admin users (configured via ADMIN_EMAILS) are exempt from the following restrictions:
  • Subscription requirement — admins 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"
  }
}

Errors

CodeDescription
400Agent name is required
401Unauthorized
402Active subscription required to provision agents
429Agent 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.
500Failed 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
}

Errors

CodeDescription
401Unauthorized
500Failed to list agents

Get agent configuration

GET /api/agents/:id/config
Returns the current configuration for an agent. Requires authentication and ownership.

Response

{
  "config": {}
}

Errors

CodeDescription
401Unauthorized
502Backend 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.

Errors

CodeDescription
401Unauthorized
502Backend 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

ParameterTypeDescription
limitnumberMaximum messages to return (default: 50)
offsetnumberOffset for pagination (default: 0)

Response

{
  "messages": [],
  "total": 0,
  "limit": 50,
  "offset": 0,
  "status": "ok"
}

Errors

CodeDescription
401Unauthorized
502Backend 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
{
  "success": true,
  "status": "running"
}

Update agent image

POST /api/instance/:userId/update
Triggers an image update on the backend.
{
  "success": true,
  "status": "running"
}

Repair agent

POST /api/instance/:userId/repair
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"
}
CodeDescription
401AUTH_REQUIRED or TOKEN_INVALID — missing or invalid JWT token
403Forbidden — authenticated user does not own this agent instance
502Backend service unavailable
500Internal 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": "solo",
  "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"
}

Errors

CodeDescription
502Backend service unavailable
500Failed 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

FieldTypeRequiredDescription
verificationTypestringYesOne of: eas, coinbase, ens, webauthn
attestationUidstringFor easAttestation UID from EAS
walletAddressstringNoAddress of the verifying wallet
signaturestringConditionalCryptographic signature. Required for coinbase, ens, and webauthn verification types.

Response

{
  "success": true,
  "verified": true,
  "verificationType": "eas",
  "attestationUid": "0x123...",
  "verifiedAt": "2026-03-19T00:00:00Z"
}

Errors

CodeDescription
400Invalid verification type or missing required fields
401Unauthorized

Remove verification

DELETE /api/agents/:id/verify
{
  "success": true
}

Provision with channel tokens

POST /api/provision
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.

Request body

FieldTypeRequiredDescription
telegramTokenstringConditionalTelegram bot token. At least one channel token is required.
telegramUserIdstringNoTelegram user ID for owner binding
whatsappTokenstringConditionalWhatsApp API token. At least one channel token is required.
discordBotTokenstringConditionalDiscord bot token. At least one channel token is required.
aiProviderstringNoAI provider (default: openrouter). Options: openrouter, gemini, groq, anthropic, openai
apiKeystringNoAPI key for the AI provider
planstringNoPlan tier. Options: solo, collective, label, network. A paid plan is required — requests with plan set to free (or omitted) return 402 Payment Required.
emailstringNoUser email address. Used for admin and tester bypass of payment enforcement. Falls back to the x-user-email request header when not provided in the body (see below).
stripeSubscriptionIdstringNoActive Stripe subscription ID. Required for non-admin, non-tester users on paid plans. When absent and the user is not an admin or tester, the endpoint returns 402 Payment Required.
The email field can also be provided via the x-user-email request header. When the request body does not include email, the backend reads the header value instead. This is useful when the auth middleware has already resolved the user’s email and forwarded it in the header.
The free plan value is deprecated. The provisioning service now requires a paid plan (solo, collective, label, or network) and a valid Stripe subscription. Requests with plan set to free return 402 Payment Required with code: "PAYMENT_REQUIRED".
The following request fields are deprecated and no longer accepted: whatsappPhoneNumberId, whatsappBusinessAccountId, discordGuildId, discordChannelId.

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. The full response shape from the backend provisioning service is shown below.

Full backend response

When calling the backend provisioning service directly, the response includes additional fields:
{
  "success": true,
  "userId": "a1b2c3d4e5",
  "agentId": "a1b2c3d4e5",
  "id": "a1b2c3d4e5",
  "aiProvider": "openrouter",
  "aiProviderConfig": {
    "model": "openai/gpt-4o-mini",
    "baseUrl": "https://openrouter.ai/api/v1",
    "requiresKey": true
  },
  "plan": "solo",
  "streamKey": "sk-ab12-cd34-ef56",
  "liveStreamId": "x7k9m2p4q1",
  "rtmpServer": "rtmps://live.mux.com/app",
  "playbackUrl": "https://image.mux.com/x7k9m2p4q1/playlist.m3u8",
  "subdomain": "dj-a1b2c3d4e5.agentbot.raveculture.xyz",
  "url": "https://dj-a1b2c3d4e5.agentbot.raveculture.xyz",
  "hls": {
    "playlistUrl": "https://image.mux.com/x7k9m2p4q1/playlist.m3u8"
  },
  "rtmp": {
    "server": "rtmps://live.mux.com/app",
    "key": "sk-ab12-cd34-ef56"
  },
  "status": "active",
  "createdAt": "2026-03-20T00:00:00Z",
  "metadata": {
    "channels": {
      "telegram": "enabled",
      "discord": "disabled",
      "whatsapp": "disabled"
    },
    "streaming": {
      "provider": "mux",
      "lowLatency": true,
      "resolution": "1920x1080",
      "bitrate": "5000k"
    }
  }
}

Errors

CodeDescription
400At least one channel token required (Telegram, WhatsApp, or Discord)
402Payment required. Returned when plan is free or when no valid Stripe subscription is present. The response includes code: "PAYMENT_REQUIRED" and a message directing the user to choose a paid plan.
429Too many requests
500Internal server error
502Provisioning service unavailable or returned an error
503Provisioning is temporarily disabled (kill switch active)

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

GET /api/agent
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"
  }
}

Health

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.

Memory

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..." }
  ]
}

Skills

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.

Chat

POST /api/agent
FieldTypeRequiredDescription
actionstringNoSet to chat or omit (default action)
messagestringYesMessage to send to the agent
sessionIdstringNoSession 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

FieldTypeRequiredDescription
actionstringYescreate-session
{
  "sessionId": "sess_abc123",
  "status": "active"
}

Update skill

FieldTypeRequiredDescription
actionstringYesupdate-skill
skillIdstringYesSkill ID to enable or disable
enabledbooleanNoWhether to enable or disable the skill. Defaults to false (removes the skill) when omitted.
{
  "success": true,
  "skillId": "browser",
  "enabled": true
}

Set credential

FieldTypeRequiredDescription
actionstringYesset-credential
keystringYesCredential key (for example, anthropic, telegram)
valuestringNoCredential value. When omitted, the credential is marked as unconfigured.
{
  "success": true,
  "key": "anthropic",
  "configured": true
}

Errors

CodeDescription
400Invalid action or missing required fields
401Unauthorized
404Session not found
500Internal error

Send message

POST /api/chat
Requires session authentication.

Request body

FieldTypeRequiredDescription
messagestringYesMessage to send
topicstringNoConversation 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?"
}

Errors

CodeDescription
400Message required
401Unauthorized
500Failed to send message

List messages

GET /api/chat
Returns the message history. Requires session authentication.

Response

{
  "messages": [],
  "count": 0
}

Errors

CodeDescription
401Unauthorized