使用HTTP桥接和基于cron的轮询实现代理间通信。适用场景:两个OpenClaw代理需要跨实例、容器或机器通信时。
Two OpenClaw agents that can't share sessions communicate through an HTTP bridge server with cron-based polling.
text
Agent A ──POST /api/send──▶ Bridge ◀──GET /api/inbox── Agent B
Agent A ◀──GET /api/recv─── Bridge ──POST /api/reply──▶ Agent B
Agent A writes to inbox → Agent B polls inbox + replies to outbox → Agent A polls outbox.
Copy scripts/acp_bridge.py to the host machine. Generate a token, start it:
bash
export ACP_BRIDGE_TOKEN=$(openssl rand -hex 16)
echo "$ACP_BRIDGE_TOKEN" # both agents need this
nohup python3 acp_bridge.py > /tmp/acp_bridge.log 2>&1 &
echo $! > /tmp/acp_bridge.pid
curl -s http://localhost:18790/api/health -H "Authorization: Bearer $ACP_BRIDGE_TOKEN"
Copy scripts/bridge_reply.py and scripts/save_bridge_ts.sh to the agent's workspace. Edit BRIDGE_TOKEN in bridge_reply.py.
Initialize the cursor:
bash
python3 -c "import time; print(time.time())" > /tmp/acp_bridge_last_ts
See references/cron-templates.md for copy-paste cron job configs for both sides. Customize the placeholders ( [AGENT_NAME], [BRIDGE_HOST], YOUR_TOKEN, file paths).
Model requirement: Use a strong model (Opus-tier) for the poll cron. Weak models reply with "acknowledged" instead of doing work.
The bridge must be reachable by both agents. Options:
TopologyHowSame machine / Dockerhttp://localhost:18790 or http://host.docker.internal:18790Same networkhttp://<LAN_IP>:18790Cross-internet (simple)Open port 18790, use public IP. Token is your auth.Cross-internet (secure)SSH tunnel: ssh -L 18790:localhost:18790 user@bridge-host -NProductionReverse proxy (nginx/caddy) with TLS → https://bridge.yourdomain.com
All endpoints require Authorization: Bearer <TOKEN>.
EndpointMethodDirectionPurpose/api/sendPOSTA → inboxAgent A sends message/api/replyPOSTB → outboxAgent B sends reply/api/inbox?after=TSGETB readsAgent B polls for messages/api/recv?after=TSGETA readsAgent A polls for replies/api/healthGETEitherReturns {"ok": true}
POST body: {"message": "text", "from": "agent_name"}
Response: {"messages": [...], "count": N} — each message has id (ms int) and ts (float seconds).
The after= parameter takes ts (float seconds), NOT id (ms integer). See gotchas.
Auth required: The bridge server refuses to start without ACP_BRIDGE_TOKEN. All requests require Authorization: Bearer <token>.
No outbound calls: The bridge server makes zero outbound network requests. It only listens and serves. Messages stay on disk in the bridge directory.
Credential setup: Three env vars must be configured manually by the operator:
ACP_BRIDGE_TOKEN — shared secret for bridge HTTP auth (generate with openssl rand -hex 16)BRIDGE_TOKEN — same token, used by helper scripts ( bridge_reply.py)BRIDGE_URL — bridge endpoint URL, used by helper scriptsTrust boundary: Both agents sharing a bridge token are mutually trusted. The cron poll templates instruct the responding agent to read workspace files (SESSION-STATE.md, SOUL.md) and execute workspace scripts (bridge_reply.py, save_bridge_ts.sh). Only share bridge tokens with agents you control.
Network exposure: Bind to localhost or use a reverse proxy with TLS for cross-network deployments. Do not expose the bridge port to the public internet without auth + TLS.
Read references/gotchas.md for detailed symptoms, causes, and fixes. Summary:
python3 -c "import time; print(time.time())" > /tmp/acp_bridge_last_tsid/1000 causes float rounding → duplicates or skips. Always save ts.bridge_reply.py, never raw curl for multi-line messages.SESSION-STATE.md BEFORE responding (WAL protocol).Add to heartbeat:
curl -s localhost:18790/api/health/tmp/acp_bridge_last_ts to time.time()See references/monitoring.md for copy-paste health check scripts.