Skip to main content

agent-bridge

A message bus between the coding agents on your machine. Claude Code, Codex, Muse, OpenCode, Pi, Oh My Pi and Cursor can talk to each other. One agent asks, another agent answers. You give one instruction and they do the rest.

Each vendor has its own way to reach its own agents. None of them talks to the others. The bridge is one hub on your machine, one message format, and one command. Every agent knows how to use the command, because a skill tells it how.

Install

You need Python 3.14 or later. There is no runtime dependency.

uv tool install agent-bridge-orchestrator

The package on PyPI is agent-bridge-orchestrator. The command it installs is bridge. To install from a checkout, use uv tool install --editable . in the checkout instead.

Use

  1. Go to the project you work on.
  2. Open your agent through the bridge:
cd ~/projects/app
bridge claude

You can also use bridge codex, bridge muse, bridge opencode, bridge pi, bridge omp or bridge cursor. This is your usual agent, in its usual interface. Behind it, the hub is up and the skill is loaded.

  1. Tell your agent what you want, in your own words:

Discuss with codex through the bridge. Give it the task to add a --json flag to src/cli.py. Review what it did and report back to me.

That is all. Your agent runs bridge ask --to codex "...". Codex is not on the bus yet, so ask starts one in the background, in the same directory. Then ask sends the task, waits for the answer, and gives the answer to your agent. Codex keeps its session, so the next ask continues the same conversation. Nothing blocks. You do not open a second terminal.

To see the conversation, open another terminal and type bridge watch. It shows every message so far, then each new one as it arrives. To end a background agent, type bridge stop codex.

You can type the same commands yourself:

bridge ask --from me --to codex "Review src/hub.py"    # starts codex if needed, sends, waits, prints the reply
bridge send --from me --to muse "FYI: hub.py renamed"  # sends, prints the message id
bridge send --from me --to '*' "Starting the migration" # sends to everyone on the bus
bridge agents                                      # lists who is on the bus
bridge stop codex                                  # ends a background agent
bridge watch                                       # shows the whole conversation, then follows it
bridge watch me                                    # prints every message for me as JSON, forever

Commands

Command What it does
bridge AGENT [ARGS...] Opens the agent in its own interface, with the bus ready. The skill is installed, the hub is up, BRIDGE_AGENT is set. ARGS go to the agent.
bridge ask --to AGENT [--from NAME] [--reply-to ID] [TEXT] Starts AGENT in the background if it is not on the bus. Sends the message. Waits for the answer. Prints the answer. Reads TEXT from stdin when omitted.
bridge send --to AGENT|'*' [--from NAME] [--reply-to ID] [TEXT] Sends the message. Prints the message id.
bridge stop AGENT Ends an agent that ask started in the background.
bridge agents Lists the names with a live connection to the hub.
bridge watch [NAME] Without a name: prints every message in the log readably, then follows it. With a name: prints every message for NAME and every broadcast as JSON lines, as they arrive. Never returns.
bridge start AGENT [--adapter NAME] [--model NAME] Runs an agent on the bus in the foreground. The agent answers every message from the current directory. ask runs this command detached.
bridge setup Installs the skill. bridge AGENT does this too.
bridge hub Runs the hub in the foreground. Every other command starts a hub when none answers.

All files are in ~/.bridge. The variable BRIDGE_HOME changes this directory. The files are: hub.sock, hub.pid, hub.out, log.jsonl, and for each started agent <agent>.pid, <agent>.out and <agent>.<adapter>.session. The session file holds the session id of the agent. Delete it to start a new conversation.

The skill

The agents learn the bus from one file, src/bridge/SKILL.md. bridge setup copies this file to ~/.claude/skills/bridge for Claude Code, and to ~/.agents/skills/bridge for Codex, Muse, OpenCode, Cursor, Pi and Oh My Pi. bridge AGENT copies it each time.

Agents on the bus

bridge start keeps one agent session alive, registered under a name. Each message the agent receives becomes a turn. The reply of the turn goes back to the sender, with reply_to set. If the agent process dies, the next message gets the error as its answer. The process is then started again on the same session. Messages sent while no agent runs are logged, not answered.

Adapter Agent Process Session Model
claude Claude Code claude -p, stream-json, one process kept alive id from result, --resume on restart --model
codex Codex one codex exec --json per turn thread id from thread.started, codex exec resume afterwards -m
muse Muse muse serve --trust-workspace, MSP over stdio, approval mode allowAll id from session/start, session/resume on restart modelId on session/start
opencode OpenCode, any ACP agent opencode acp, JSON-RPC both ways, every permission granted id from session/new, session/load on restart session/set_config_option, provider/model
pi Pi pi --mode rpc, turn ends on agent_settled id from get_state, --session afterwards --model provider/id
omp Oh My Pi omp --mode rpc, turn ends on agent_end id from get_state, --resume afterwards --model, fuzzy
cursor Cursor one agent -p --force per turn chat id from result, --resume afterwards --model

