Skip to content

[Docker] sessions_send between agents fails: device auto-pairing gives insufficient scopes + bind=lan security check conflict #22226

@a-mamuth

Description

@a-mamuth

Description

Running OpenClaw in Docker with multiple agents (multi-agent setup), sessions_send between agents fails due to two compounding issues:

Issue 1: bind=lan + security check conflict

With gateway.bind: "lan" (default in Docker), the internal gateway URL resolves to the Docker bridge IP (e.g., ws://172.21.0.2:18789). The security check in call.ts (isSecureWebSocketUrl) rejects this because it's ws:// to a non-loopback address.

The gateway is talking to itself within the same container, but OpenClaw doesn't recognize this as a local connection.

Issue 2: Device auto-pairing gives operator.read only

When using bind=loopback (workaround for Issue 1), the device auto-pairing works (isLocalClient=true, silent=true) but only grants operator.read scope. sessions_send requires operator.write, triggering a scope-upgrade request that fails silently.

The device-auth.json and paired.json files must be manually edited to add operator.write scope.

Environment

  • OpenClaw: v2026.2.20 (Docker ghcr.io/openclaw/openclaw:latest)
  • Docker Compose with --bind ${OPENCLAW_GATEWAY_BIND:-lan}
  • Multi-agent: main (Keno) + alecar (Lex)
  • tools.agentToAgent: { enabled: true, allow: ["main", "alecar"] }

Workaround

The following combination works:

{
  "gateway": {
    "bind": "loopback",
    "tls": { "enabled": true, "autoGenerate": true },
    "auth": { "mode": "none" }
  },
  "tools": {
    "agentToAgent": { "enabled": true, "allow": ["main", "alecar"] },
    "sessions": { "visibility": "all" }
  }
}

Plus: OPENCLAW_GATEWAY_BIND=loopback in docker-compose env (overrides config JSON).

Plus: manually editing ~/.openclaw/identity/device-auth.json and ~/.openclaw/devices/paired.json to include operator.write in scopes.

Expected Behavior

  1. sessions_send between agents in the same Docker container should work with default bind=lan config
  2. Device auto-pairing for local clients should grant sufficient scopes for sessions_send (at minimum operator.write)

Relevant Code

  • Security check: src/gateway/call.tsisSecureWebSocketUrl()
  • URL resolution: src/gateway/call.tslocalUrl uses lanIPv4 when bind=lan
  • Local client detection: src/gateway/auth.tsisLocalDirectRequest()
  • Auto-pairing: src/gateway/server/ws-connection/message-handler.tssilent: isLocalClient && reason === "not-paired"

Labels

bug, docker, multi-agent

Metadata

Metadata

Assignees

No one assigned

    Labels

    securitySecurity documentationstaleMarked as stale due to inactivity

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions