I've tried several ways to work with multiple coding agents, including Paperclip and other agent setups. I kept looking for something simpler.
I wanted to give an agent a task, see what it was doing, and hand the result to another agent for review. I wanted to stay involved without constantly copying messages between sessions.
In the setups I tried, too much effort went into running the coordination itself. Agents re-read context, discussed who should take work, and posted updates for other agents to read. That used tokens before much coding happened.
I wanted coordination simple enough to handle with a shared task board.
So I built agent-board. I'm sharing it because someone else might be looking for the same small thing.
What it is
A kanban board where directories are columns and tickets are Markdown files:
.agent-board/
todo/ 007-fix-login-redirect.md
doing/ 003-add-auth.md
review/ 005-refactor-api.md
blocked/
done/
Moving a ticket means moving a file. Comments are sections appended to that file. Commit the board files and git gives you their history.
The implementation is one Python file, standard library only. There is a CLI for agents and a local web UI for me. Both work on the same files. Refresh the page and it rebuilds the board from disk.
No database, framework, build step, or background service to install. Run board serve when you want the UI.
What using it looks like
In a project:
board init
board new "Fix login redirect loop" --desc "401 doesn't clear the cookie"
board serve
Open http://127.0.0.1:8899 in your browser. You can create tickets, move them between columns, set an owner hint, and add comments.
Then tell an agent:
Take ticket 1 from the board. You're the implementer.
board init adds a short workflow to the project's agent instruction files, normally AGENTS.md and CLAUDE.md. An agent that loads those files has the commands available in its instructions. The workflow looks like this:
board show 1
board take 1 --owner implementer --from todo
# Do the work, then report what changed and how it was checked.
board comment 1 "Fixed in a1b2c3d; regression test passes" --by implementer
board move 1 review
The --from todo check refuses the claim if the ticket has already left that column.
Now another agent can read review, inspect the code, leave a comment, and move the ticket to done or blocked. The handoff is there for the next session to read. I don't have to reconstruct it from two chat histories.
Claude, Codex, or a person can do either job. The board does not need to know which one it is.
Where the simplicity comes from
The board never knows which agents exist.
There is no roster to maintain, no manager agent assigning work, and no scheduler deciding who is free. Moving a ticket to review makes it available to whoever is handling review. The optional owner field is a sticky note; it routes nothing.
The board itself makes no LLM calls. Listing tickets, moving files, adding comments, and watching a column are ordinary local operations. Agents still use tokens to read tickets and do the work; the board adds no model calls of its own.
I also kept the columns fixed and left out presence indicators and automatic claim expiry. I watch for stuck work myself. That is a reasonable tradeoff for how I use it: a few agents with me in the loop.
The longer explanation of what I left out, and why, lives in docs/decisions.md. Those choices keep the tool small enough that I can understand and change it.
One small thing that helped
My previous setup had a message bus, but I still kept typing “check your inbox.” Eventually I noticed that the project's agent instructions never mentioned it. New sessions had no reason to know it existed.
That is why board init writes the instructions. It was a small change that made the board easier to use than another delivery mechanism would have.
It does not wake an idle agent. If you want nudges, the optional board watch command polls a column locally and can feed a notification into your terminal setup. The README has an example. You can also just tell an agent to check the board.
Try it
You need Python 3.11+ on macOS or Linux. To install the CLI:
git clone https://github.com/jharjadi/agent-board.git
mkdir -p ~/.local/bin
ln -s "$PWD/agent-board/board" ~/.local/bin/board
Make sure ~/.local/bin is on your PATH, then run board init in the project where you want a board. Install the tool once; each project gets its own ticket files.
If your agents work in separate git worktrees, point every agent, watcher, and web server at the same board:
export AGENT_BOARD_ROOT=/absolute/path/to/project/.agent-board
Use a board already created with board init. Separate worktrees keep the code apart; that shared path keeps coordination together.
Keep the board on a local filesystem and the UI on localhost. Mutations through the CLI and UI share a file lock; direct file edits bypass it. This is a small, supervised tool, with known limitations documented in the README.
It is MIT licensed. Use it, read the single file, or fork it to fit your workflow.
I built this because I kept wanting something smaller than the setups I had tried. If you have a few coding agents and mostly need a place to put work and hand it on, here it is.

Top comments (1)
The part about tokens spent on meta-work mirrors something Ronald Coase mapped in 1937. Firms exist because market transaction costs exceed internal coordination costs. Your orchestrator was a firm. Its coordination overhead crossed the line where a simpler market (agents polling a directory) became cheaper. Most multi-agent setups I have seen get this wrong in exactly the same way. They add rosters, schedulers, presence, and message buses because those feel like mature engineering, but each piece raises the internal transaction cost until the "firm" is more expensive than the problem it replaced. Your refusal inventory is basically a list of things that push coordination cost above the Coasean floor. The directory-as-column trick works because its coordination cost is nearly zero: a stat call, not a planning round.