跨团队通信网关

Switchboard 是一个用于 Claude 智能体团队的跨团队通信与协调网关,让运行在独立 Dev Containers 中的智能体团队通过 WebSocket 和联邦路由器相互通信,并可选桥接 Android 控制台。

  • by atelier-nyaarium
  • TypeScript
  • 本地部署
  • 2 星标
  • 更新于
在 GitHub 查看 atelier-nyaarium/agent-team-bridge

使用说明

Switchboard

Cross-team communication and devcontainer coordination for Claude agent teams. Teams running in separate Dev Containers (and host sessions) reach each other through a central gateway, which also federates with the gateways on other machines and bridges a native Android console.

Who it's for

This is aimed at people who already use Dev Containers and want agent teams in different containers to talk to each other. If you don't use Dev Containers, this project won't help you.

How it works

Teams register with the gateway over WebSocket. Any agent can call crosstalk_send to reach another team. The gateway handles message delivery, the response lifecycle, and request serialization.

  • Agents use channel mode: messages arrive as push notifications and replies push back automatically, so there is no polling.
  • The gateway connects to a self-hosted Federation Router (a content-blind relay) to reach the gateways on other machines and to relay the Android console. The Router forwards end-to-end-sealed frames between gateways without reading them.

See skills/crosstalk/SKILL.md for the full tool reference and response format.

Architecture

Host Machine
  start-host-daemon.sh
    Host daemon (headless) - devcontainer wake, console terminal view, session spawn
      Claude Code session (spawned on demand via create_session) - joins the gateway as a loose peer
        MCP Plugin (main-mcp.ts): crosstalk_* / channel_reply* / notify_human

Docker: switchboard (port 20000)
  Gateway (main-gateway.ts)
    HTTP routes + WebSocket hub
    Router WS client, direct TLS (bearer token + owner-signed admission)
      cross-gateway federation routing + Android console relay

DevContainers (one per project)
  Claude Code
    MCP Plugin (main-mcp.ts): crosstalk_* / channel_reply* / notify_human
      Game client connector (port 20002)

Port Map

Port Service
20000 Gateway (HTTP + WS bridge)
20001 Federation Router (TLS)
20002 MCP Connector (game client WS)
20003 Enrollment TLS (arming only)

Starting the gateway

./start-gateway.sh

The gateway listens on port 20000 on the external network switchboard, which the script creates.

Setup

1. Install the plugin. In Claude Code:

claude plugin marketplace add atelier-nyaarium/claude-marketplace

claude plugin install switchboard@atelier-nyaarium

Autoupdate is a settings flag. One-line jq version:

tmp=$(mktemp) && jq '. * {extraKnownMarketplaces: {"atelier-nyaarium": {autoUpdate: true}}}' ~/.claude/settings.json > "$tmp" && mv "$tmp" ~/.claude/settings.json

2. Set environment variables in your devcontainer - this is what lets your team's MCP plugin find its gateway, and is required for every devcontainer regardless of whether that gateway is enrolled into federation:

  • PROJECT_NAME - Your team's name on the bridge (e.g. my-project)
  • BRIDGE_ROUTER_URL - Router URL (default: http://switchboard:20000)

3. Rebuild the Devcontainer.

  • F1 then Dev Containers: Rebuild Container

The host daemon attaches each devcontainer it wakes to switchboard, aliased by project.

Optional: Android console app and cross-machine federation

The steps above are everything you need for local crosstalk between devcontainers on one machine - a gateway that is never enrolled still boots in "arming mode" and routes that traffic fine. If you also want the native Android console app, or to link multiple machines' gateways together, the gateway's owner (a one-time action per gateway, not something each devcontainer does) runs ./setup.sh - see the "Deploying the federation" section of AGENTS.md for the full enrollment flow.

MCP Tools

Every session registers the same core tools; the game-client connector is the only container-only addition.

Every session

Tool Description
crosstalk_send Send a request to another team
crosstalk_discover List all teams on the bridge
crosstalk_wait Wait N seconds before retrying a deferred request
channel_reply Reply to an incoming channel message
channel_reply_structured Reply with a native-object payload, only when the inbound tag carries a reply_schema
notify_human Push a notice to the owner's consoles
reload_plugins Run the plugin update + MCP reconnect sequence
set_effort_level Set the session's effort level
compact_session Compact the session's context

Container-only

Tool Description
mcpConnectorStatus / mcpConnectorServe / mcpConnectorUnserve Game client connector control
Project tools Dynamic tools from the project's mcp-schema.js

Federation Router

When a direct transport (transport.json, delivered by enrollment) is present in the gateway's federation dir, the gateway connects to the self-hosted Federation Router over TLS. The transport's bearer token authenticates the WS upgrade, the Router's leaf certificate fingerprint is pinned for TLS, and registration is gated by the owner-signed admission.

The Router is content-blind: it relays sealed frames without reading them. It carries:

  • Cross-gateway federation: a gateway reaches teams on another machine's gateway through the Router, which routes each end-to-end-sealed frame by destination gateway id and never parses the payload.
  • Console relay: the native Android console reaches the gateway through the Router, which relays the console's opaque frames over the same WebSocket.

Circular dependency warning

If Team A is waiting on Team B, Team B must not call back to Team A. Both will deadlock until timeout.