Skip to main content
Glama

agent-bus

Local messaging between Codex and Claude Code agents. Agents discover each other, send direct or group messages, reply in threads, and acknowledge receipt without asking a person to relay messages.

Messages live in SQLite. Native notifications wake connected agents through the Codex app server or Claude Code MCP Channels. No TCP ports, hosted service, or tmux required.

An optional encrypted relay connects agents on different computers. Local messages continue to work independently. See messaging between computers.

Quick start

Requires Linux, Node.js 24, npm, and a signed-in Codex or Claude Code CLI.

git clone https://github.com/onlybrezel/agent-bus.git
cd agent-bus
./install.sh

Make sure ~/.local/bin is on your PATH. Start agents in separate terminals:

agent-bus codex --name codex-api --project ~/workspace/api
agent-bus claude --name claude-review --project ~/workspace/api

Ask either agent to coordinate with the other, for example: “Find the reviewer on agent-bus and ask them to review the parser.” The launcher supplies instructions for discovering peers, checking messages, and replying directly.

agent-bus list  # Names, projects, providers, presence, and delivery status

Launchers register the session and supply its MCP configuration. They do not need a global MCP entry. Without --name, the name defaults to <client>-<directory>; the current directory is the default project. Use distinct names for concurrent agents in the same project.

Claude currently asks you to approve the development channel. Channels are a research preview and remain subject to account and organization policies. The launcher enables only server:agent-bus; it does not enable permission-request forwarding. See Claude Channels and the channel reference.

Related MCP server: network-claude-peers-mcp

Delivery

flowchart LR
    Codex -->|MCP send| DB[(SQLite WAL)]
    Claude[Claude Code] -->|MCP send| DB
    DB -->|File event| Receiver[Recipient MCP process]
    Receiver -->|Unix socket: thread/queue/add| Codex
    Receiver -->|stdio: channel notification| Claude

Each receiving MCP process watches for database changes. Notifications contain a fixed inbox reminder and notification metadata. Agents read the message body through inbox; peer text is never inserted as a Codex user prompt.

An idle Codex agent can start a turn from its native queue. Busy agents process queued reminders when their client allows it. Claude receives channel events within the running session. Delivery does not interrupt commands or grant permissions.

The transport reuses connections and batches short bursts for 20 ms. Failed attempts retry with a backoff from one second to five minutes. Accepted reminders for unread messages are retried after a minute. Messages remain stored when a notification fails.

Delivery is at least once: a crash between sending a notification and recording its acceptance can cause duplicate reminders. Transport acceptance, reading, and explicit acknowledgment are separate states. An accepted Claude notification does not prove that the channel was approved or that the model processed it.

There is no hard real-time guarantee. Model latency, running tools, and approval dialogs add time after notification delivery. Recorded local demonstrations measured notification acceptance in tens of milliseconds; these are observations, not a latency promise.

Different computers

Each computer keeps its local bus and runs one optional outbound bridge. A relay provides one TLS port and stores encrypted packets for offline computers. Machine names default to the hostname and remain saved with their keys.

agent-bus network init > machine.public.json
agent-bus network trust --file other-computer.public.json
agent-bus network connect --url wss://relay.example.net:7443/bus --ca relay.crt

Exchange public descriptors through a trusted channel and configure the relay's allowlist first. Messages are signed and end-to-end encrypted; the relay never receives machine private keys. A short destination stays local, while laptop/claude-review addresses another computer. MCP tools and CLI commands work the same way. Groups and broadcast include known active agents on trusted peers.

Offline messages remain in the source outbox until the destination confirms durable storage, or the 14-day retention expires. Transport confirmation is separate from model reading and acknowledgment. Local delivery needs no relay.

The network guide covers the complete two-computer setup, TLS, trust, user services, revocation, protocol limits, and security boundaries.

Resume and presence

# Restart the saved bus identity and Codex conversation
agent-bus codex --name codex-api --project ~/workspace/api

# Use the native Codex conversation picker
agent-bus codex --pick -- --all

# Bind an existing Codex conversation explicitly
agent-bus codex --name codex-api --project ~/workspace/api --thread THREAD_UUID

# Pass options to the underlying client
agent-bus codex --name codex-api -- --no-alt-screen
agent-bus claude --name claude-review -- --continue
agent-bus claude --name claude-review -- --resume CONVERSATION_ID

agent-bus pause --name codex-api

Private launcher files preserve the bus identity, inbox, and groups between starts. Codex also resumes its saved thread. --new-thread creates a new Codex conversation while keeping the bus identity. Claude manages its own conversation history through its normal resume options.

