Agent Automation Without Losing Engineering Control
How MCP tools, the Context Engine, CodeGraph, and checkpoint recovery keep an AI agent's actions bounded and inspectable
AI Systems·Advanced·9 min read · July 6, 2026
The Beginning
At some point this repository stopped being a place I coded in by myself and became a place an AI agent — Claude Code, specifically — did real work in too: reading files, editing across modules, running commands, calling MCP tools. That's a different kind of collaborator than a linter or a CI check, and early on I didn't have a good answer for what happens when it gets something wrong in a way that isn't obviously wrong.
The First Solution
The first fix was the obvious one: write more into CLAUDE.md. Every time I noticed the agent miss a rule — evidence selection has to stay deterministic, no shell interpolation in a Python spawn call, content always needs both languages — I'd add a line telling it not to do that again, and remind it again at the start of the next session if it slipped.
What Broke
That worked for a while, in the sense that a single flat instructions file can absorb quite a lot before it stops working. What actually broke wasn't correctness in any one instance — it was that the failure mode I was worried about wasn't "the agent writes bad code," it was "the agent writes code that looks completely fine and quietly violates an invariant nobody told it about," because that invariant only lived in my memory, not in anything the agent could check for itself. As the number of subsystems grew — cover letters, CVs, photography, Ask Vikram, MCP, an admin surface for each — a single instructions file couldn't hold all of that "why" without becoming unreadable, and even when it did hold the rule, the agent still had to guess which parts were relevant to the task in front of it.
The other thing that broke was continuity. Sessions get interrupted, compacted, or simply end mid-task, and the next session would either re-derive context it already had — slow — or worse, continue on a stale assumption because nothing forced it to check what had actually changed.
The Decision
The tempting fix for "the agent doesn't know what's relevant" is a smarter router — embeddings, or a small classifier, deciding what context to load for a given task. I considered it and rejected it, for a reason that had nothing to do with whether it would work: a routing layer built that way would itself need the same security and correctness review as any other LLM-facing surface in this repo, and I didn't want to add a probabilistic dependency to the thing whose entire job is keeping the agent grounded. I chose a static, twelve-category lookup table instead — a JSON manifest, validated the same way code is, that a session pattern-matches against by eye. It's less clever. It's also fully git-reviewable, and it doesn't need its own threat model.
The second decision was about what automation is allowed to do once it notices something. Every hook in this system — session start, pre-commit, pre-push, the checkpoint writer — reports or blocks. None of them fix, commit, or apply a change on my behalf. Even the one place a second model enters the loop, drafting a commit message from the staged diff, stops short of actually committing anything without an explicit yes from me. I didn't want a system that's technically safer but that I'd stopped actually reading the output of — the value of "the agent proposes, I decide" only holds if that line stays visible in practice, not just in the docs.
The New Architecture
Task
↓
context-engine/routing-manifest.json (static, 12 categories, no LLM)
↓
knowledge/ concepts + CodeGraph entry points (loaded, not memorized)
↓
Edit
↓
Hooks: report or block, never auto-fix
↓
Checkpoint (session state reconstructed automatically)
↓
Commit draft (second model proposes, I confirm — y/e/n)
The knowledge layer underneath this treats knowledge/ the way a compiler treats source code — something to validate and lint, not something written for me. Seven validators check metadata, links, and staleness against git history; the one fully mechanical artifact (index.md) regenerates from validated frontmatter, and everything requiring actual judgment goes through a proposal a human still has to accept — not because I don't trust automation with small things, but because I wanted one clear line between "mechanical" and "judgment," not a blurry one.
Lessons Learned
The most honest thing I can say about the proposal framework — Proposal → Review → Accept → Apply — is that it exists in full and has zero registered generators today. I built the scaffolding ahead of the automation that was supposed to use it, on the assumption that having the framework ready would make writing the first generator easy when the need showed up. The need hasn't shown up yet, and I'm not sure anymore whether building ahead of demand was foresight or just enthusiasm for the framework itself.
The MCP documentation drift I mentioned in the platform's history — mcp/README.md still describing bearer-token auth as primary after the system moved to OAuth 2.1 — is, in retrospect, the single best piece of evidence that this whole guardrail system is necessary rather than paranoid. It's exactly the class of silent divergence between what's written and what's true that the knowledge layer's staleness checks exist to catch, and it happened in a corner the checks didn't yet cover.
Looking Forward
Writing the first knowledge-builder proposal generator — most likely something small, like flagging a concept file whose updated: date has drifted from its cited source's git history — is the concrete next step that would make the proposal framework worth having rather than a well-built path nobody's walked down yet. I'd also like bun knowledge:validate and the index freshness check running as a blocking CI step, not just a local git hook — HUSKY=0 is a documented, legitimate way to skip hooks, which is exactly why it shouldn't be the only thing standing between a violation and a merge.
Takeaway
None of this scaffolding makes the agent smarter. What it does is make sure that whatever the agent decides, I can always tell whether it acted or proposed — and that line staying visible is the only reason I'm comfortable giving it as much access as it has.