Skip to content

The Drift Log · Governing agents that write code

Preventing Blind Agent Writes with Build Intent Terminal States

3 September 2026 · 3 min read · 743 words · established

A crystal shard held at a red-lit gateway in a black wall

Prevent agent drift and polluted git history by intercepting file modifications at a Build Intent gate before touching the disk.

An agent given direct write access will eventually trash your git history.

The failure rarely looks like malice or outright garbage. It looks like small, plausible drift. An agent tasked with adding an endpoint modifies an authentication helper. Another, asked to fix a failing test, rewrites the test assertion to match broken behaviour. Because the tool execution layer maps directly to the filesystem or the GitHub API, the write happens the instant the model decides it should happen.

By the time human review occurs, the developer is staring at a 400-line diff across seven files, trying to reverse-engineer why the agent made three tangential edits. The write already happened; the repository is already polluted.

Treating the filesystem as the write target is the mistake. Agent writes need a gate that halts execution until an intent payload resolves to an explicit terminal state.

The limit of post-hoc code review automation

Most teams try to govern agents using the same pipeline they use for humans: git branches, linters, and CI runs. When an agent hallucinates a dependency or alters a core invariant, CI fails, and the developer gets a broken PR notification.

This is standard code review automation, but applied to agents, it fails for two reasons:

  1. Context decay. Once an agent produces a multi-file diff, you can no longer tell which changes were required to satisfy the prompt and which were exploratory drift.
  2. Compute waste. Running a complete integration test suite on an unvalidated, hallucinated edit is an expensive way to learn that an import does not exist.

CI validates the state of the codebase after an operation. It does not validate the operational intent before disk execution. Real agent governance requires moving the control point upstream: intercepting the agent’s decision to modify code before the disk or git index is touched.

The Build Intent contract

A Build Intent gate treats every proposed change as an uncommitted transaction. The agent does not call fs.writeFile or create git commits directly. Instead, it submits a structured payload describing its intended mutation:

{
  "target_modules": ["auth/session.py"],
  "operation": "modify_function",
  "symbol": "validate_token",
  "invariants_maintained": ["no_external_network_calls", "constant_time_comparison"],
  "patch": "..."
}

When this payload arrives at the build gate, execution halts. The gate runs static resolution rules against the intent before applying the patch:

  • Scope boundaries: Does this modification touch files outside the bounded working set?
  • Invariant preservation: Does the proposed change break declared safety or licensing rules?
  • Deterministic verification: Can the changes be evaluated against a reproducible test harness before touching the local working tree?

The gate does not return arbitrary strings or conversational output. It returns a terminal state: APPROVED, REJECTED, or BLOCKED_ON_INVARIANT.

If the intent resolves to REJECTED, the write aborts immediately. The agent receives the specific invariant failure, remains inside its context loop, and can adjust its proposal without leaving orphaned diffs across your working directory.

Wiring terminal states into an MCP server

If you connect your agents via an MCP server, you control the tool surface.

Do not expose raw shell tools or arbitrary filesystem write tools to the agent runtime. Instead, expose a gated tool: propose_build_intent.

Agent Loop -> calls propose_build_intent() -> MCP Server
                                                  │
                                       [ Build Intent Gate ]
                                                  │
                                ┌─────────────────┴─────────────────┐
                                ▼                                   ▼
                         State: APPROVED                     State: REJECTED
                                │                                   │
                      Apply patch to disk                  Return error payload
                                                               (No disk write)

When the tool executes:

  1. The MCP server validates the incoming patch schema and invariant declarations.
  2. It evaluates the patch against repository policies in memory or in an isolated scratch space.
  3. It emits a terminal state.
  4. If and only if the state is APPROVED, the server flushes the change to the repository.

This decouples the agent's generative reasoning from the actual modification of the project. The agent can be as non-deterministic as its model makes it; the interface to your code remains strictly deterministic.

What to build on Monday

You do not need to rewrite your entire developer platform to stop blind agent writes. You can enforce this boundary in a few concrete steps:

  1. Audit your agent's tool definitions. Remove unrestricted file-writing primitives (write_file, edit_file, or raw bash execution) from the tool list provided to the model.
  2. Introduce an Intent Shim. Replace the write tool with a single command that accepts a diff and a declared scope list.
  3. Enforce hard failure modes. If an agent attempts to touch a file outside its declared target scope, fail the tool call immediately with a structured error. Do not fall back to partial writes.

Once you separate the agent's intent from the write itself, you stop reviewing messy, drifting diffs and start enforcing precise mechanical contracts.

This post supports the longer argument in Governing Code Agents at the Build Intent Gate.

Keep reading

Next in the log

The Strategic Master Library · written and reviewed under the house's own epistemic rules: nothing claimed that we cannot show.