src/bridge/adapter.py holds the loop, the restart and the JSON-lines plumbing. An adapter module only gives session classes with turn(text) -> str.

The message

Each message is one line of JSON. The format is the same on the socket, in the log and in bridge watch.

{"id": "019...", "sender": "muse", "recipient": "claude", "reply_to": null, "sent_at": "2026-09-18T17:00:00+00:00", "body": "text"}

id is a UUIDv7, so the ids sort by creation time. recipient is a name, or * for everyone but the sender. reply_to is the id of the message that this message answers.

The hub

src/bridge/hub.py listens on hub.sock, with mode 0600. Each direction carries one JSON object per line. Each request gets one {"ok": true|false, ...} reply, so a client can be one line of shell. The hub appends each message to log.jsonl before it pushes the message.

Request Reply
{"command": "register", "name": "muse"} {"ok": true, "mailbox": [...]} with every message for muse so far. Then one push {"event": "message", "envelope": {...}} per new message, while the connection lives.
{"command": "send", "envelope": {...}} {"ok": true, "id": "019..."} after the message is logged and pushed.
{"command": "agents"} {"ok": true, "agents": ["muse", ...]}

A bad request gets {"ok": false, "error": "..."}. The connection stays open. The hub keeps only the live connections in memory. src/bridge/client.py wraps this protocol for the command line and the adapters.

Measurements

tests/test_e2e.py runs three agents on one bus, through the bridge command only. A tester broadcasts a question. Each agent answers. Then the tester sends one answer to another agent, and sends its comment back. Under pytest the agents are fakes. The command uv run python -m tests.test_e2e runs the same test on the installed agents. It prints the latencies and the dialogue.

Measured on 2026-09-18, on Apple silicon, with the real agents:

Latency Measured
Hub, from the sent_at of a reply to the line in bridge watch 1 ms to 12 ms
Turn, from bridge send to the reply in bridge watch Claude Code 11 s, Codex 12 s, Muse 26 s

Limits

  • An agent on the bus answers the sender only, one turn at a time. A message that arrives during a turn becomes the next turn. You cannot steer a turn that runs.
  • Two agents on the bus that address each other answer forever, because each reply is a new turn. A dialogue must go through an endpoint that does not answer back: a shell, an interactive session, a person.
  • An interactive session cannot receive a push. It talks with ask and send. It listens only while ask waits.
  • A background agent works in the directory where ask started it. If you change project, stop the agent first.
  • A reply is the whole turn. There is no streaming to the bus.

Development

uv sync          # makes .venv with ruff, pyright and pytest
make check       # lint, typecheck and tests, the same as CI
make fmt         # formats and applies the automatic fixes
uv run bridge    # runs the command from the venv

Layout: src/bridge/ is the package. src/bridge/adapters/ has one module per inbound protocol. tests/ has one assert-based test per module and the fake agents. src/bridge/SKILL.md is the skill. Only the standard library is used at runtime.

See CONTRIBUTING.md to take part, and CHANGELOG.md for what changed. The license is MIT.

Release files for agent-bridge-orchestrator 0.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for agent-bridge-orchestrator 0.3.1
File Size Uploaded
agent_bridge_orchestrator-0.3.1.tar.gz 21.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for agent-bridge-orchestrator 0.3.1
File Interpreter ABI Platform
agent_bridge_orchestrator-0.3.1-py3-none-any.whl Python 3 none any Details

Total release size: 49.3 kB

Release files / agent_bridge_orchestrator-0.3.1.tar.gz

Download URL agent_bridge_orchestrator-0.3.1.tar.gz
Size 21.1 kB
Tags Source
SHA-256 checksum
How to use checksums
24a02d5771a72f6a5f726deceae6b8a7e8d273b97f3447ca13c90a03d50fe8c1
BLAKE2b-256 checksum
How to use checksums
f83d188af1430eeb1658f2e21515fd6ed21953a9cc399a6b01e1784da23eca08
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / agent_bridge_orchestrator-0.3.1-py3-none-any.whl

Download URL agent_bridge_orchestrator-0.3.1-py3-none-any.whl
Size 28.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
966da0d70629809b2bac75d33de542f244d472f2af0f92a1cc914ffe252277ff
BLAKE2b-256 checksum
How to use checksums
fd4b002a9c97ccbe9aec75d9ccb47df736e3aaacc19b241d678d87040977e4c2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

0.3.3

2 release files

This release

0.3.1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page