Quick setup
Add the bundled plugin to your OpenClaw configuration and define a separate bearer token for each trusted peer:A2A_HERMES_TOKEN to a strong, unique secret in the gateway environment, then restart the gateway. Use your externally reachable HTTPS origin as advertisedUrl when the gateway runs behind a reverse proxy. If omitted, the plugin derives the advertised origin from the incoming discovery request.
Discover the Agent Card
Fetch the public A2A Agent Card without authentication:channels.a2a.exposeAgents to an array of agent IDs to limit which agents appear. If unset or empty, all configured agents are advertised.
/.well-known/agent.json returns the same card for older A2A clients.
Send a task
Send an authenticatedSendMessage JSON-RPC request to /a2a/v1:
message.contextId on subsequent requests to continue the same conversation. Context IDs can contain letters, numbers, periods, underscores, colons, and hyphens, and must not exceed 128 characters.
To return immediately while the agent continues working, add "configuration": { "returnImmediately": true } alongside "message" in params. The task initially reports TASK_STATE_WORKING. Requests that exceed replyTimeoutMs also return the current working task instead of canceling it.
Older clients can use message/send as an alias for SendMessage.
Poll a task
Poll a task by sending its ID toGetTask:
TASK_STATE_WORKING to TASK_STATE_COMPLETED, TASK_STATE_FAILED, or TASK_STATE_REJECTED. Older clients can use tasks/get as a compatibility alias.
CancelTask is refused with JSON-RPC error -32004 rather than acknowledged. A dispatched agent run has no plugin-facing abort seam, so reporting TASK_STATE_CANCELED would tell the peer the work stopped while the run kept using tools. Refusing keeps the reported state honest.
Configure outbound peers
Add a peer URL when OpenClaw should send messages to another A2A agent. SetoutboundToken when the remote agent requires its own bearer token:
a2a:hermes. The plugin sends SendMessage directly to the configured URL without performing Agent Card discovery. Outbound messages reuse a stable conversation context per peer. A peer without a configured url cannot receive outbound messages.
Configuration reference
Peer names must begin with a lowercase letter or number and can also contain periods, underscores, and hyphens.
Session isolation
Each authenticated peer and A2AcontextId pair gets its own agent session. A2A pins the most
isolated direct-message scope rather than inheriting session.dmScope, so remote peer content never
joins the operator’s main session and one peer cannot read another peer’s conversation history.
Security
Agent Card discovery is intentionally public: anyone who can reach the gateway can read the instance description and exposed agent IDs. UseexposeAgents to limit disclosure, and expose the gateway through HTTPS when it is reachable over an untrusted network.
Every JSON-RPC request requires a configured peer bearer token; there is no unauthenticated mode. Each authenticated peer is also the sender identity used for normal OpenClaw channel ingress policy. Use different high-entropy tokens for each peer, keep tokens out of source control, and rotate tokens by updating the gateway environment and restarting.
A2A peers send tasks, not user commands. Messages beginning with / are rejected with TASK_STATE_REJECTED and an explanation. Command-like text inside an ordinary task stays literal; it cannot change session settings or resolve approvals. This also applies when the peer sets the protocol message role to ROLE_USER: that field does not authenticate a human user.
Ordinary tasks retain the tools and permissions of their routed agent. Work requiring approval still needs an authorized operator’s decision through a supported user channel or the Control UI. Existing integrations that sent slash commands over A2A must use plain-text tasks for agent work and an authorized user surface for commands; there is no peer command opt-in.
While an exec approval is pending, the original task stays working. After the operator decides, that same agent run receives the result and completes the task through its original reply path. An inbound peer does not need an outbound url to receive that completion through GetTask.
Requests are limited to 1 MiB, JSON-RPC batches to 30 entries, and serialized JSON-RPC responses to 1 MiB. Extracted message text is capped at 64 KiB and includes an explicit truncation marker when shortened. The default sliding-window limit is 30 requests per minute for each peer; schema-invalid requests count toward that limit. Set rateLimitPerMinute to 0 only on a separately protected network. Rate-limited requests return a JSON-RPC error while keeping HTTP status 200.
Outbound destinations come only from operator-configured peer URLs. Inbound callers cannot supply a proxy target or redirect OpenClaw to another destination.