02 JUL 2026 · 5 min read

Any agent, any session, one record everyone works from

Most tools bolt an AI layer onto software built for people. Projects is built the other way round: agents are first-class participants in the work, and the record they act on is the same one people read.

AI agents are individually useful long before they are easy to coordinate. Give several of them a codebase and the failure mode is familiar: two agents start the same change, a dependency is buried in a markdown file, a blocker disappears into a transcript, and the person responsible has to reconstruct the truth from chat. The problem is not that the agents cannot write code. It is that they do not yet share a dependable account of the work.

I built Projects for that gap. It gives people and models the same durable record of what is ready, who owns it, what is blocked, and what done means. A Project contains Tasks; Tasks contain SubTasks; and a SubTask is the small, explicit unit of work an agent can execute. The result is not an AI layer bolted onto a tracker. It is a work system in which the AI is a participant.

A work loop, not a chat transcript.

Start with a SubTask: the change to make, the file or branch it concerns, its definition of done, and any work that must finish first. An authorized agent asks the Dispatcher for work. The server checks the dependencies, access, durable assignees, and current leases, then offers the next eligible SubTask. The agent does not choose a convenient item or race another agent for it.

Once it accepts the work, the agent holds an exclusive lease and streams progress back to the same record. If it hits an external problem, it reports a blocker with a reason and releases the lease. The person directing the work sees that state in the terminal or local dashboard, can read the history, resolve the blocker, and intervene safely when necessary. Progress has somewhere better to live than a message that will scroll away.

The record lives on the server rather than inside a session, and that is what makes it durable in the ways that matter. It survives the end of a session, so work I interrupt at the end of one day is still waiting for me the next. It follows me between devices, because nothing important is held in local context on one machine. And it outlives any particular provider: the state does not belong to whichever model or vendor happened to be executing, so changing the agent I use does not mean reconstructing where things stood.

One contract, many surfaces.

By contract I mean the shared definition of what the system can do and the rules it enforces. In Projects, that contract is a typed protobuf and gRPC API. It defines operations such as creating a SubTask, requesting work, reporting progress, resolving a blocker, and finding out who the caller is. The server is the authority behind it: it owns the data, decides what is eligible, and enforces access and state transitions once.

That distinction matters when a tool serves a person and a model. It is tempting to make the agent integration its own product, with its own rules and its own view of the world. I have made that mistake. It creates two places for behaviour to drift and two places for a security decision to be wrong. Instead, I keep the core contract stable and build deliberately thin adapters around it.

One core, three ways in.

For people, pctl is the command-line interface: an interactive terminal view when I am exploring work, structured JSON when I am scripting it, and a local dashboard for totals, blockers, and live progress. For agents, projects-mcp is the primary interface, and it is deliberately not tied to one vendor or one product: any coding agent that speaks MCP can connect to it. Inside that agent, the model calls structured tools such as list_projects, request_work, and report_progress instead of shelling out and parsing text. For ordinary integrations, projects-rest exposes the same capability over HTTP and JSON.

Those adapters are intentional code, not magic generation. Adding a capability still means designing the operation and giving each surface a useful translation. What does not get copied is the behaviour: the caller identity is forwarded to the core, the core applies the same rules, and no adapter gets to decide on its own what a caller may see or change. Three interfaces can evolve without becoming three competing systems.

Agents with boundaries.

An agent is not a privileged service account with a view of everything. Agent Types are principals in the same access model as people, and an Agent Type describes a role in the work rather than a particular tool or model behind it. They have to be added to a Project, their membership can be scoped and revoked, and they can only receive work they are allowed to see. The lease makes execution exclusive; the access model makes it bounded. That is the difference between letting an AI loose in a system and giving it a real, accountable role in one.

The same discipline makes the human side better. Projects keeps durable assignees separate from the transient agent lease, records versions of work items, and lets an operator inspect history, compare changes, or revert an earlier state. The person is not reduced to approving prompts. They retain a clear view of what the system is doing and a deliberate way to change course.

The stack serves the model.

The implementation is Go, protobuf and gRPC over PostgreSQL with row-level access controls. Buf keeps the generated contract code consistent, while the production stack uses Auth0 for identity and Fly.io with managed Postgres. I keep a k3s environment for development. These choices are not the product, but they support the same idea: explicit interfaces, portable clients, and one place where the rules live.

Working with me and the machine.

This is the kind of AI-enabled software practice I want to build. Use models to move faster, but give their work a shared record, a bounded scope, a visible definition of done, and a way for people to understand and redirect it. The useful future is not humans outside the loop while agents improvise inside it. It is people and agents working from the same facts, through interfaces designed for each of them.

Projects is available now. Connect it to whichever coding agent you already use through MCP, use pctl where a terminal is the right surface, and let the work itself stay coherent as the number of agents grows.

Tri2b · the studio