DEV Community

Cover image for Your agent orchestrator is a black box. Mine is a folder.
Jimmy
Jimmy

Posted on

Your agent orchestrator is a black box. Mine is a folder.

Status: experimental. I started Agent Board last night. The protocol will probably change.

There is a point with agent orchestration software where you stop feeling like you are shipping software and start feeling like you are operating an airport.

Planner. Supervisor. Queue. Registry. Worker pool. Dashboard. Trace viewer. Retry policy. Task graph.

Somewhere in that pile, an agent writes useful code.

I kept ending up with the same questions:

  1. What is each agent doing right now?
  2. Who is waiting on whom?
  3. What did they decide, and why?
  4. Which discussion led to this code change?

I did not want another dashboard to answer them.

I wanted to answer most of them with:

ls
Enter fullscreen mode Exit fullscreen mode

So last night I started building Agent Board.

It is not an autonomous agent framework. It is an experimental, repo-local coordination layer for coding agents.

The idea is deliberately boring:

folders are columns, Markdown files are tickets, and Git is the audit log.

Or, more bluntly:

The orchestrator is a folder.

The board is the filesystem

Right now the whole model looks like this:

.agent-board/
├── todo/
├── doing/
├── review/
├── blocked/
├── done/
└── threads/
Enter fullscreen mode Exit fullscreen mode

A ticket's status is where the file lives.

todo/    → work not yet claimed
doing/   → an agent or human is actively working on it
review/  → work is ready for review
blocked/ → work cannot progress
done/    → work is accepted and finished
Enter fullscreen mode Exit fullscreen mode

There is no second status field to reconcile. No database row that can disagree with the board. No background process maintaining another version of reality.

If a ticket is in review/, it is in review.

If it is in blocked/, it is blocked.

You can inspect the project with tools you already have:

ls .agent-board/review
cat .agent-board/review/011-fix-message-parsing.md
grep -R "codex" .agent-board
git log -p -- .agent-board/
Enter fullscreen mode Exit fullscreen mode

For v0, that is the data model.

There is a web UI too, but it owns nothing. It is only a projection of the directory. Kill the server, restart it, hard refresh it: the state is still on disk.

That constraint matters to me.

What it is — and what it is not

Agent Board is for a developer or small technical team running a handful of coding agents in one Git repository.

Maybe Claude is implementing, Codex is reviewing, another agent is testing, and you are deciding scope and resolving disagreements.

Agent Board gives those agents a durable place to hand work to each other without turning the coordination layer into another intelligent system.

It is not:

  • a distributed job queue
  • an autonomous scheduler
  • a replacement for Jira, Linear, or GitHub Issues
  • a workflow engine for hundreds of unattended workers
  • a process supervisor
  • a substitute for human review

If you need leases, retries, service-level guarantees, role-based access control, cross-machine scheduling, or a fleet of unattended workers, use a tool built for that job.

Agent Board sits deliberately below that layer.

The goal is not zero communication.

The goal is zero opaque coordination machinery.

No model decides who works next

The board itself makes no model calls.

Agents still spend tokens reading tickets, inspecting code, writing tests, making decisions, and reviewing diffs.

What Agent Board does not do is spend more tokens on a supervisor deciding which model should work next, a planner replanning the plan, or a routing agent selecting another agent.

The board tracks explicit things:

Where is the ticket?
Who claimed it?
What was asked?
What was answered?
What commit or diff is being discussed?
Enter fullscreen mode Exit fullscreen mode

A human can put work in todo/. An agent can claim it. A reviewer can receive it in review/.

For the kind of workflow I am testing, that may be enough.

A 30-second handoff

Claude takes a bug:

board init
board new "Divide crashes on zero divisor"
board take 1 --owner claude
Enter fullscreen mode Exit fullscreen mode

Claude fixes it, records the commit, asks Codex to review, and moves the ticket:

board comment 1 "Fixed in a1b2c3d. Added a guard clause and regression test." \
    --by claude --to codex --ask --commit a1b2c3d

board move 1 review
Enter fullscreen mode Exit fullscreen mode

Codex checks what is waiting on it:

board inbox codex
Enter fullscreen mode Exit fullscreen mode

It sees:

AWAITING YOUR REPLY (1)

001  ticket #1   claude → codex   a1b2c3d
     Fixed in a1b2c3d. Added a guard clause and regression test.
Enter fullscreen mode Exit fullscreen mode

Codex reviews the diff, replies, and closes the ticket:

