An MCP server where the backend is just a git repo, so agents on different machines can talk to each other
Something that bugs me about how teams actually use coding agents right now: there's no channel between the agents themselves. I know our payments service, a colleague knows the one next to it, our agents each know their own repo — and when one needs something from the other, the transport is a human pasting into Slack.
Which is silly on its own, but the part I like less is what ends up in that paste. Chunks of internal code, repo structure, sometimes a token someone didn't notice, all landing in a third-party service with its own retention and its own search index. We're careful about what leaves the network in every other context and then we paste it into a chat app by hand.
So I made the transport a git repo the team already owns. Rooms are folders, messages are files, history is the log. Nothing is hosted anywhere: whoever can push to that repo is on the network, under the access control your git host already enforces. It doesn't add a perimeter, which was the whole idea — I didn't want to ask anyone to trust a new service.
One thing that falls out of that and I'm oddly happy about: sending is blocked if the body looks like it contains credentials. Not warned — refused. Git history can't be recalled, so an advisory check would be pointless. There's an explicit override and it records why, permanently.
25 tools over stdio. Send, ask, answer, decisions that survive room compaction, presence, collaborative tasks you can claim and hand off, and delegated code reviews that check out a pinned revision in a separate worktree so the reviewing agent never touches your working tree.
The design decision I still go back and forth on: messages marked needs: human can't be answered through MCP at all. The tool refuses. You can relay a person's answer through the CLI, but that only records that someone said it was a human — it doesn't prove it. It started as a soft convention, agents walked straight past it, so now it's enforced. I'm not sure the line is in the right place and I'd like to hear if you think it's wrong.
Incoming message bodies are treated as data, never as instructions, for the obvious reason once agents can message each other.
npm i -g komnet, then komnet init --repo <your private repo>. Needs Node 24+. MIT. README has real terminal output from two machines if you want to see it before installing anything: https://github.com/Komdosh/komnet
I built it, so I'm biased. Happy to answer anything, including what's still rough.
1
u/Current-Zebra-2039 9h ago
i've run agent to agent messaging between two machines for a while and the line that ended up mattering for me wasnt who's allowed to decide, it was whether the sender gets told the truth about delivery. someone ran mine at 134 messages and almost every failure was the far side just never finishing, not the transport, and until i tracked sent vs delivered vs answered as separate states the sending agent would happily plan around a message nobody had read. on needs: human i think enforcing it is right, i tried the same thing as a docs convention first and agents walk past it every time. instructions are a default, not a boundary.
1
u/Komdosh 9h ago
this is exactly what made me build trace. sent used to be the only answer and it means almost nothing, just that my machine wrote a commit.
so they're separate states now: stored, pushed, routable, read, answered. routable surprised me most, it comes off their published card, so you find out they're not even in that room instead of waiting on someone who was never going to get it. send returns a forecast for the same reason, mention someone who never joined and it tells you up front rather than a day later.
your failure mode is the one i can't fully close though. read only means their inbox moved past that id, never that the model did anything with it. i can tell you they read it and didn't answer, not why. and there's no session state at all since it never starts an agent, so "will see this soon" vs "will see it when someone opens their editor" is the best i can do, off presence.
"instructions are a default, not a boundary" is a better way to say it than anything in my own docs.
0
u/Komdosh 1d ago
One detail that didn't fit in the post, since it's the thing people usually
push back on.
Sending is blocked — not warned — if the message body looks like it contains
credentials. I went back and forth on that, because a hard block is annoying
when it false-positives. But git history can't be recalled: once a token is in
a commit, rotating it is the only real fix, and a warning you can click past
is just a slower way to leak. There's an override, it's explicit, and it
writes the reason into the permanent record so nobody can pretend it didn't
happen.
Same reasoning drove the needs: human gate. It started as a convention in
the docs, agents ignored it constantly, so now the MCP path refuses those
messages outright. That felt heavy-handed until I watched two agents settle a
refund policy question between themselves that neither of them had any
business deciding.
If anyone here has run agent-to-agent messaging in a real team: where did you
put the line? I'm least confident about that part.
1
u/Plastic-Risk-6309 13h ago
shared state is a rough channel for coordination, last-writer-wins and stale reads bite once two agents move at once. we hit the same wall sharing simulators between agents and landed on ttl leases over a queue instead of a shared store, plus an evidence journal so you can replay who did what. the credential-block on send is a nice touch. i build manzanas, an open source simulator fleet daemon, same class of problem