A2A Server — Inbound Task Listener
Run an A2A protocol listener that allows this OpenClaw instance to receive tasks routed from the A2A API Gateway. The listener runs as a background HTTP service.
Sidecar Principle
This skill is strictly an OpenClaw sidecar — it receives tasks FROM the A2A API Gateway in whatever format the gateway sends them. The gateway's A2A protocol is the contract; OpenClaw's listener just speaks it. Never assume what the sending system looks like — it could be any agent that routes tasks through the gateway. The listener implements the gateway's expected endpoints as-is.
Configuration
The listener reads configuration from a shared a2a.conf file (located in the a2a-client skill directory), with auto-detection fallbacks for local settings.
Priority order: CLI flags → env vars → a2a.conf → auto-detected defaults
| Setting | Auto-detected Default | Description |
|---|---|---|
| Port | 8100 | Listen port (LISTENER_PORT) |
| Bind Address | Tailscale IP or first NIC | Local bind address (BIND_ADDR) |
| Agent Slug | hostname -s (lowercase) | Agent identifier (AGENT_SLUG) |
| Agent Name | Slug (capitalized) | Display name (AGENT_NAME) |
| Agent URL | http://{bind_addr}:{port} | Agent endpoint (AGENT_URL) |
| Capabilities | chat,code,research | Comma-separated (AGENT_CAPABILITIES) |
| Auth Type | bearer | Auth method (AGENT_AUTH_TYPE) |
| API Key | empty | Bearer token — if empty, auth checks are disabled (A2A_GATEWAY_API_KEY) |
Run a2a-register/a2a-setup.sh to configure interactively, or set env vars / create a2a-client/a2a.conf.
When to Use
- Start the listener — When this OpenClaw instance needs to receive inbound A2A tasks
- Stop the listener — When shutting down or pausing inbound task reception
- Check listener status — When verifying the A2A service is running
Endpoints
The listener (a2a-listener.py) handles these routes:
| Method | Path | Description |
|---|---|---|
GET | /health | Health check — returns {"status": "ok", "agent": "<slug>"} |
GET | /v1/a2a/agents/{slug} | Returns the agent card for this OpenClaw instance |
POST | /v1/a2a/tasks/send | Receives an inbound A2A task (requires Bearer auth if API key is set) |
Auth
Inbound tasks (POST /v1/a2a/tasks/send) require a Bearer token matching the configured A2A_GATEWAY_API_KEY. If no API key is configured, auth checks are disabled (with a warning at startup). Health checks and agent card lookups are unauthenticated.
Tools
start.sh — Start the Listener
./start.sh [--port PORT] [--bind ADDR]
Starts the A2A listener in the background. All other settings are read from a2a.conf or env vars.
# Start with defaults (from a2a.conf or auto-detected)
./start.sh
# Custom port and bind address
./start.sh --port 8200 --bind 0.0.0.0
Saves the PID to a2a-listener.pid for management. Logs to a2a-listener.log.
stop.sh — Stop the Listener
./stop.sh
Gracefully stops the A2A listener using the PID file.
a2a-listener.py — The Listener Process
Python HTTP server that implements the A2A protocol endpoints. Started by start.sh. Can also be run directly:
# Run directly (foreground)
python3 a2a-listener.py
# With custom settings via env vars
LISTENER_PORT=8200 BIND_ADDR=0.0.0.0 A2A_GATEWAY_API_KEY=your-key python3 a2a-listener.py
All configuration is loaded from a2a.conf, env vars, or auto-detected — no hardcoded values.
⚠️ Current Status — Mock Responses
The listener currently returns mock responses for inbound tasks. It acknowledges receipt and echoes back the task content, but does not yet process tasks through OpenClaw's agent runtime.
Next step: Integrate the listener with OpenClaw's task processing pipeline so inbound A2A tasks are dispatched to the appropriate skill/agent, and real results are returned.
Typical Workflow
- Configure → Run
a2a-register/a2a-setup.shor createa2a.conf - Register → Use the
a2a-registerskill to register this instance in the A2A API Gateway - Start →
./start.shto begin listening for inbound tasks - Verify →
curl http://YOUR_IP:8100/healthto confirm it's running - Receive — The gateway routes tasks to this listener automatically
- Stop →
./stop.shwhen done