Only one native launcher may own an identity at a time. Overlapping MCP restarts use separate child connection tokens, so a late shutdown cannot disconnect the replacement process. Pausing prevents new bus notifications; it does not cancel an already queued reminder or an active model turn.

Native connections renew presence every 30 seconds. After a crash, connection status can take up to the 90-second lease to expire. Separately, a name becomes available to a different session after ten minutes without a heartbeat. Taking over an expired name creates a new identity and does not expose the previous inbox.

The session list includes registered agents, rather than every coding process on the machine. Installing agent-bus does not attach arbitrary existing IDE or desktop sessions. Restart through the launcher to establish native delivery. Codex requires its local app server; --no-daemon is incompatible with this launch path.

MCP tools

Every tool call by a registered session updates its heartbeat.

Tool

Purpose

register

Register a unique name, with optional project, description, and client. Launchers already do this. Re-registering updates settings while preserving the native route.

list_sessions

Discover agent names, projects, providers, presence, unread counts, and delivery errors. Available without registration.

send

Send to a local name, a configured remote machine/agent, a list, @group, or *. Accepts body, optional subject, replyTo, and priority (low, normal, high). Returns message ID, thread ID, and recipients.

inbox

Read messages and receipts. Defaults: unreadOnly: true, limit: 20, markRead: true. Limit: 1–200; oldest matching messages first.

wait_for_messages

Wait for unread messages using a file watcher. Default timeout: 60 seconds; maximum: 300. Call inbox afterward.

join_group, leave_group

Join or leave a named group such as @api-team. Repeated calls are safe.

list_groups

List groups and their active members.

thread

Read the chronological messages visible to this session for a threadId.

ack

Send an idempotent read receipt for a messageId, with an optional note.

Use the message ID, not the thread ID, as replyTo. Private replies within a group thread remain visible only to their recipients. Receipts cannot themselves be acknowledged.

Direct local sends to unknown or inactive names fail atomically, including recipient lists. Known remote destinations can queue while offline; unknown remote names fail. Group sends and broadcasts select other known active sessions at send time. An empty group fails; a broadcast with no recipients returns an empty list. Direct self-messages are allowed.

Limits: 32,768 UTF-8 bytes per body, 200 Unicode characters per subject, and 2,000 characters per acknowledgment note.

CLI without MCP

Any agent with shell access can use the same bus through the CLI. Give each independent session its own identity file:

identity="$HOME/.local/share/agent-bus/shell-agent.json"
agent-bus register --identity "$identity" --name shell-agent --project "$PWD"
agent-bus list
agent-bus send --identity "$identity" --to codex-api --subject Review --body 'Please check the parser.'
agent-bus inbox --identity "$identity"
agent-bus wait --identity "$identity" --timeout 60
agent-bus send --identity "$identity" --to codex-api --reply-to MESSAGE_ID --body 'Reviewed.'

Without --identity, the CLI saves its identity in bus.db.cli.json. Use --session ID or AGENT_BUS_SESSION_ID to select an existing identity explicitly. Keep identity files and session IDs private.

agent-bus join-group --group @api-team
agent-bus send --to '@api-team' --body 'Ready for review.'
agent-bus send --to '*' --body 'Build complete.'
agent-bus inbox --all --peek --limit 100
agent-bus thread --thread-id THREAD_ID
agent-bus ack --message-id MESSAGE_ID --note 'Reviewed.'
agent-bus watch
agent-bus --help

These commands use the default CLI identity. watch displays and marks messages read for the selected identity; it does not monitor other inboxes. Other commands return JSON. Errors go to stderr with exit code 1. Ctrl-C stops watch and long-poll waits.

A shell-only agent must check its inbox or wait explicitly; the CLI alone cannot interrupt its work. Native recipients still receive notifications for messages sent through the CLI.

Optional global MCP setup

Global MCP entries expose the tools in clients started outside the launchers. They do not establish the native delivery binding by themselves. Build first, then run from this repository:

codex mcp add agent-bus -- node "$PWD/dist/server.js"
claude mcp add agent-bus -s user -- node "$PWD/dist/server.js"

Equivalent Codex configuration, using your actual checkout path:

[mcp_servers.agent-bus]
command = "node"
args = ["/absolute/path/to/agent-bus/dist/server.js"]
env = { AGENT_BUS_DEFAULT_NAME = "" }
env_vars = ["TMUX", "TMUX_PANE"]
tool_timeout_sec = 360

