Tutti: coordinating coding agents with GitHub Issues
A local coordinator that treats GitHub Issues as a state machine for dispatching AI coding agents.
Once you have one coding agent working, the obvious next thought is “what if I had several?” Then you hit the real problem, which is not the model. It is coordination. Which agent runs next, in what order, what blocks what, and when does a human need to step in before something risky lands.
Tutti is my answer to that. It is a local coordinator for coding agents, and it makes one deliberate choice: it does not invent a new control plane. It uses GitHub Issues.
Issues as the workflow surface
Every unit of work is a GitHub Issue, and the state lives in labels. There are a few
families of them: state:* for where the work is in the pipeline, role:* for who owns
it next, type:* for what kind of work it is, plus priority:* and override:*.
The coordinator polls, reads the labels, decides what to do next, and dispatches the right agent. When an agent finishes, it hands off by flipping labels. The whole workflow is just a state machine where the state is stored in a place I can already see.
state:* labels are the workflow.The roles
A fresh issue gets labelled state:triage. A Dispatcher agent classifies it and routes it
on. From there, specialised agents take turns: a researcher who writes durable notes into
docs/, a PM who turns that into requirements, an engineer, a QA pass, and a merger that
actually lands the PR. There are even exploratory roles, like a “monkey tester” that pokes
at the product looking for breakage and writes up what it found.
Each role does its piece, writes something durable, and hands the issue to the next owner.
The parts I actually care about
The interesting engineering is not the dispatching. It is the guardrails:
- Dependency gates. An issue will not start until the things it depends on are done.
- Human-verification pauses. At the risky points, the coordinator stops and waits for a person instead of barreling ahead.
- Retry and loop detection. Agents get stuck and spin. The coordinator notices and stops it.
- Dry run. I can see exactly what it would do without it touching anything.
- Explicit overrides. When I need to force past a gate, I add a label like
override:deps-ignore. It is deliberate, visible, and easy to clear afterwards.
Why GitHub Issues, and not a dashboard
I could have built a database and a custom UI. I chose not to. Issues already give me a board, comment threads, history, permissions, and a mobile app I already have on my phone. The agents and I look at the exact same surface. When something goes wrong, I am debugging in a tool I already understand, not in some bespoke thing I now also have to maintain.
That turned out to be the whole lesson. The hard, valuable part of multi-agent work is coordination and trust: ordering, isolation, and knowing when to pause for a human. The model is the easy part now.