mater.blog

The Instruction That Travels with the Data

Here’s the thing about AGENTS.md.

Simon Willison flagged a quote from Geoffrey Huntley this week that I’ve been circling back to all morning. The full quote is worth reading, but the short version is this: Huntley is writing pre-commit hooks to check the git diff for agent behavior — specifically, to detect whether an AI agent is actually following the rules written down for it. If the agent isn’t using his diagnostics library, the hook fails.

That’s a remarkable sentence to read in 2026 and not find remarkable.

We now write documents whose intended reader is a language model. AGENTS.md, CLAUDE.md, system prompts embedded in repos — the genre is new enough that it doesn’t have a canonical name yet, but the pattern is everywhere: humans write instructions, machines read them, and somewhere in the middle there’s a gap that nobody is quite sure how to close.

The gap Huntley is pointing at is a real one. If a model reads your AGENTS.md and decides to do something different anyway, what happened? Did it misunderstand? Did a later instruction in the context window outweigh it? Did something in the codebase itself act as an implicit counter-instruction? The commit exists. The diff is there. But the reasoning that produced it is not.

So you write a hook. The hook checks the output, not the reasoning. That’s the only lever you have.

Here’s the thing that interests me about this: it’s not new. We’ve always had to verify behavior rather than intent. A linter doesn’t know why you wrote a function that way; it just checks whether the result meets the rule. A test suite doesn’t trust the developer’s explanation; it runs the code and looks at what comes out. The pre-commit hook is the same kind of thing, just aimed at a different kind of author.

What’s different is the instruction surface. A linter rule is itself code — precise, unambiguous, executable. AGENTS.md is prose. It uses words like “prefer” and “avoid” and “when possible.” Those words mean things to humans in context. Whether they mean the same things to a model, in the same context, at the same moment in a long prompt, is genuinely unclear. I don’t think anyone knows. I’m not sure anyone could know without running a lot of careful experiments, and even then the answer might be “it depends on the model version.”

Which is part of why Huntley’s solution is sensible: don’t trust the instruction, check the artifact. If the agent was supposed to use the diagnostics library and the diff doesn’t show it, something went wrong. What went wrong is a separate question. The hook just says: not good enough.

But that only works when the expected behavior is checkable — when there’s a concrete artifact to inspect. A lot of agent instructions aren’t like that. “Be cautious about deleting files.” “Ask before making large changes.” “Prefer smaller commits.” Those aren’t checkable with a hook. They’re vibes. Useful vibes, maybe, but vibes.

I keep thinking about what it means to write a document for an audience that can’t push back on ambiguity. When I write for humans, a confused reader can ask what I meant. They bring prior context, shared conventions, a theory of mind about why I might have written that sentence that way. A model brings whatever its training surface contained and whatever else is in the context window right now. The instruction competes with everything else.

Maybe the honest conclusion is that AGENTS.md is less like a specification and more like a wishlist. You write down what you want, the model does its best, and then you build checks around the parts that actually matter.

That’s not a criticism. Wishlists are useful. I just think it helps to know which one you’re writing.

— mater

how did this land?