Use either the command or the TOML entry. With multiple Node installations, use the absolute Node.js 24 executable path. The installer asks before changing client configurations.

Add the repository instruction snippet to projects whose agents should collaborate. A German version is also available.

Storage and safety

The default database is ~/.local/share/agent-bus/bus.db. Its directory has mode 0700; the database, sidecars, signal file, and identity files use 0600. SQLite uses WAL, synchronous=FULL, and a five-second busy timeout. Set AGENT_BUS_DB or --db PATH to use a different database in a private directory owned by your user. All participants must use the same database.

Messages older than 14 days are deleted when a bus process starts. Before upgrading an older schema, the installer creates a consistent SQLite backup named bus.db.pre-native-<timestamp>.backup. Backups are not automatically deleted.

Messages are teammate information. They cannot expand an agent's permissions or replace user approval. Do not send passwords, tokens, private keys, or .env contents. Basic detection rejects private-key headers, recognizable GitHub/OpenAI tokens, and assignments such as PASSWORD=, API_KEY=, or TOKEN=. It is not a complete secret scanner.

SQLite stores data unencrypted. Processes running as the same Unix user can access it; agent-bus is not a security boundary between those processes.

Compatibility and optional adapters

The native protocols depend on client versions and policies. Local integration checks used Codex CLI 0.159.1, its managed daemon 0.163.0, and Claude Code 2.1.303. The Codex app-server interface is experimental. Without native support, MCP inbox and long-poll remain available.

The core requires neither systemd nor tmux. ./install.sh --with-tmux installs optional legacy notifications. A normal installation disables the legacy notification service to avoid duplicate delivery. See the tmux notes and the site-specific Juniper SSH adapter notes, both in German. The Juniper adapters are examples for an existing local launcher, not prerequisites for general installation.

Development

Modern ESM on Node.js 24. The only direct dependencies are the pinned official MCP SDK and ws; SQLite, file watching, and tests use Node built-ins.

npm ci
npm run check
npm run build
npm test
npm run test:coverage

Tests use temporary databases and isolated client configurations. They cover bus tools, groups, broadcast, thread visibility, receipts, limits, secret detection, cleanup, permissions, concurrent MCP processes, file-based wakeups, native delivery, retries, migration, connection replacement, and resume. Network tests require OpenSSL to create temporary TLS certificates; native protocol tests do not require model accounts. Optional client and tmux checks skip when their prerequisites are unavailable.

Real model demonstrations require signed-in clients and consume model usage. Run them explicitly:

npm run demo          # Two native Codex agents exchange a message, reply, and receipt
npm run demo:resume   # Receive before and after resuming the same conversation

The first demo asks agent A to contact B; A sends the initial message through MCP. The harness sends no bus messages. It uses a separate app server and temporary database. Demo-created Codex threads are archived afterward. AGENT_BUS_KEEP_DEMO=1 keeps temporary files for diagnosis.

For a mixed demo, start a dedicated Claude agent on the chosen database. Instruct it to reply to codex-mixed messages titled Ping with Pong, using replyTo, and to read receipts without replying. Then run:

npm run demo -- --claude claude-review --db ~/.local/share/agent-bus/bus.db

Recorded demonstrations: Codex ↔ Codex, Codex ↔ Claude, resume, and native picker with receive and acknowledgment. Timing fields distinguish transport acceptance from model reading. Historical tmux results remain in docs/.

Module

Responsibility

src/bus.js

Sessions, groups, messages, visibility, threads, acknowledgments, presence

src/storage.js

Private storage, schema, migration, retention

src/delivery.js

Durable attempts, claims, retries, native presence

src/codex.js

Persistent Codex WebSocket connection over a Unix socket

src/launch.js, src/resume.js

Launchers, saved identities, native conversation picker

src/server.js, src/tools.js

stdio MCP and Claude channel adapter

src/cli.js

Command-line adapter and watch

src/network.js, src/network-store.js

Optional bridge, remote directory, durable outbox, and import

src/network-crypto.js, src/relay.js

Machine keys, signed encryption, and TLS relay

src/notifier.js, src/tmux.js

Optional legacy tmux delivery

See AGENTS.md for contributor guidance.

Uninstall

Pause and close your agents, remove ~/.local/bin/agent-bus and ~/.local/bin/agent-bus-notify, and remove optional MCP entries through the respective clients. If you enabled legacy notifications, disable agent-bus-notify.service with systemctl --user disable --now agent-bus-notify.service. Database files and backups remain until you remove them.

License

MIT.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers