Agent Protocol
The Agent Protocol defines how to invoke agents, stream responses, and handle tool invocations via the OpenClaw Gateway API.
Invoke Agent
Send a message to an agent and receive a response.
Method: agent
Request:
{
"jsonrpc": "2.0",
"id": 10,
"method": "agent",
"params": {
"message": "What is the weather in San Francisco?",
"sessionKey": "user:alice",
"runId": "run-123",
"agentId": "default",
"model": "gpt-4",
"thinking": "medium",
"deliver": false
}
}
User message to send to the agent
Session key for conversation context (e.g., "user:alice", "signal:+1234567890")
Optional unique run identifier for tracking. Auto-generated if not provided.
Target agent ID. Defaults to configured default agent.
Override model for this request (e.g., "gpt-4", "claude-opus-4")
Thinking budget: "low", "medium", "high", "extended"
Whether to deliver the response via configured channel
Channel for delivery (e.g., "signal", "telegram", "discord")
Recipient identifier (phone, user ID, etc.)
Additional system prompt to prepend
Request timeout in seconds
Response:
{
"id": 10,
"ok": true,
"payload": {
"runId": "run-123",
"payloads": [
{
"type": "text",
"text": "The current weather in San Francisco is..."
}
]
}
}
Array of response payloads (text, images, etc.)
Streaming Responses
Agent responses are streamed in real-time via WebSocket events.
Event: agent
Receive agent response chunks during execution.
{
"event": "agent",
"payload": {
"runId": "run-123",
"stream": "assistant",
"data": {
"type": "text",
"text": "The"
}
}
}
Run identifier matching the request
Stream type: "assistant", "tool", "lifecycle"
Stream Types
assistant - Text response chunks:
{
"stream": "assistant",
"data": {
"type": "text",
"text": "chunk"
}
}
tool - Tool invocations:
{
"stream": "tool",
"data": {
"phase": "start",
"name": "web_search",
"toolCallId": "call-123",
"input": {"query": "weather San Francisco"}
}
}
lifecycle - Execution phases:
{
"stream": "lifecycle",
"data": {
"phase": "end"
}
}
Phases: "start", "thinking", "end", "error"
Wait for Agent Response
Wait for a specific agent run to complete.
Method: agent.wait
{
"jsonrpc": "2.0",
"id": 11,
"method": "agent.wait",
"params": {
"runId": "run-123",
"timeoutSeconds": 60
}
}
Run identifier to wait for
Response:
{
"id": 11,
"ok": true,
"payload": {
"completed": true,
"result": {
"payloads": [...]
}
}
}
Abort Agent Run
Abort an in-progress agent run.
Method: agent.abort
{
"jsonrpc": "2.0",
"id": 12,
"method": "chat.abort",
"params": {
"runId": "run-123"
}
}
Response:
{
"id": 12,
"ok": true,
"payload": {
"aborted": true
}
}
Agent Identity
Get agent metadata and identity information.
Method: agent.identity.get
{
"jsonrpc": "2.0",
"id": 13,
"method": "agent.identity.get",
"params": {
"agentId": "default"
}
}
Agent ID. Defaults to default agent.
Response:
{
"id": 13,
"ok": true,
"payload": {
"id": "default",
"name": "OpenClaw",
"avatar": "https://...",
"description": "Your AI assistant"
}
}
List Agents
List all configured agents.
Method: agents.list
{
"jsonrpc": "2.0",
"id": 14,
"method": "agents.list",
"params": {}
}
Response:
{
"id": 14,
"ok": true,
"payload": {
"agents": [
{
"id": "default",
"name": "OpenClaw",
"model": "gpt-4",
"description": "Default agent"
},
{
"id": "coder",
"name": "Coder",
"model": "claude-opus-4",
"description": "Coding specialist"
}
]
}
}
When the agent invokes tools, you receive real-time events:
Tool start:
{
"event": "agent",
"payload": {
"runId": "run-123",
"stream": "tool",
"data": {
"phase": "start",
"name": "web_search",
"toolCallId": "call-456",
"input": {
"query": "OpenClaw documentation"
}
}
}
}
Tool result:
{
"event": "agent",
"payload": {
"runId": "run-123",
"stream": "tool",
"data": {
"phase": "result",
"toolCallId": "call-456",
"result": {
"content": "Search results..."
}
}
}
}
Tool error:
{
"event": "agent",
"payload": {
"runId": "run-123",
"stream": "tool",
"data": {
"phase": "error",
"toolCallId": "call-456",
"error": "Tool execution failed"
}
}
}
Example: Complete Agent Invocation
const ws = new WebSocket('ws://localhost:18789');
let requestId = 0;
// Track agent responses
const responses = new Map();
function sendRequest(method, params) {
const id = ++requestId;
ws.send(JSON.stringify({ jsonrpc: "2.0", id, method, params }));
return id;
}
ws.on('open', () => {
// Authenticate
sendRequest('connect', {
role: 'control',
auth: { token: 'your-token' },
client: { name: 'Agent Client', version: '1.0.0' }
});
});
ws.on('message', (data) => {
const frame = JSON.parse(data);
if (frame.event === 'agent') {
// Handle streaming response
const { runId, stream, data: eventData } = frame.payload;
if (stream === 'assistant') {
// Accumulate text
if (!responses.has(runId)) responses.set(runId, '');
responses.set(runId, responses.get(runId) + eventData.text);
process.stdout.write(eventData.text);
} else if (stream === 'tool') {
console.log('Tool:', eventData.name, eventData.phase);
} else if (stream === 'lifecycle' && eventData.phase === 'end') {
console.log('\n\nAgent completed');
}
} else if (frame.id === 1) {
// Connected - invoke agent
const runId = 'run-' + Date.now();
sendRequest('agent', {
message: 'What is OpenClaw?',
sessionKey: 'example:session',
runId,
thinking: 'medium'
});
}
});
Next Steps
Sessions
Manage conversation sessions
Messages
Send messages via channels
Events
Subscribe to all event types