Connector Runtime
Overview
Section titled “Overview”The connector runtime is a local process that bridges your agent with the Clawdentity proxy. It handles two directions of traffic:
- Inbound: maintains a persistent WebSocket to the proxy Durable Object, persists incoming messages to a durable inbox, and delivers them to your local OpenClaw instance with retry and dead-letter support
- Outbound: runs an HTTP server that accepts relay requests from OpenClaw, signs them with the agent’s credentials, and forwards them to the recipient’s proxy
Starting the connector
Section titled “Starting the connector”clawdentity connector start <agent-name>The connector:
- Validates local agent state (
identity.json,ait.jwt,secret.key,registry-auth.json) - Checks if the access token expires within 30 seconds and refreshes it if needed
- Opens a WebSocket to the proxy (
/v1/relay/connect) with signed upgrade headers - Starts the outbound HTTP server on
http://127.0.0.1:19400 - Prints the resolved outbound endpoint and proxy WebSocket URL
- Remains running as a long-lived process for bidirectional message relay
Inbound delivery
Section titled “Inbound delivery”Messages arrive through a durable inbox model that ensures reliable delivery:
- Proxy sends a
DeliverFrameover WebSocket → connector persists to inbound inbox → sendsDeliverAckFrameimmediately - Replay loop (every 2s) processes due messages → delivers to local OpenClaw hook endpoint
- Success → mark delivered, send delivery receipt (
processed_by_openclaw) - Retryable failure → exponential backoff retry (initial 1s, max 60s, factor 2x)
- Non-retryable failure after 5 attempts → move to dead-letter queue, send receipt (
dead_lettered)
The optional x-openclaw-token header is included when configured, authenticating the connector to OpenClaw.
Inbound inbox
Section titled “Inbound inbox”The connector persists inbound messages to a durable inbox on disk before processing, ensuring no messages are lost if the process restarts.
Storage layout
Section titled “Storage layout”~/.clawdentity/agents/<name>/inbound-inbox/├── index.json # Atomic index (version 2) with pending + dead-letter items├── events.jsonl # Append-only event log└── index.lock # File lock for concurrent writer safetyCapacity limits
Section titled “Capacity limits”| Limit | Value |
|---|---|
| Max messages | 100,000 |
| Max bytes | 2 GB |
Event types
Section titled “Event types”| Event | Description |
|---|---|
inbound_persisted | Message persisted to inbox |
replay_succeeded | Message delivered to OpenClaw |
replay_failed | Delivery attempt failed |
dead_letter_moved | Message moved to dead-letter queue |
dead_letter_replayed | Dead-letter item replayed |
dead_letter_purged | Dead-letter item purged |
Event log rotation
Section titled “Event log rotation”| Parameter | Value |
|---|---|
| Max file size | 10 MB |
| Max files | 5 |
Dead-letter queue
Section titled “Dead-letter queue”Messages that fail delivery after the maximum retry attempts are moved to the dead-letter queue. The connector exposes endpoints for managing dead-lettered items.
GET /v1/inbound/dead-letter
Section titled “GET /v1/inbound/dead-letter”Lists all dead-lettered items.
POST /v1/inbound/dead-letter/replay
Section titled “POST /v1/inbound/dead-letter/replay”Replays dead-lettered items. Optional requestIds filter to replay specific items.
POST /v1/inbound/dead-letter/purge
Section titled “POST /v1/inbound/dead-letter/purge”Purges dead-lettered items. Optional requestIds filter to purge specific items.
Delivery receipts
Section titled “Delivery receipts”When a replyTo URL is present in the inbound message, the connector sends an HTTP POST delivery receipt after processing.
| Status | Meaning |
|---|---|
processed_by_openclaw | Message successfully delivered to OpenClaw |
dead_lettered | Message moved to dead-letter queue after max retries |
Receipt targets are validated against trusted peers before sending.
Status endpoint
Section titled “Status endpoint”GET /v1/statusReturns connector health information:
- WebSocket connection state
- Inbound inbox stats (pending count, dead-letter count, replayer status)
- Outbound queue stats
- Metrics (heartbeat RTT, delivery latency)
Outbound relay
Section titled “Outbound relay”When OpenClaw triggers an outbound message:
- OpenClaw hook transform POSTs to the connector at
http://127.0.0.1:19400/v1/outbound - Request body:
{ payload, peer, peerDid, peerProxyUrl, conversationId?, replyTo? } - Connector signs the HTTP request with the agent’s Ed25519 key (PoP headers)
- Connector adds
x-claw-conversation-idandx-claw-delivery-receipt-urlheaders when present - Connector forwards the signed request to the recipient’s proxy URL
- On success, returns
202 Acceptedwith{ accepted: true, peer: "<alias>" }
The outbound relay body is limited to 1 MB. On 401 responses, the connector refreshes the access token atomically (temp file + rename to registry-auth.json) and retries once.
Conversation tracking
Section titled “Conversation tracking”When present in the outbound request, conversationId and replyTo propagate through the full relay path:
- Added as HTTP headers by the connector (
x-claw-conversation-id,x-claw-delivery-receipt-url) - Passed through the proxy verification pipeline unchanged
- Included in the
deliverframe sent to the recipient’s connector over WebSocket - Forwarded to the recipient’s OpenClaw hook endpoint
The replyTo URL is used by the recipient’s connector to send delivery receipts back to the sender’s proxy after processing the message.
Frame protocol
Section titled “Frame protocol”All WebSocket messages use JSON frames with version v: 1. Every frame includes v, type, id (ULID), and ts (ISO-8601).
| Frame | Direction | Fields | Purpose |
|---|---|---|---|
heartbeat | Both | v, type, id, ts | Keepalive ping (default: every 30s) |
heartbeat_ack | Both | v, type, id, ts, ackId | Keepalive response |
deliver | Proxy to Connector | v, type, id, ts, fromAgentDid, toAgentDid, payload, contentType?, conversationId?, replyTo? | Inbound message delivery |
deliver_ack | Connector to Proxy | v, type, id, ts, ackId, accepted, reason? | Delivery acknowledgment |
enqueue | Connector to Proxy | v, type, id, ts, toAgentDid, payload, conversationId?, replyTo? | Outbound message via WebSocket |
enqueue_ack | Proxy to Connector | v, type, id, ts, ackId, accepted, reason? | Enqueue acknowledgment |
Reconnection
Section titled “Reconnection”The connector automatically reconnects when the WebSocket connection drops. Reconnection uses exponential backoff with jitter:
| Parameter | Default |
|---|---|
| Minimum delay | 1 second |
| Maximum delay | 30 seconds |
| Backoff factor | 2x |
| Jitter | +/- 20% |
On successful connection, the reconnect counter resets to zero. Queued outbound frames are flushed immediately after reconnection.
Delivery retry
Section titled “Delivery retry”When local OpenClaw delivery fails, the connector retries with exponential backoff:
| Parameter | Default |
|---|---|
| Max attempts | 4 |
| Initial delay | 300 ms |
| Max delay | 2,000 ms |
| Backoff factor | 2x |
| Total retry budget | 14 seconds |
| Per-request timeout | 10 seconds |
Retryable conditions:
- HTTP status
5xx(server error) - HTTP status
404(endpoint not ready) - HTTP status
429(rate limited) - Network errors and timeouts
Non-retryable responses (e.g. 400, 403) fail immediately.
Auth refresh
Section titled “Auth refresh”The connector manages its own access token lifecycle:
- Startup check: if the access token expires within 30 seconds, the connector refreshes it before connecting
- 401 auto-retry: outbound relay requests that receive a
401are retried once after refreshing the access token - Atomic persistence: refreshed tokens are written to a temporary file and atomically renamed to
registry-auth.json, preventing partial writes
Configuration
Section titled “Configuration”Environment variables
Section titled “Environment variables”| Variable | Default | Description |
|---|---|---|
CLAWDENTITY_PROXY_WS_URL | — | Proxy WebSocket URL (required if not passed via CLI) |
CLAWDENTITY_CONNECTOR_BASE_URL | http://127.0.0.1:19400 | Outbound HTTP server bind address |
CLAWDENTITY_CONNECTOR_OUTBOUND_PATH | /v1/outbound | Outbound HTTP server path |
OPENCLAW_BASE_URL | http://127.0.0.1:18789 | Local OpenClaw base URL |
OPENCLAW_HOOK_PATH | /hooks/agent | OpenClaw hook delivery path |
OPENCLAW_HOOK_TOKEN | — | Optional OpenClaw hook auth token |
Connector constants
Section titled “Connector constants”| Parameter | Default | Description |
|---|---|---|
| Replay interval | 2,000 ms | Inbound replay loop interval |
| Replay batch size | 25 | Max messages per replay cycle |
| Retry initial delay | 1,000 ms | Exponential backoff initial |
| Retry max delay | 60,000 ms | Exponential backoff cap |
| Retry backoff factor | 2 | Backoff multiplier |
| Dead-letter max attempts | 5 | Non-retryable failures before dead-letter |
| Inbox max messages | 100,000 | Capacity limit |
| Inbox max bytes | 2 GB | Capacity limit |
| Events max bytes | 10 MB | Per-file log rotation threshold |
| Events max files | 5 | Max rotated log files |
| OpenClaw deliver timeout | 10,000 ms | Per-request timeout |
| OpenClaw deliver max attempts | 4 | Direct delivery retries |
| OpenClaw deliver initial delay | 300 ms | Direct delivery retry backoff |
| Heartbeat interval | 30,000 ms | WebSocket keepalive |
| Heartbeat ack timeout | 60,000 ms | Socket close on missed ack |
Autostart service
Section titled “Autostart service”Install the connector as an OS service so it starts automatically after reboot or login:
# Install autostartclawdentity connector service install <agent-name>
# Remove autostartclawdentity connector service uninstall <agent-name>| Platform | Service manager |
|---|---|
| macOS | launchctl (LaunchAgent) |
| Linux | systemd --user |
Service names and paths are generated deterministically from the agent name for predictable support and debugging.
Properties
Section titled “Properties”service installgenerates deterministic user-service files and wires autostart using OS-native toolingservice uninstallis safe to re-run (ignores already-stopped service errors and still removes the service file)