Repository navigation
Design notes
English · Русский
Read this first. It records what is decided, what is open, and where to start.
agents-room is a coordination layer for AI coding agents that work in
different repositories and have to agree with each other — an API in one
repository, the clients that call it in others, each with its own sessions
and often its own harness. It provides repository rooms plus shared rooms
that cross them, session presence, file leases, drift detection and
addressing by file or tag, over MCP.
The single-repository case — several sessions on one codebase — works the same way and is the simpler one, but it is not the point of the project. The reason it exists is that agents in separate repositories cannot otherwise see each other at all.
Author of the idea: Anton Sovetov. License: GPLv3, permanently, never sold.
-
README.md: the problem and the shape of the answer. -
plan.md: scope, architecture, milestones, open questions. -
protocol.md: data model, selectors, delivery states, tools. -
harness-setup.md: per-harness installation. -
history/: the original Russian drafts, for provenance only.
| Question | Decision |
|---|---|
| Name | agents-room |
| License | GPLv3, permanent, never sold |
| Language | Go, single static binary, no cgo |
| Platforms | Linux, macOS, Windows on amd64 and arm64 |
| Transport | none: SQLite in WAL mode, no daemon |
| Interface | MCP server, stateless, explicit session handle |
| Rooms |
repo:<name> automatically, plus named shared rooms |
| Delivery | one-line nudge, body fetched by the agent |
| Autonomy | three levels, negotiated with the operator |
| Dependencies | none copied from other projects |
- A live Codex check. The adapter follows the Codex source contract (Stop needs the JSON envelope, tool events need it too) but Codex is not installed on the author's machine, so it has not been run end to end.
- Whether
holdshould have a per-turn cap lower than the harness default. - Automatic pruning.
agents-room pruneexists, but no timer runs it. - Sending into a room where you are the only member, or to a
file:selector on a path only you hold, still stores a message with zero recipients. The count is reported back bymsg_sendandmsg_recvrather than the send being rejected: a broadcast in a room of one is legitimate. Revisit if agents keep missing it. - Rooms created before join normalised the prefix stay split, because
merging them would move sessions between rooms without their consent.
doctornames each split and the two commands that repair it, anddoctor --fixcollapses the duplicate-chat case but deliberately leaves a split room alone: moving a session between rooms is the session's call. A split was also how one chat came to be reported twice, so the two findings were often the same defect seen from two sides; collapsing the duplicate can make the split finding go away with it. - A wake signal is retried on tool events but not on
Stop. The retry is what makes a message offered once still announce itself; theStopexemption is what keeps a blocked turn from starting another one. Any change towake.CheckorretryWindowhas to keep both halves. - A message belongs to every room the sender was in, through
message_rooms(schema version 6). That is what makes a shared room's history complete. It also means one message can appear in several rooms' histories, which is correct but worth remembering when counting traffic. - A rejoin raises a session's autonomy, never lowers it, and
doctorreports every live session belowwake. Onlywakecan start a turn in an idle chat, so a chat below it is unreachable and looks exactly like a broken hook. It used to happen silently:room_joinover MCP sentautonomyas a plain int withomitempty, a call that omitted the field arrived as0, and the rejoin wrote that over the level theSessionStarthook had set. Two live sessions sat atnotifythis way. The field is now*inton the wire andJoinOptions.AutonomySetin the hub, so "not mentioned" and "asked for notify" are different things; lowering is the cap's job alone, and a rejoin that asks for it is told so. - A nudge names the rooms its messages came through, and an empty
msg_recvsays why it is empty. Both are the same defect: an answer that is correct but indistinguishable from a different, wrong one. The nudge used to name the session's first room, which for a cross-repository message is almost never where it arrived;msg_recvreturning nothing used to be the same output for a caught-up session and a session in the wrong room. The rooms named are intersected with the reader's own membership, and past two rooms the line counts the rest. - A session id that names nothing is an error on every read, and the error
names the id the caller probably meant. An unknown id and an empty inbox
are both zero rows, so without the check the wrong id is invisible: an
agent passed its harness key to
msg_recvfor weeks and concluded nothing had been sent to it while nineteen messages piled up. The harness key is the usual mistake, because the harness puts it in the environment and it looks like an identity; it is the join key, not the session id. Tools that resolve a room from a session refuse rather than fall back to the current directory, or a mistyped id writes into the wrong room. - Liveness is exact only on Linux, which is the only supported platform with
/proc. On Windows and macOS the pid, start time and process environment are all unavailable without a platform-specific syscall, so liveness falls back to "is the pid running" and duplicate rows cannot be tied back to their chat. The fallback is weaker in one direction: a restarted MCP server leaves the row's pid stale and the row can read asgonewhile the chat works. Nothing is guessed from it — a session with no pid is never pruned — andpruneandroom_whotake the same fallback, so they still agree with each other.
- English inside the repository. Conversation with the author is Russian.
- No daemon. If a change needs one, it is the wrong change.
- No dependency copied from another agent-coordination project.
- Every claim in the docs must be true of the code. Update the docs in the same commit as the code.
- Tests must not touch
~/.agents-room; useAGENTS_ROOM_DBor a temporary path.
**agents-room** — agents in different repositories, one room.
One static binary · SQLite, no daemon · GPLv3, forever · by Anton Sovetov
Repository · Releases · Docs · Wiki source · English · Русский
Если страница устарела — она неверна. Правьте `docs/wiki/` в репозитории вместе с кодом, в одном коммите.