12 board stages, 6 repos per ticket, about 5,100 lines of TypeScript, 2 days to build. The first full ticket went from Todo to merged across all 6 repos for 0.8M tokens.
That is Orch2, the development pipeline we run on Envizom at Oizom, where I'm a Tech Lead. One change usually touches a Go backend, a Svelte frontend, a UI library and 3 driver repos. Orch2 turns a kanban board into the control panel: a plain script runs the pipeline, Claude agents only do the coding, and every ticket gets its own sandboxed copy of the whole product. The Envizom code is proprietary, so this is the design, not the source.
Three things stay separate. The tracker is a product. Orch2 is a client of it. The agent is what Orch2 runs.
A script, not an agent
The orchestrator is ordinary TypeScript: predictable, cheap and easy to debug. An LLM starts only when there is code to write or a conflict to resolve. The board is the whole UI. There are no dashboards and no CLI for users, just stages, the thread and question cards, and orch replies in the thread with links, PRs and preview URLs. A human types one field, Src Branch. The ticket branch is the ticket key in every repo, and everything else is derived.
| Stage | Who | What happens |
|---|---|---|
| Todo | human | backlog, orch never acts |
| Pull Latest | script | branch in all 6 repos, workspace built, stack health-checked |
| Approved | script | agent started or resumed on the ticket branch |
| Working | agent | posts a plan as a task list, codes, tests against its live stack, calls endWork |
| Review | human | opens the running app and the browser IDE |
| Git Push | script | commit, merge base, build check, push, one PR per changed repo |
| Preview | script | production build, HTTPS link posted |
| Confirm | human | the lead checks the preview |
| Git Merge | script | every PR checked first, then merged libraries-first |
| Completed | done | |
| Cancel | human | Yes/No card, stops the agent, closes the PRs |
| Trashed | branch, workspace and preview deleted |
Every agent turn posts a short receipt and adds its token use to a board aggregate, so cost shows per ticket on the card and per day in analytics. The aggregate is stored in millions because 798,400 on a card was unreadable. It now says 0.8.
Each developer runs their own orch, with its own board agent and token, so assigning that agent to a ticket hands the ticket to that machine. The same codebase has a preview mode that runs once, on the dev server, for production previews.
A copy of the product per ticket
A workspace is 6 repo clones, its own data and its own stack on its own block of ports. Git uses a bare mirror of each repo and clones with --reference --dissociate, so a checkout takes seconds and owns its objects. GitHub auth goes per command as an HTTP header, so no credential is written to disk in a workspace.
One front router on a single port routes by hostname: <ticket>.localhost for the app and code-<ticket>.localhost for code-shell, the browser IDE. Browsers resolve *.localhost themselves, so a new ticket needs no DNS record and no proxy reload.
Data is real and safely copied. SQLite comes through a token-gated read-only file server as a VACUUM INTO snapshot, because copying a live WAL database gives a corrupt file. Downloads are checked by magic bytes, so an HTML error page can never be saved as a database.
Five layers around the agent
A ticket agent can run commands, edit, build and test. It can't push, reach secrets or touch anything outside its ticket. A gap in one layer is caught by the next:
- Scrubbed environment. Every secret removed, for the agent, the workspace stack and the IDE.
- OS sandbox on every shell command. Seatbelt on macOS, bubblewrap on Linux. Writes only in the workspace and build caches, network limited to localhost, package registries and GitHub.
- A guard on every tool call. The same policy twice, in the SDK permission callback and a PreToolUse hook. It blocks
git push, branch switches,reset --hard,sshand piping downloads into a shell, orch-managed files are read-only, and every denial returns the reason. - A narrow tool surface. Only orch's own MCP server: ticket and thread, plan, stack control,
endWork. No connectors, and no web fetch because it could leak ticket text. - Gates.
endWorkis refused until the plan is finished, the stack is healthy and the merge is clean. Orch commits and pushes only after a human moves the card to Git Push.
What production taught us
| Symptom | Fix |
|---|---|
| 160k tokens lost by one agent fighting a failed Go module download | network build failures go to a human; agents get only code problems |
| Corporate TLS inspection broke Go proxy and GitHub calls at random | quiet retries at 1, 3 and 9 minutes before anything is posted |
| Fast clones failed with "unable to parse commit" on new git versions | commit-graph off on clone and mirror fetch |
| A production build ran out of memory and hung a swapless 15 GB server | one preview at a time, container memory limit, heap cap, free-memory check |
| A preview stack died after a container restart | 10-minute watchdog; startup reconciles every ticket |
The first row decided a design rule: infra failures go to a person, never an agent, because an agent can't fix a firewall and will burn tokens trying.
What in your pipeline still lets an agent spend tokens on a problem it can't solve?

