Latticeflow: Making AI Agents Deterministic
AI coding agents are powerful and completely non-deterministic. Latticeflow wraps them in one: a single native binary that drives a ticket through a deterministic plan, implement, review, ship lifecycle - and only pays for an agent on the steps that actually need one. I use it to build almost everything else on this site.
The Problem
My earlier approach drove everything through a persistent chat session that re-read its whole prompt corpus on every action. One 7-ticket chain on TradeTrack2 took four hours and burned about 190 million cache-read tokens - call it $258 in equivalent API tokens if I hadn’t been on a Max plan. Roughly 76% of that was the chat re-reading its own 26k-token corpus on every transition. I was using a chat loop as a state machine and paying the full corpus cost on every step.
No money actually left my account, so that number isn’t a war story about spend. It’s the target: burning tokens is not the achievement, doing the same work on a fraction of them is. And when Anthropic announced they would start charging API rates for piped CLI commands, the rebuild stopped being an optimization and became preparation.
What I Built
Latticeflow, a single-binary command-line tool called build that owns the full lifecycle of a development ticket. Point it at a Plane project, give it a ticket, and it drives that ticket through a deterministic state machine: plan the work, cut a git worktree, implement the changes, run a gate of automated checks, dispatch a review, and ship the result back to the target branch. Every phase either succeeds, fails with a classified exit code, or triggers a bounded rework loop. No daemon, no server, no shared state across invocations - the binary exits at the end of each verb.
Latticeflow replaced Claude-Config, an earlier corpus of markdown slash-commands that drove ticket lifecycles through a live Claude Code chat acting as runtime, state machine, and tool gateway all at once. That corpus shipped real tickets on real projects, TradeTrack2 among them, and it’s the reference implementation behind The Shape of Done. Latticeflow is the public name, build the binary, throughline-build the repo.
Tech Stack
- C#
- .NET 10
- native AOT (single self-contained binary)
- System.Text.Json
- TOML config
- Plane backend (git worktrees for isolation)
- cross-platform AOT builds (Windows / macOS / Linux)
- GitHub Actions three-platform CI matrix
- multi-vendor worker orchestration - Claude Code
- Codex
- Gemini
- Copilot CLIs
- ConPTY / Unix PTY interactive transport
- xUnit (~2
- 200 tests across 19 projects)
How It Works
C# on .NET 10, compiled to a native-AOT single executable that needs no .NET runtime on the target. Every interaction falls into one of three tiers: state transitions, gates, and Plane writes are plain deterministic code; small scoped decisions are single API calls; plan, implement, and review spawn a worker CLI in an isolated git worktree.
The worker layer is genuinely multi-vendor. Claude Code, Codex, Gemini, and Copilot each sit behind an IWorkerAgent implementation, selectable globally or per phase, each handling its own auth posture - so all LLM cost flows to the operator’s subscription and the orchestrator never touches provider credentials directly.
Between implement and review, a deterministic gate runs the configured checks and proves itself first: a vacuity prover hard-fails any gating check that can’t actually fail, and a control prober re-runs failed checks against the untouched base ref so a broken environment is never blamed on the ticket.
The chain orchestrator drives multi-ticket trees through a post-order traversal with accumulated integration branches - children ship into a parent’s local chain branch, nested parents merge up, and only the outermost chain lands and pushes. Multi-ticket dispatch builds a graph from blocked_by relations and runs level-synchronously with bounded concurrency.
What Made It Hard
Making a non-deterministic tool behave deterministically at the boundaries. Attributing cost per action across four different vendor CLIs. Proving a passing gate actually tested something. And building an interactive transport for Claude Code after Anthropic moved --print usage onto a separate credit allowance: launching Claude under a platform PTY (ConPTY on Windows, a Unix PTY elsewhere), feeding the brief as a file reference, and detecting completion by tailing the persisted transcript once the per-turn Stop hook stopped firing in interactive sessions. Validated green on Windows 11, macOS 26.4 arm64, and Ubuntu 24.04.
The Throughline
This is the tooling underneath everything: I built the system that builds the products. It’s the productized version of the method in The Shape of Done, writing to my self-hosted Plane fork, and it’s the difference between using AI and engineering with it.
Status
Active development, and dogfooded - every ticket in Latticeflow ships through Latticeflow. The four worker agents, the full plan-through-ship pipeline, the chain orchestrator with gate and batch implement, the bootstrap verbs, and the interactive Claude Code transport are all functional and in daily use, with the AOT binary built and tested across all three platforms and roughly 2,200 xUnit tests. A vendor-neutral model client with SSE streaming is built and tested but not yet wired onto a production path. Plane is the sole ticketing backend today; GitHub and Linear remain aspirational.