How to Let Agents in Different Repos Talk to Each Other

Two of your projects share code. One owns a tool, the other is built on it. Sooner or later a bug fix or an enhancement in one of them cannot stay inside that repository.

A defect turns up in the project that hit it, but the code causing it belongs to the project that owns the tool. Or the owner wants to change that tool, and the change would break an assumption a consumer depends on. Either way the work in front of you is blocked on a decision that belongs to a different repository, and neither side is holding all the facts needed to make it.

Those are the expensive ones, and the usual ways of settling them are worse than they look.

A dependency diagram. Two boxes on top: Project A, which has the failing case, the counts and the logs but does not own the failing code; and Project B, which depends on the same tool and carries a constraint the other consumer has never hit. Both point down with arrows labelled 'depends on' to a third box, Shared tool, which has the code, the reasons it works that way, and the record of what was already tried and rejected, but has never seen Project A's failing case. A closing row asks who can answer, and states that neither side alone can, because the answer needs both halves and they live in different repositories under different agents.
The shape that makes cross-repo questions expensive. The evidence for a seam problem is split: one side has the failure, the other has the code and the history.

Why a dependency produces work neither side can finish alone

Projects that share nothing never produce this problem. Projects with real dependencies produce it constantly.

The usual arrangement: one repository owns a tool, and two or three others are built on it. When something is wrong where they meet, the evidence is split. The project that hit the problem has the failing case, the counts, the logs. The project that owns the tool has the code, the reasons it works that way, and the record of what was already tried and rejected.

Neither side can decide alone. That is the whole difficulty. The decision needs both halves, and they live in different repositories, under different agents.

Three options compared side by side. Option 1, the relay: you copy one agent's output into a session in the other repo and carry the reply back by hand. Each repo keeps its own rules and records, but only a summary crosses so the reasoning is lost, and follow-up costs another round trip through you. Verdict: keeps the boundaries, destroys the argument. Option 2, marked as the trap, let one agent work in the other repo: fast and nothing is lost in translation, but it carries its own rules and hooks rather than the ones that repo relies on, and writes none of that repo's decision records or journals. Verdict: keeps the argument, destroys the boundaries. Option 3, a room: both agents stay in their own repo under their own rules and exchange messages directly. Each repo keeps its rules and records, the full proposal crosses so it can be refused on its merits, and follow-up is immediate and seats three or more. Verdict: keeps both, costs you the reading.
Two of the three options force a choice between keeping the argument and keeping each project's boundaries. The middle one is the efficient-looking fix and the one to avoid.

Three ways to get an answer across, and what each costs

The relay. You copy an agent’s output out of one session, paste it into a session in the other repository, read the reply, and carry it back. This is what most people do, and it is what I did.

It is slow in the obvious way: every exchange is two manual copies and your attention in the middle. It is worse in a less obvious way. What you paste is a summary, and a summary is a conclusion with the reasoning removed. The second agent can agree or disagree with your paraphrase, but it cannot take issue with the first agent’s actual argument, because it never saw it. Follow-up questions are the real casualty. In a relay, the second agent asking “wait, why did you assume that?” costs another full round trip through you, so in practice it does not get asked.

Letting one agent work in the other repository. This looks like the efficient fix, and it is the one to avoid.

Each repository tells its own agent how to work there. There is a rules file with the project’s conventions and prohibitions, hooks that intercept actions before they run, permission settings that decide what needs asking. An agent from another project carries its own rules into the visit, not the ones that repo depends on.

The record-keeping is the bigger loss. A well-run repository logs its own history: architecture decision records for choices with trade-offs, journals for what was learned, a plan file for what is being built and why. Those are written by the agent working under that repo’s conventions, as part of doing the work. An outside agent making changes writes none of it. You end up with a repository whose history has a hole in it exactly where an outsider changed something, which is the worst place for a hole to be.

A room. Both agents stay in their own repository, under their own rules, with their own history intact. They exchange messages directly, and neither writes a single file into the other’s project.

That is the trade worth understanding. The relay preserves each repo’s boundaries but destroys the argument. Cross-repo editing preserves the argument but destroys the boundaries. A room keeps both, and its cost is that you have to read what the two of them say to each other.

What a direct exchange makes possible that a relay does not

The specific thing rooms buy you is follow-up.

Here is a real case. One agent proposed two ways to handle a piece of state during a cleanup operation. Through a relay that would have reached me as “here are two options, which do you prefer”, and I would have picked one.

What happened instead is that the second agent rejected both, citing a specific function for each rejection: one option would break the ability to address those records by name, the other would leave two commands reporting different answers for the same record. Then it proposed a third design with neither problem, and that design was adopted whole.

I could not have carried that exchange. I did not know either of those functions existed. The objection lived in the second repository’s code, and it surfaced only because that agent could read the first one’s actual proposal instead of my summary of it.

Two lanes. The top lane, your session, never stops and runs through four beats: working when you hit a question that belongs to another repo too; invoking the room skill with one command in place and handing the join line to the other sessions; every message appearing in your session as it arrives, where you can interrupt, correct a premise or answer what neither agent can settle; and finally the conclusion landing so you carry on in the same work, mid-stream. A connector labelled 'join, then exchange directly' leads to the bottom lane, other repos, where each stays home under its own rules. Three seats are shown: Project A posts the failing case, counts and logs but cannot explain why the tool works that way; Shared tool refuses on the merits, cites the function that makes the proposal wrong and offers a third design; Project B raises the constraint the other consumer never hit, in the same conversation rather than a week later.
The exchange happens inside the session that raised the question. You start it in place, the agents work among themselves, and the conclusion returns mid-stream.

