GitHub Issues Is a Bad Message Bus, and That's the Point
I run a control plane and a handful of coding agents, and they have to coordinate. The channel I use for that is GitHub Issues, the same tracker you file bugs in.
It clicked for me while I was explaining message buses to a class. I had been chewing on this coordination problem for weeks, and standing at the board it landed: the issue tracker I was already using was a message bus, and the issues were the RAM my agents read from and wrote back to. Once I saw it that way, the setup stopped looking like a hack.
If you have spent real time in distributed systems, using an issue tracker as your bus should make you wince, so let me make the case against it properly first.
A real message bus is built for speed and for guarantees. A queue like RabbitMQ takes a message, hands it to exactly one consumer, waits for an acknowledgment, and then the message is gone; it is fast, point-to-point, and built so nothing gets processed twice. A log like Kafka keeps an ordered, durable record that any number of consumers can replay from their own position, and it is built to drink from a firehose. Something like D-Bus does near-instant request and reply between processes on one machine. Different tools, same family of virtues: low latency, real throughput, delivery you can reason about.
By those standards GitHub Issues is a joke of a bus. A message can take seconds to post, and in the way I run it a step might wait hours for me to look at it. There are no real delivery or ordering guarantees, and nothing acknowledges anything the way a broker would. Graded as a message queue, it fails on every axis the textbook cares about.
Some of that is the tool, and some of it is my choice. I could make it faster and more autonomous: give each agent its own identity, let them assign themselves issues, run the whole thing as a free-for-all with locking so they don’t collide. I have not, because the speed I would gain has not been worth the overhead yet, and because slow and supervised is mostly what I want here. In practice the control plane points each agent at a specific issue, so the collisions a real free-for-all would have to guard against just don’t come up.
Now write down what an agentic workflow actually needs, and the list comes out almost backwards.
You need a human able to read the traffic, in plain language, and step in. Issues are human-readable by construction. You need the work slow enough that a person can catch a bad instruction before it runs. Issues are slow. You need the state to survive an agent crashing mid-task, a laptop closing, a week passing; issues are still sitting there when everything else has gone away. You need to know, later, what was asked and what was decided and what produced the result. An issue thread is an audit trail by default.
Every property that makes GitHub Issues a bad message queue is a property that makes it a good substrate for this particular job. Slow, human-readable, persistent, audit-trailed. Those are not failure modes you put up with. They are the reasons it works.
The trap is asking “what is the best message bus” as if the question has an answer in the abstract. It does not. A bus is a bundle of tradeoffs, and you pick the one whose tradeoffs fit the shape of the work. I argued a version of this back in 2013: that you do not need the heavy reliable-messaging guarantees the standards push unless your use case actually depends on them. The buses change; matching the mechanism to the job does not. Machine-to-machine traffic at scale wants Kafka or a real queue, because there latency and throughput are the whole game and no human is in the loop. Agentic work is the other thing: low volume, high stakes, and worth a record, because the agent is fallible and a human is in the loop. For that, the boring human tracker beats the fast machine bus, and it is not close.
This is the same move as choosing infrastructure over policy. You get the behavior you want out of the properties of the substrate, not out of a rulebook bolted on top. It is why the build prompt that lives on the issue doubles as a debugging record, and why “who wrote this” has an answer at all. The bus and the audit trail turn out to be the same object.
So that is the bus I run on, on purpose. The issue tracker is the RAM for my agents, and the property that would sink it in a load test is the one that makes it work here: it is slow, it is legible, and it forgets nothing.