Compound engineering for the implementation phase
Compaction eats your decisions
Compound engineering for the implementation phase starts with controlling what an agent loads. Reading files, capturing build output, and dumping git status burn tokens fast. A 1M context window sounds like plenty until a single grep across a monorepo lands half the codebase in the transcript.
When the context window fills, the session compacts. Compaction is lossy. A decision made fifty turns ago comes back as a paragraph summary, and the constraint that mattered is gone. The next turn rewrites code you already agreed not to touch.
Prompt caching makes repeated conversation history cheaper to process, but it does not make the context window larger. Load only the material the agent needs.
Share project instructions through AGENTS.md
Put working agreements in a project-root AGENTS.md. The instructions describe how to work in the repo, so they should not depend on a particular model or agent tool:
# Shared agent instructions
- Read the relevant files before editing.
- Use code-review-graph for source navigation when its graph is current.
- Use Worktrunk for isolated feature work.
- Keep replies concise and direct.
AGENTS.md gives coding agents a shared place for project instructions. Agents that recognize the file load it directly. When a tool needs its own entry point, keep that adapter small and point it at AGENTS.md. Hooks and connections remain in each tool’s configuration.
Keep the agent’s own output short
The agent’s own output is context too. Every “Let me check…” preamble, every restated user instruction, every paragraph of closing fluff feeds back into the next turn.
The output rules fit in the shared file:
## Output
- Think before acting. Read existing files before writing code.
- Be concise in output but thorough in reasoning.
- Prefer editing over rewriting whole files.
- Do not re-read files you have already read unless the file may have changed.
- No sycophantic openers or closing fluff.
- Go straight to the point. Lead with the answer or action, not the reasoning.
- Do not restate what the user said. Just do it.
- If you can say it in one sentence, don't use three.
Shorter replies leave more room in the context window. Prompt caching can reduce the cost of replaying previous turns, so reply length alone is not a reliable measure of session cost.
Structural code search with code-review-graph
A grep for a function name returns every occurrence: the definition, every call site, every comment that mentions the name. The agent reads all of them and decides relevance after the fact, billed per token.
code-review-graph (CLI code-review-graph, MCP server) builds a local knowledge graph of the codebase. Symbols are nodes. Calls, imports and tests are edges. The agent queries the graph instead of the filesystem:
query_graph callers_of "parsePost" # who calls this?
query_graph tests_for "parsePost" # which tests cover it?
get_impact_radius "src/utils/slugify" # blast radius of a change
semantic_search_nodes "rate limit" # find code by concept
The response is structural. A list of nodes with locations, not the source lines themselves. The agent reads files only after the graph tells it which ones matter. A typical “where is X used?” turn drops from a fifty-file grep dump to a dozen-node response.
Registration is the friction point. A graph the agent doesn’t know about gets ignored. crg-here is a one-shot zsh function that registers the current repo and builds the graph in one step, idempotent so it is safe to run on every clone:
crg-here() {
local repo
repo=$(git rev-parse --show-toplevel) || return 1
code-review-graph register "$repo" --alias "$(basename "$repo")"
code-review-graph build --repo "$repo"
}
Registration writes to ~/.code-review-graph/registry.json, which a launchd watcher picks up to start indexing in the background. MCP server configuration varies by agent, so it stays outside the shared instructions. The CLI also works when an agent has no graph MCP connection.
Check the graph at the start of a session and refresh it after code changes:
code-review-graph status
code-review-graph update --skip-flows
Each agent can run those commands from its own hook configuration. AGENTS.md tells the agent when to use the graph; a hook can keep the local index current.
Why I removed RTK
I used to run RTK through a PreToolUse hook that rewrote shell commands and filtered their output. I no longer recommend it for this setup. The rewriting caused enough prompt cache misses in my sessions that the smaller command outputs did not justify keeping it.
The agent harness already reused conversation history through prompt caching. A changed cached prefix can miss and require processing again, as prompt caching documentation explains. RTK’s own savings guide says rtk gain estimates the reduction in shell output, not the effect on the whole session’s cost.
I removed the RTK hook and RTK.md import. When a command is noisy, I narrow its output at the source or read the relevant lines after it runs.
What changes in a long session
Compaction is where the agent forgets the constraint that mattered: “don’t touch this file”, “we already rejected that approach”, “keep the public API stable”. Pushing that point from turn 30 to turn 60 can be the difference between one implementation session and a hand-off prompt that restates half the project.
The turns also get less tedious. A graph query returns the handful of call sites the agent needs instead of dumping every textual match for a function name. Focused commands keep build and test output readable.
That changes what you can hand to the agent. A monorepo that used to overflow context on the second grep can stay addressable for a full debugging session. A refactor that touches ten files no longer needs a separate planning phase just to decide which files the agent is allowed to read.
The useful part is boring: fewer interruptions. The instruction file cuts the verbose reply before it becomes part of the next turn. Structural reads stop the over-eager grep before it fills the transcript.
Two gotchas worth knowing
CLI over MCP when both exist
An MCP server adds JSON-RPC framing, a schema header, and tool descriptions to every call. A CLI command returns plain output. For deterministic operations like git, file reads, or a build, the CLI is cheaper. Reach for MCP when the operation is stateful or the schema earns its bytes (Xcode build, browser automation, a graph database).
Images over PDFs
A PDF of an API doc burns thousands of tokens on layout and font metadata before any text reaches the model. A screenshot of the same page is a few thousand tokens of pixels and renders identically for the agent’s purposes. When the source is the rendered page, hand it the image.
The setup now
Shared instructions: AGENTS.md holds the working agreements every coding agent needs.
Tool-specific setup: Each agent keeps its own hooks and connections. A tool that needs another entry point can load the shared file from there.
Command output: I use focused commands and the agent harness’s prompt cache instead of RTK’s rewrite hook.