Backpressure Is the Whole Game
Last Tuesday I asked an agent to refactor getUserById in a Go codebase. Clean diff. Tight commit message. Fourteen lines changed. Then I ran go build.
47 callers. The agent changed the function signature -- renamed it, altered the return type -- but it had no idea those 47 other call sites existed. It couldn't. The context window held maybe 4 files. The codebase had 380.
The agent wasn't stupid. It was blind.
What backpressure means here
The term comes from systems engineering: backpressure is the signal a downstream component sends upstream to slow down, change course, or stop. In plumbing it's literal pressure. In TCP it's window sizing. In agent-assisted coding it's the information that flows back to the agent before it writes code that breaks things.
Other people have written well about adjacent problems. banay.me describes verification stacks -- layered checks that catch errors after generation. hlyr.dev writes about context-efficient output compression -- reducing the token cost of feeding errors back. Both correct. Both focused on the reactive side: errors happen, then you catch them, then you feed them back.
The question that kept bugging me: what if the agent knew about the 47 callers before it touched the function? Not after the build failed. Before it wrote a single line.
That's the difference between reactive error correction and proactive structural enforcement. The first one costs you 6-8 build cycles. The second costs you one keel discover call.
Timing matters
Here's the reactive loop in practice:
- Agent changes function signature
- Build fails with 47 errors
- Agent fixes the first 8 callers it can see in context
- Build fails with 39 errors
- Agent requests more files, fixes 12 more
- Build fails with 27 errors
- Repeat 4-6 more times
Each cycle burns context tokens. Each cycle risks the agent introducing new errors while fixing old ones. By cycle 5 the agent is spending more tokens on error-correction overhead than on the actual refactor. I've watched this happen in real sessions -- an agent that started with 80k tokens of headroom hitting the window ceiling by the third rebuild.
The proactive loop:
- Agent runs
keel discover <hash>-- sees 47 callers, their files, their line numbers - Agent plans the change across all call sites
- Agent writes the refactor in one pass
keel compileconfirms clean
One pass. No rebuild cascade. The total token cost is lower because you're not round-tripping through build errors.
keel in action
Three real enforcement scenarios. Each runs in under 200ms.
Broken caller detection
Type drift
Wrong-module placement
Every violation includes an error code, the exact file and line, a hash for graph lookup, and a concrete fix hint. No stack traces. No 200-line compiler dumps. Just the signal.
Context window economics
HumanLayer's research on context window management identifies a "smart zone" around 75k tokens where agents perform best. Below that, they lack information. Above that, they start losing coherence -- attention degrades, instructions get dropped, hallucination rates climb.
A go build on a broken codebase dumps 200+ lines of errors. That's ~2,000 tokens of raw compiler output, most of it redundant (the same root cause repeated across 47 callers). The agent has to parse all of it, deduplicate mentally, figure out which errors are cascading from which root cause.
keel compile outputs ~15 lines for the same scenario. Deduplicated. Grouped by root cause. Each error has a fix hint that tells the agent exactly what to do. keel discover front-loads the structural context so the agent can plan the change before making it.
The cheapest token is the one you never generate.
Where keel fits
There's no single tool that catches everything. The verification stack is layered:
Types tell you a value is the right shape. Lints tell you the code follows style rules. Tests tell you the code does what it should. None of them answer: "does this function still connect correctly to the 47 other functions that depend on it?"
That's structural correctness. Cross-file, cross-module integrity. keel builds a graph of every function, every call edge, every import relationship -- and validates that graph after every edit. It doesn't replace your type checker or your test suite. It catches the class of errors that neither of them catch well: the silent breakage that happens when an agent modifies one node in a graph it can't see.
Build the loop once
No config. No dependencies. Just a binary that knows your code graph.