I built a coding agent to find out where the tokens go.
Phil is a terminal coding agent built on LangGraph and DeepAgents. It plans with you, works in its own git worktree, and stops at a budget you set. Every change I make to it runs against a live benchmark, and I write up what I learn.
The one-line change that took fifty minutes.
I asked an early version of Phil to add one hidden <meta name="easter-egg" content="hello world"> tag to a one-page Astro site. Any current model writes that line in two seconds. Here is where the other fifty minutes went.
The model wrote reasonable code. The harness around it tripped over its own guardrails, dropped context on every approval, and insisted on a failing test for a meta tag.
1. Every ls needed approval
The agent used ls, cat, and grep to inspect the repository. None were on the execution allowlist, so each call paused for human approval. After each pause, the agent forgot its state and re-explored from zero.
2. Each retry started from zero
Each approval, retry, or resume started a new agent session. Most of the 3 million tokens were the same context, sent again.
3. TDD for a meta tag
The orchestrator wanted a failing test before any code. A meta tag can't fail a unit test, so the agent looped in the red phase and never got out.
4. No spending limit
A small website change on Sonnet ran 46 model calls and 1.56M tokens in 90 seconds ($3.17) with nothing to stop it.
Every step is a node you can inspect.
Phil runs each job as a LangGraph state machine. Intake, planning, implementation, and review are separate nodes, and each one hands the next a contract it can check. When something goes wrong, you can see which step did it.
LangGraph Core
Intake, routing, planning, implementation, verification, and PR creation are LangGraph nodes with conditional edges between them.
/resume after a crash or stopDeepAgents Delegation
An agent can hand a search to a subagent. The subagent spends the tool-call tokens, and the parent gets back a short answer.
Worktree Sandboxing
Phil never touches your working directory. Each run gets its own .phil/worktrees/<id> on its own branch.
Four decisions, and what they bought.
Each one came out of a run that went wrong. Here is what changed and what it saved.
A classifier for routing
Deciding whether you asked a question or want a refactor is a classification problem. Paying $3 per million tokens for a chat model to make that call is overkill, so Phil uses TypeSafe Jev, a small "System One" decision model.
- ›$0.042 per million input tokens, with no charge for output. About 70× cheaper than a frontier chat model.
- ›12× lower p95 latency. Routing takes under 200 ms.
- ›If Jev times out, the low-tier model routes instead.
Two tiers instead of six roles
Early versions of Phil asked you to pick a model for each of six internal roles. That was a lot to ask, so now there are two tiers.
Agent shells never see your keys
An agent that can run shell commands is one prompt injection away from reading your keys. Phil assumes that will happen.
- ›Subshells set
PYTHON_KEYRING_BACKEND=null, so code the agent runs can't read the OS keychain. - ›API keys and tokens are removed from the environment of every child command.
- ›Commands with
&&,|, or;, symlinks that point outside the worktree, and mutating flags are rejected.
Small jobs get a small process
A typo fix doesn't need an intake interview, an architect, and a code review. Phil picks one of three paths.
- ›Questions run against a read-only snapshot. No branch, no commits.
- ›A one-task change gets one implementer and one review. The quick-path demo above cost four cents.
- ›When a request is ambiguous, Phil asks one multiple-choice question instead of guessing.
A rule written first.
Every change to Phil runs against a live benchmark, and I write down what I expect before I run it. This series is the record: what broke, what I changed, and what it cost.
Stop the Waste
Fifty minutes and 3 million tokens on a one-line meta tag. Where they went, and the benchmark harness that came out of it.
Configure Once, Any Model
Six internal model roles become two tiers. API keys move to the OS keychain and stay out of agent shells.
The Right Amount of Process
Routing with TypeSafe Jev, a small decision model, and deciding how much process each request deserves.
Paying for What You Use
How planning a small change cost $3.17, and the call caps, prompt caching, and intake questions that fixed it.
A Rule Written First
Setting classifier thresholds on 50 live runs, with the pass/fail rule written down before the first one.
Install it and point it at a repo.
There are no config files to write. Run phil setup once to pick a provider and models and to store your key in the OS keychain. Then run phil in any git repo.
From a clone of the repo, with uv:
Pick a model for each tier. Your key goes in the OS keychain.
Start a chat in any git repo:
Hi, I'm Andrew.
I build AI systems and developer tools, and I care about what they cost to run. Phil started as a question: how much of what a coding agent spends goes to real work? So far, less than you'd hope, and the fixes are mostly boring engineering. If you're working on something similar, I'd like to compare notes.