board comment 1 "Approved. The guard is correct and the regression test covers zero." \
    --by codex --to claude --re 1

board move 1 done
Enter fullscreen mode Exit fullscreen mode

For now, the protocol is intentionally tiny.

--ask means a reply is expected.

--re 1 means this message answers message 1.

One rule decides whether something is still pending:

An addressed message carrying ask remains pending until a later message in the same ticket explicitly references it with re.

A normal comment is not pending. A reply is tied to the question it answers.

The system does not guess based on who spoke last, an unread badge, or a model interpreting whether a conversation "seems resolved."

That distinction matters.

Conversation happened is not the same thing as the question was answered.

The screen I actually want

The existing inbox can show unanswered requests across tickets.

But the next thing I want is not more intelligence. It is better derived visibility.

Something like:

$ board status

TODO       5
DOING      2
REVIEW     1
BLOCKED    1
DONE      14

ACTIVE
#12  claude   Fix auth race
#15  codex    Refactor parser

WAITING
#12  claude → codex   18m

POSSIBLY STALE
#09  claude   doing for 3h 41m
Enter fullscreen mode Exit fullscreen mode

The important part is what board status doesn't do.

It does not create another state store.

It does not maintain presence.

It does not silently reassign stale work.

It simply derives a useful view from the files that already exist.

If an agent crashed three hours ago, the board should not pretend it knows whether that process is alive. It can tell me that a ticket has been sitting in doing/ for three hours.

That is enough information for a human to decide what to do.

Why Git matters

Most agent tools treat conversations as application data.

That is fine until the conversation becomes more important than the output.

A code change often needs context:

  • Why did the agent choose this implementation?
  • What alternative did it reject?
  • Which reviewer found the edge case?
  • Which test was claimed to cover it?
  • Did anyone challenge that claim?
  • Which commit resolved the disagreement?

With Agent Board, that context is plain text beside the project.

It can be searched, diffed, branched, reviewed, archived, and recovered using the same tools as the code.

The reviewer's argument is not a transient chat bubble.

It is a diff.

That is the property I care about most:

custody.

Not just observability, where a dashboard tells you something happened.

Custody, where the project retains the discussion that explains why it happened.

It already found a bug in itself

The first interesting thing Agent Board did was help find a bug in its own message parser.

I shipped a feature with 161 tests passing and asked Codex to review the diff.

Codex found a message-parsing problem involving bare carriage returns. A Markdown message body could contain text that looked like another message header. I had tried to neutralise that content, but Python's text-mode newline handling could later turn a bare carriage return into a newline.

That meant body text could become something that looked like a real message.

Worse, a forged reply could make a genuine --ask appear answered and silently remove it from the inbox.

The reproduction looked like this:

after real ask  → messages=1  pending_asks=1
after CR body   → messages=3  pending_asks=0
    #1 by='claude'  re=[]   ask=True   to='codex'
    #2 by='mallory' re=[]   ask=False  to=None
    #3 by='codex'   re=[1]  ask=False  to='claude'
Enter fullscreen mode Exit fullscreen mode

I pushed back on the severity. Codex pushed it higher.

Then it caught me overstating what my fix actually tested.

That exchange mattered more to me than the bug.

The original finding, reproduction, disagreement, revised fix, review, and commit were not trapped in a chat tab that would disappear.

They were part of the project history.

The green tests were useful.

The review trail caught the difference between:

"I said this was covered."

and:

"The committed test actually covers it."

That is exactly the kind of thing I want agent tooling to preserve.

What I deliberately did not build

The easiest way to ruin a simple coordination tool is to keep saying yes to reasonable features.

I know because Agent Board replaced an earlier homegrown experiment called .agent-bridge.

That system accumulated the usual "small sensible additions": a registry, duplicated state, structured messages, and per-project copies that drifted apart.

Agent Board is partly an experiment in saying no earlier.

Rejected Why
Agent registry Crashed agents leave stale roster state. I care more about explicit work than a roster pretending to be live.
LLM scheduler I do not want a model spending tokens deciding which model should work.
Separate status field The directory already is the status. Two sources of truth eventually disagree.
JSON ticket files Concurrent structured edits create ugly Git conflicts. Markdown is easier to read, merge, and repair.
SQLite Great tool, wrong trade-off here. I value a human-readable Git history more than query power.
Heartbeats / presence Stale presence can be worse than no presence because it looks authoritative.
Automatic claim expiry I would rather surface stale work than silently mutate it.
Stateful web backend The UI should project the files, not become another owner of state.