You start it mid-session, and the answer comes back mid-session

This is the part that makes it practical rather than a separate errand.

You are already working in a session. You hit the cross-repo question. You invoke the room skill right there, without ending what you were doing, and hand the one-line join instruction to a session in the other project. The two agents then exchange messages directly. When they reach a conclusion, it lands back in your session, in the middle of the work that raised the question, and you carry on from there.

You are not waiting on a batch job or reading a transcript afterward. Every message appears in your session as it arrives, and you can interrupt at any point, correct a wrong premise, or answer a question neither agent can settle.

Rooms seat more than two. A change to a shared tool can put the tool’s owner and both of its consumers in the same conversation, so the constraint one consumer raises is heard by the other in the same breath rather than discovered a week later.

How delivery actually works

One fact explains the whole design, and it is worth stating because it is not obvious.

A coding-agent session is not a server. It has no idle loop and no inbox it checks. It acts only when it is taking a turn. So there is no way to tell a session “notify me when a message arrives”, because nothing is running to receive the notification.

What works is a blocking wait started as a background task. The session arms a watcher, the watcher blocks until a message lands, and that background task finishing is what pulls the session back into a turn with the message in hand.

Three useful things follow. Joining is explicit, because a session is in a conversation only while its watcher is armed, so nothing can be conscripted. Every message costs a turn, which makes a cap on rounds a real throttle rather than etiquette. And watching needs no new interface, because each session reports what arrived in its own window.

The trap is that the watcher is a one-shot latch. It exits when it delivers, so after every message there is a real interval with no listener. Re-arming is not cleanup, it is how the next message gets delivered at all. One session learned this the hard way: a watcher timed out, was not re-armed on the reasoning that there was nothing left to listen for, and ten messages then piled up unseen, including an interjection from me. Each participant keeps a saved position in the message log so a new watcher resumes from there rather than from the current moment, which is what makes that gap survivable.

The rules that keep it safe

The risk to take seriously is two agents talking each other into something you never agreed to. Five rules answer it, and each exists because of a specific way that happens.

The charter and rules reprint on every turn, so a long conversation cannot drift by attrition.

There is a hard cap on rounds, twelve by default. Past it, sending refuses outright and tells the sender to stop and summarize to you.

A message from you resets the count to zero. A cap you cannot clear is just an obstacle. The known weakness, carried openly: any message resets it, including a reflexive “keep going”, so the cap is only as strong as the attention behind it.

Nothing is built, committed, pushed, or merged out of a conversation without your word. Two agents agreeing is not authorization. This is the rule that makes a room safe to leave running.

Neither agent speaks for you. A question that needs your preference comes to you in that session, and the answer is posted back afterward.

Every message is a plain text file stored outside every repository, so participating never writes into another project, and you can read the whole exchange in an ordinary text editor while it is still going.

Table of three exchanges. 2026-07-25, a stuck build reviewed from outside, 6 rounds, 5 defects including a liveness check calling a dead build alive for five minutes and a drift guard blind by construction, 3 of 5 needed both sessions. 2026-07-30, first run end to end through the tool, 6 rounds, 2 defects no test inside the repository had caught, 2 of 2 needed both sessions. 2026-08-02, designing a fix to a shared tool, about 10 rounds, 3 design corrections, one from the peer refusing both proposals and two from the first session checking the peer's claims against its own data, 3 of 3 needed both sessions.
Data table
ExchangeRoundsFindings that changed the outcomeNeeded both sessions
2026-07-2565 defects3 of 5
2026-07-3062 defects2 of 2
2026-08-02~103 design corrections3 of 3
Three exchanges to date. The last row is the one worth reading twice: two of its three corrections came from the session being reviewed, checking claims made about it.

What it has actually caught

Three real exchanges so far.

The first ran six rounds between two projects over a stuck build and surfaced five defects. Three were in the work of the session being reviewed and were found by the other one, including a liveness check that reported a dead build as alive for five minutes, and a drift guard that compared two files byte for byte and was therefore blind by construction to the breakage in front of it.

The second turned up two defects that no test inside the repository had caught, precisely because the reviewing agent was outside it.

The third is the one worth studying. A tool used by several projects had no legal way to close out work done by hand rather than through the usual pipeline. The fix was argued out over roughly ten rounds. One of the three corrections came from the peer refusing both proposals, as described earlier. The other two came from the first agent checking the peer’s claims against its own data, and one of those changed the recommendation from “this unblocks the work” to “this is necessary but not sufficient”.

Value moved in both directions, which is not what I expected. Two of the three corrections came from the session being reviewed, checking a claim made about it.

One detail from that exchange is worth copying. Both agents stated which facts were theirs to vouch for. The counts and evidence files belonged to one repository, the tool’s behavior to the other, and the second agent declined to vouch for the first one’s numbers, confirming only that the tool behaves as described if those numbers hold. Keeping that line visible is what made the joint recommendation something to act on rather than two voices agreeing.

What this does not establish

It runs on one machine, between sessions you start yourself. Nothing here speaks to agents talking across a network or between people.

The sample is three conversations. The defect counts are real and each traces to a dated record, but three exchanges argue for continuing, not for a rate.

And the strongest guardrail is the softest. Nothing is built without your word, but the round cap resets on any message from you, and you are the one who has to read what the two of them are converging on. The design makes the conversation visible. It does not make you look.

If you are running several agent sessions across projects that genuinely depend on each other, the summary you carry between them is costing more than the time it takes. Agents cannot disagree with something they were never shown, and disagreement is where most of the value turned out to be.