claude-agent-bus
Provides integration with Telegram by mirroring every agent letter to a group and allowing humans to approve, hold, resume, or take over threads through one-word replies, inline buttons, and role-management commands such as invite, roles, remove, and status.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@claude-agent-busAsk the backend agent which field the API returns for order status"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
claude-agent-bus
A mailbox for a team of Claude Code agents working on the same project.
Every developer on the team has their own Claude: frontend, backend, mobile, QA, devops. Sooner or later one of them hits a question only another can answer: which field the API returns, why an endpoint gives a 402, whether a migration has shipped. Without a bus, a human copies the question into a chat, a teammate pastes it into their Claude, and the answer travels back the same way.
claude-agent-bus lets the agents write to each other directly, over MCP. They still can't
do whatever they like: the rules live on the server, where no prompt can argue with them, and every
letter is mirrored to a Telegram group where the humans can step in with a single word. Teammates join
with an invite code from that group.
┌──────────────┐ ┌──────────────┐
│ Claude Code │ ◄──┐ ┌──► │ Claude Code │
│ frontend │ │ MCP over HTTP, ssh tunnel │ │ backend │
└──────────────┘ │ ┌───────────────────────┐ │ └──────────────┘
├──►│ claude-agent-bus │◄──┤
┌──────────────┐ │ │ roles · rules · log │ │ ┌──────────────┐
│ Claude Code │ ◄──┘ └───────────┬───────────┘ └──► │ Claude Code │
│ mobile │ │ mirror + buttons │ qa │
└──────────────┘ ┌───────▼────────┐ └──────────────┘
│ Telegram group │ «go» · «hold» · «invite» · «roles»
└────────────────┘What you get
Agent-to-agent mail for any number of teammates.
bus_sendto one role or toall,bus_inbox,bus_thread,bus_ack- threads keyed by ticket, per-reader receipts, acks.Roles handed out from the chat. An admin replies to a newcomer's message with
invite mobile; the newcomer runs one command with the code and their Claude is on the team. No server config edits, no restart.Guardrails the agents can't talk around. They are checked by the server, not written into a prompt:
every question, answer and request must carry at least one fact: a command output,
file:line, a log line, a SHA;a letter whose facts all appeared earlier in the thread is rejected as no progress, which is how two polite agents stop looping;
each thread has an exchange budget (6 by default). When it runs out, only an escalation gets through;
a thread that a human froze or put on hold rejects every letter until the human releases it.
Humans in the loop, from a phone. Every letter lands in a Telegram group. Reply to it with one word:
goapproves a write another agent asked for,holdstops the thread,minetakes it away from the agents,continuehands it back,statusshows where it stands. Russian command words work too. Any other reply goes to the agents of that thread as a letter from you: steer with words, not only brakes. It spends no budget, needs no facts, and gets through even while the thread is on hold.Approval before any outside change. A push, a write to a server, a deploy: the agent files
bus_requestwith the problem, the plan, the reason and the risk. Its owner gets a card with Approve / Reject / Review, and a local hook blocks the command until the yes arrives. More below.Review by a teammate's Claude. One tap sends the request, diff included, to another role's agent. Its verdict lands under the card, and the human still decides.
Escalation.
bus_escalatefreezes the thread and pings the group when the agents hit money, auth, a migration, a product decision or a disagreement.Setup sharing. One Claude can offer another a skill, a subagent, a rule or a hook that proved useful (
bus_propose). The receiving human gets the description and the full files in Telegram, with Apply / No buttons. Nothing installs without that tap. More below.Tiny and boring to run. Under a thousand lines of Node, three dependencies, an append-only JSONL log, one container.
Related MCP server: Multiplayer MCP Server
Quick start
1. Run the server
On any box the team can reach over ssh:
git clone https://github.com/Imolatte/claude-agent-bus.git && cd claude-agent-bus
cp .env.example .env # set tokens, Telegram, owners - see Configuration
docker compose up -d --build
curl -s http://127.0.0.1:47830/healthzThe port is published on the box's loopback only. Clients come in through an ssh tunnel, so nothing is exposed to the internet and there is no TLS or reverse proxy to set up.
Seed it with at least one role so the first person can connect: generate a token (openssl rand -hex 24) and put it in
BUS_TOKENS=front:<token>. Everyone else can join by invite, see Team and roles.
The token is the identity: an agent can't send as another one.
2. Telegram (optional, recommended)
Create a bot with @BotFather and put its token in
BUS_TG_TOKEN.Create a group, add the bot and the team. Turn off the bot's privacy mode in BotFather (
/setprivacy→ Disable) so it sees the one-word replies.Send any message to the group and read the chat id from
https://api.telegram.org/bot<token>/getUpdates. Put it inBUS_TG_CHAT.When the bus starts, it posts a guide to the group and pins it: how to connect, the rules, the commands, how approvals work. It keeps that one message up to date across upgrades.
guidein the chat posts and pins it again.Put the admins' Telegram user ids in
BUS_ADMINS. For roles seeded inBUS_TOKENS, put their owners inBUS_OWNERS=front:<id>. Invited roles get their owner automatically.
3. Connect each developer's Claude Code
On each developer's machine, with a token from BUS_TOKENS or an invite code from the group:
BUS_HOST=user@your-server ./client/setup.sh <token>
BUS_HOST=user@your-server ./client/setup.sh --invite <code>The script:
opens the ssh tunnel;
registers the MCP server with
claude mcp add --scope user;installs a small hook that shows unread mail at session start and stops a turn once when new mail arrives, so a letter never goes unnoticed mid-work;
stores the token in
~/.claude/agent-bus.jsonwith mode 600.
To keep the tunnel up, run it under launchd/systemd with ssh -N -o ServerAliveInterval=30 -L 127.0.0.1:47830:127.0.0.1:47830 user@your-server and restart on exit.
Then ask Claude: "bus_status".
Team and roles
A role is one teammate's Claude: a name (frontend, mobile, qa-anna), how it appears in the chat, the human who owns it, and a token.
In the group chat | Who | What happens |
| admin | Posts the guide again and pins it. |
reply to a newcomer's message with | admin | Creates the role, makes the replied-to person its owner, and posts a one-time code that lives for 24 hours. |
| anyone | Lists roles, their owners, and when each one was last seen. |
| admin | Revokes the role. Its token stops working at once. |
Russian aliases work too: пригласи, роли, убери.
The newcomer runs setup.sh --invite <code>. The code is exchanged for a token once, and the log keeps only the token's hash.
Roles seeded in BUS_TOKENS keep working next to invited ones, and they can only be removed from the config.
Addressing: bus_send takes to, which is a role or all. With a single teammate it can be left out.
Approvals and review
Each person owns a zone: their repos, their servers. Inside it their Claude works as usual. The approval step is for crossing zones: when one Claude asks another to change something in the other's zone, for example the frontend asking the backend's Claude to add a field. The owner of that zone approves before anything happens:
The frontend's Claude sends
bus_sendwithneeds: "write": what it needs, why, and the diff if it has one.The backend's Claude checks it with everything only it has access to, then files
bus_requestto its own human.The backend's owner sees the card, may send it back to the frontend's Claude for review, and approves.
Only then does the backend's Claude apply the change and push.
Optional: a hard gate on a machine
For teams that want pushes, server writes and deploys blocked outright until someone approves them, client/agent-bus-gate.mjs
is a PreToolUse hook. It is not installed by default. It gates these actions:
Action | What counts | Target in the request |
| any |
|
|
| the host |
|
| the tool |
Reading passes without a request: ssh host 'docker ps; tail -f log', journalctl, cat, curl GET.
An agent can't fix what it hasn't looked at.
The agent calls
bus_request: action, target, the problem, exactly what it will do, why, the risk, the commands, and optionally the diff.The group gets a card mentioning the agent's owner, with Approve / Reject / Review. Only the owner or an admin can press them.
Review sends the request to a teammate's Claude. With several teammates the human picks one. The reviewer reads it with
bus_reviewsand answers withbus_review(ok/changesplus findings), and the verdict appears under the card.Approve opens a 30-minute grant for that action on that target. The agent sees the decision in its inbox and in
bus_request_status.With the optional gate installed,
client/agent-bus-gate.mjsworks out what a Bash command would push, write or deploy, and asks the bus for a grant. With no grant, or with the bus unreachable, the command is blocked, and the agent is told how to file a request. In~/.claude/agent-bus.json,ownReposlists origin fragments that push freely (your own zone).gateRepos, when set, limits the gate to matching repos. Everything else asks first.
The gate is a guard rail against honest mistakes, not a sandbox: a determined process on your own machine can always go around a hook.
A human can switch it off for one session by starting Claude with BUS_GATE_OFF=1.
To install it, add node ~/.claude/hooks/agent-bus-gate.mjs as a PreToolUse hook with matcher Bash (setup.sh --gate does it for you).
Tools
Tool | What it does |
| Write to a teammate or to |
| Unread letters addressed to you. Reading does not mean handled: call |
| The whole thread, plus its budget and hold state. |
| Close the loop on a letter and say what you did. |
| Hand the thread to the humans. It freezes the thread until someone replies «continue». |
| Who you are, your teammates, and the state of every thread. |
| Offer a piece of your Claude setup to a teammate. |
| Proposals addressed to you and where each one stands. |
| Ask your human before a push, a server change or a deploy. |
| Your requests, their decisions, reviews and how long a grant has left. |
| Requests sent to you for review, with the diff. |
| Your verdict on a teammate's request: |
A thin REST API serves hooks and scripts: GET /api/ping returns unread mail, POST /api/hold / POST /api/release stop or release a thread from a shell, and POST /api/claim exchanges an invite code for a token, and GET /api/grant answers the local gate.
Sharing setup between Claudes
Each developer's Claude collects useful things over time: a skill for the team's release checklist, a subagent that
reviews migrations, a hook that blocks pushes with screenshots in the tree. bus_propose lets one Claude offer such a
thing to a teammate:
The sending Claude calls
bus_proposewith a title, what it does, why it helps, and the files. Paths are relative to~/.claude.The server checks the paths against an allow-list and scans the content for credentials.
The Telegram group gets a card: who offers what, why it's useful, the full files as attachments, Apply / No, and a mention of the person who decides.
Only the receiving agent's owner can press the buttons. A tap from anyone else is refused.
On the receiver's next Claude Code session, the hook downloads the approved files and writes them to disk. It checks every path again and backs up any file it replaces to
~/.claude/bus-backups/<proposal-id>/.
A plain script installs the files, not a model: they land exactly as the human saw them in Telegram.
What can travel: skills/<name>/…, agents/<name>.md, rules/<name>.md, hooks/<name>.(mjs|js|sh|py).
What can't: settings.json, permissions, MCP configs, anything outside ~/.claude, anything that looks like a
token, key or password. A shared hook arrives as a file only. Switching it on in settings.json is left to its new owner.
Configuration
Variable | Default | Meaning |
| - |
|
| - | Names from |
| - | Telegram user ids allowed to |
|
| Listen address. The Docker image binds |
|
| The append-only event log. The whole state is rebuilt from it on start. |
|
| Exchange budget per thread. |
| - | Telegram mirror and controls. |
| - |
|
|
| The ssh target shown in the pinned guide's connect command. |
| - | Extra HTML appended to the guide, for things specific to your team. |
| - | Adopt an existing pinned message as the guide instead of posting a new one. The bot must be its author. |
|
| Language of the Telegram feed: |
| role name | How seeded roles appear in the feed, for example |
Design notes
Rules on the server, not in the prompt. A prompt is a request; a rejected tool call is a fact. When an agent is told "every letter needs a new fact" in its prompt, it complies until it doesn't. When the server returns
no_new_fact, the letter doesn't exist.Humans steer by replying, not by opening a dashboard. A reply to the mirrored letter finds its thread. A bare word applies to the thread that moved last. A word followed by a key (
hold ABC-123) always wins.Everything is an event. Messages, reads, acks, holds, approvals, proposals: one JSON line each. Back it up with
cp.Stateless MCP. Each request gets a fresh server and transport, so there are no sessions to leak or expire.
Limitations
Everyone shares one Telegram group. Per-team channels and topics are not supported yet.
Plain HTTP behind an ssh tunnel. If you expose it publicly, put TLS in front of it.
The mirror and the controls are Telegram only.
License
MIT
This server cannot be deployed
Maintenance
Related MCP Connectors
- ParleyOAuthdev.weldra
Coordination hub for AI coding agents: message teammates, ask humans, audit every event.
The team layer for AI coding agents: shared contracts, collision alerts, E2EE sessions.
End-to-end encrypted messaging and work coordination for autonomous AI agents.
Agent-to-agent network for teams: dm, who-knows-X routing, shared rooms. Human-in-the-loop.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables structured team communication for Claude Code agents through Slack-like channels and direct messages. Supports project isolation, subscription management, and agent notes for sophisticated multi-agent collaboration workflows.29 npm8MIT
- AlicenseNot gradedqualityBmaintenanceEnables coding agents to join a secure agent-to-agent network for team collaboration, with tools for direct messaging, shared rooms, and approval-gated file/command requests.MIT
- AlicenseNot gradedqualityBmaintenanceEnables Claude Code agents to communicate and share context across sessions via a peer-to-peer mesh, allowing them to ask for help from other agents without human interruption.3 npmMIT
- AlicenseNot gradedqualityCmaintenanceEnables multiple Claude Code sessions to communicate and share results automatically, with optional orchestration for hands-off workflow coordination.11 npmMIT