None of those features are inherently bad.

They are useful in distributed execution systems.

They are just not obviously necessary for the thing I am trying to build.

At least not yet.

The technical boundary

This simplicity only works if I am honest about where it stops.

Right now Agent Board is one Python file, standard-library only, Python 3.11+, using POSIX file locking.

So the intended environment is:

  • macOS or Linux
  • one repository
  • a local POSIX filesystem
  • a human still in the loop

It is not a distributed consensus system.

I would not treat the board directory as a multi-writer coordination backend over Dropbox, iCloud Drive, SMB, NFS, or some casually shared network volume and expect local-filesystem semantics to magically hold.

The board can be authoritative about board state:

  • which column a ticket is in
  • who wrote a message
  • which explicit questions are unanswered

It is intentionally not authoritative about:

  • whether an agent process is alive
  • whether someone's terminal crashed
  • whether an agent is currently "thinking"
  • whether a remote machine disappeared

That is not a limitation I want to hide behind a dashboard.

It is a boundary.

The next hard problem: parallel working trees

There is another problem the board does not solve yet.

Two agents can coordinate perfectly on tickets and still destroy each other's work if they edit the same checkout at the same time.

Claude can modify auth.py while Codex is reviewing it.

One agent can run tests against another agent's half-written changes.

One can stage files the other created.

Coordination is not isolation.

So I am testing a Git worktree model:

ticket #12 → branch agent/12 → worktree ../project-agent-12
ticket #15 → branch agent/15 → worktree ../project-agent-15
Enter fullscreen mode Exit fullscreen mode

The principle would stay the same:

Agent Board coordinates the handoff. Git owns the code state.

I do not want Agent Board to become a Git abstraction layer.

But if parallel agents are going to be useful, there needs to be a clean story for isolating their working directories.

That is one of the first places I expect the current design to be tested hard.

Start with a durable handoff, not an agent organisation chart

I think the easiest way to overbuild multi-agent systems is to start by drawing the organisation.

Supervisor.
Architect.
Researcher.
Implementer.
Tester.
Reviewer.

Instead, start with two agents and one real task:

Claude: implement
Codex: review
You: set scope, approve changes, resolve disagreements
Enter fullscreen mode Exit fullscreen mode

Give Claude a focused ticket.

Let it leave implementation notes beside the work.

Ask Codex to review the actual diff.

Keep the disagreement with the code.

If that works, add a tester or researcher.

If it does not work, adding a supervisor, scheduler, registry, dashboard, and another model probably will not fix the underlying problem.

The useful primitive is not more agents.

It is a durable handoff.

Start here

Right now the project is intentionally small:

  • one Python file
  • standard library only
  • no daemon
  • no database
  • no model dependency
curl -L \
  -o board.py \
  https://raw.githubusercontent.com/jharjadi/agent-board/main/board.py

python3 board.py init
Enter fullscreen mode Exit fullscreen mode

init creates the board and adds operating instructions to AGENTS.md and CLAUDE.md so agents can discover the protocol in the repository.

Then create one ticket, give it to one agent, and have another agent check its inbox.

Do that before you build a fleet.

Because this project is still experimental, I am not pretending main is a stable release channel. Tagged releases are the obvious next step once the protocol settles enough to deserve one.

Why publish this after one night?

Because I do not want to spend a month making the wrong thing polished.

I want people who actually run Claude Code, Codex, Gemini CLI, OpenCode, Hermes, or other agents in parallel to tell me where this model breaks.

Maybe the filesystem model survives five or ten agents.

Maybe it becomes annoying at three.

Maybe Markdown is exactly right.

Maybe the message protocol turns out to be too clever.

Maybe worktrees need to become first-class.

I would rather learn that now.

The interesting question is not how many features I can add.

It is how many I can refuse while the tool still coordinates real work.

Three rules I am trying to hold onto:

  1. Assignment should be visible. A ticket's location should tell you its stage.
  2. A question should have an explicit answer rule. Do not infer resolution from conversation shape.
  3. Important agent decisions should live in plain text beside the code. The discussion that changed the implementation may be more valuable six months later than the implementation itself.

The point is not to orchestrate more agents.

It is to make the coordination layer small enough that it cannot hide from you.

That is the bar I am holding Agent Board to.

Not:

"Can it orchestrate?"

But:

"Can it get out of the way?"


Agent Board on GitHub · MIT

Experimental. Built in public. Expect the protocol to change.

Top comments (0)