Inspiration
We wanted to run a few coding agents on the same codebase at the same time. The usual approach is to give each one its own branch or worktree and sort out the mess at the end.
Git handles the obvious case. If two agents edit the same file you get a merge conflict. It does not handle this one:
- the backend agent changes an endpoint to return
orderIdinstead oforder_id - the frontend agent read the old shape twenty minutes earlier and keeps using
order_id - different files, different repos, no overlapping lines
What it does
ClockedIt is a coordination server that sits between the agents. Agents do not write to shared state themselves. They ask the server, and the server is the only thing that changes anything.
The server is not an LLM. It is normal code with a task queue and a versioned file store, so it behaves the same way every run and we can write tests for it.
When an agent commits, the server checks versions:
- the agent fetches the files it needs, works in its own scratch space, then commits the batch
- rejected if a file it wrote has changed since the version it based on
- rejected if a file it read has changed since it read it
- the rejection lists the exact paths and versions, so the agent refetches, redoes the change and tries again
- after three failed attempts the task is dropped instead of retrying forever
Agents can also create tasks for each other. A task has an owner, a list of dependencies, and the paths it plans to write. The server only hands out a task when its dependencies are done, its owner is free, and its writes do not clash with a task already running. Everything the server decides gets written to a numbered event log, which the dashboard reads.
How we built it
We started from the Agent Launchpad starter kit, which already had agent CRUD, a playground, per-agent workspaces, and Codex CLI running in a throwaway container each turn. We added the middleware on top and split it five ways so we could work in parallel:
- a message protocol, with zod schemas for every request and response
- a router that validates messages and is the only boundary agents cross
- a coordinator with the task queue, dependency graph and state machine
- a versioned file store that also records what each agent has read
- a dashboard for agents, tasks and the event timeline
Everything goes through one serialized write path in a single process. So all commits are handled by the server.
The agent's workspace starts empty. Shared files are never copied into the container. The only way to get one is to ask the server, and that request is how the server knows the file was read. Agents talk to it through a small command line tool we install in their workspace, because running commands in a folder is the one thing a Codex agent does reliably.
Challenges we ran into
Ideation: Most of the first day went on deciding what the actual problem was, rather than writing code. We read around existing agent to agent protocols and older work on database concurrency control, partly to avoid reinventing things and partly to find out which bits were genuinely unsolved. The answer we settled on was that conflicting writes are a well understood problem, and stale reads across agents are not.
Parallel work: It was difficult to split the work such that it minimised overlapped while still maintaining the ability to integrate well
Deciding what to leave out: Three days is not long, and there were a lot of features we wanted. We cut anything that was not needed to prove the core idea.
Accomplishments that we're proud of
The read check works. An agent can commit a file that nobody else has touched and still be told no, because something it read has moved since it read it. That is the case git cannot see, and it is the reason we built any of this.
The coordination logic is ordinary code, so we could actually test it rather than just show it working once. One test fires ten concurrent commits at the same path and asserts that exactly one gets through. Another checks that a commit is rejected when only a file the agent read has changed, which is the behaviour the whole design rests on.
Agents create and assign tasks to each other, so the dependency graph is something the agents build as they go rather than something we wrote out in advance.
We did all of this without breaking the platform we started from. Agent CRUD, the playground and the container runtime still work exactly as they did.
What we learned
A version check needs something to attach to. A shared contract file is useful because it is one object both agents touch and it has a version number on it.
Asking two agents to agree on something in prose gives a different answer every run, and they can both be confidently wrong in the same direction. A file with a version number does not have that problem.
Telling an agent to use the tool is not enough on its own. Handing it an empty folder is.
The prompt is the least reliable part of the whole system, and no amount of server design makes up for an agent that ignores it.
What's next for ClockedIt
- agent liveness, so a task held by a dead agent comes back instead of sitting there
- freezing files and asking a human, for the conflicts that retrying will never fix
- persisting the event log so the timeline survives a restart
- ignoring duplicate messages from containers that got retried
- real git behind the file store instead of files in a JSON document
Built With
- byteplus-modelark
- codex-cli
- deepseek
- docker
- fastify
- node.js
- react
- typescript
- vite
- vitest
- zod
Log in or sign up for Devpost to join the conversation.