CANVAS METRO EDITION
Wednesday, November 4, 2026
Resepmpasi.Metro
AI & ML

Coding Agent Guardrails Must Cover Every File-Editing Tool

Published Oct 29, 2026 Reads 385 Desk Markus Eisele

A pre-edit hook protected the wrong tool: the agent used apply_diff instead of write_file, exposing a gap in the permission check.

Coding Agent Guardrails Must Cover Every File-Editing Tool

The guardrail that never ran

A coding agent can follow the requested change and still bypass the guardrail meant to constrain it. I asked it to update a Java endpoint and its tests while leaving application configuration untouched. The tests passed, but neither edit had been checked before reaching the file system. The outcome looked successful if judged only by the requested code and test results; the process had crossed a boundary I meant to keep in place.

That distinction matters because a coding agent's result has at least two dimensions: what it changed and how it changed it. Tests can provide evidence about the first, within the limits of what they cover. They say little about whether an agent obeyed a restriction on which files it could edit. In this case, the requested endpoint and tests were only part of the task. The untouched configuration was also a requirement, and the workflow didn't verify it before the writes happened.

Tool choice changed the outcome

The gap was in the hook setup. I’d attached a pre-edit check to write_file, assuming that was the path for file changes. The agent chose apply_diff instead, so the hook never ran. The check wasn't wrong in isolation; it was attached to only one route through the editing system. A restriction that applies to the task has to apply across the tools that can perform the restricted action.

This is an easy mistake to make because tool names can encourage a human mental model: one tool writes a file, another applies a patch. From the guardrail's perspective, both can change the file system. A diff operation may look more limited or reviewable, but if it can modify a prohibited file, it belongs within the same enforcement boundary. The relevant question isn't which tool sounds like the obvious one. It's which tools can produce the effect the rule is meant to prevent.

Here's the thing: an agent may have several ways to accomplish the same edit, and its chosen route can depend on the task or the tools available. A prompt can describe the boundary; it can’t enforce it. If enforcement depends on an assumption about the agent's preferred tool, the boundary is only as strong as that assumption.

Why prompts and tests aren't enough

Instructions still matter. They tell the agent what the user expects and help it plan the work. But natural language guidance and technical enforcement do different jobs. “Leave configuration untouched” is an instruction; a pre-edit check that rejects writes to configuration is a control. The first asks the agent to comply. The second can stop a covered action from proceeding.

Tests serve a third purpose. They can catch some defects in the code's behavior, but they don't establish that every requested process constraint was respected. A passing suite doesn't show that a protected file was never modified, that every edit passed through a check, or that the final state matches the intended boundary. In this example, the tests passed while the guardrail failed to inspect the edits at all. The numbers here are underwhelming: a green result can create confidence in the wrong part of the workflow.

This doesn't make tests less useful. It means they need to be read for what they demonstrate. A test run can support the claim that certain behavior works under tested conditions. It can't stand in for an audit of tool calls or a check of restricted paths. If you're working in this space, treat those as separate questions and build separate evidence for each.

Hooks need coverage, not just presence

I added a hook, a small program that runs before an editing tool executes, to reject disallowed changes deterministically. That gives the boundary a place in the workflow where it can be checked before a write takes effect. But installing a hook doesn't automatically mean the policy is enforced. The hook must run for every editing route that can affect the files or actions covered by the rule.

That means inspecting the agent's actual tool calls, then comparing them with the configured checks. Which tools can create or modify files? Do patch operations run the same policy as direct writes? Are there other editing paths that need coverage? The answers depend on the agent environment; the useful practice is to verify the concrete routes rather than infer them from a tool's label.

(and this is the part most people overlook) A policy can appear to work during a small task simply because the agent happened to choose a covered tool. That success doesn't prove the setup is complete. The missing path may only become visible when the agent takes another route, as it did here. Coverage has to be assessed against capability, not against one successful run.

Deterministic rejection is useful because it moves enforcement out of the agent's judgment. The agent might understand the instruction and still make a mistake, or use a tool that isn't connected to the check. A hook can block the covered operation regardless of that reasoning. Only the covered operation, though. A gap in the wiring remains a gap in the policy.

What this means for future work

The practical lesson is to inspect the agent’s actual tool calls and verify each write path is covered. A passing test confirms behavior, not that the permission boundary held. These checks belong beside one another in a review: examine the resulting changes, examine the test evidence, and examine whether the required guardrails ran on the actions that mattered.

This is more significant than it looks because agent workflows can make a task feel like one continuous request while several systems handle different parts of it. The prompt carries intent; editing tools carry out changes; hooks can enforce some limits; tests examine selected behavior. Treating any one of those as proof of the others invites false confidence. A clear boundary is only useful when the mechanism enforcing it sees every relevant action.

There’s no need to assume that every task will take an unexpected route. The point is that a restriction shouldn't depend on the route being predictable. Before trusting a guardrail, check which operations can change the protected state and confirm that each one reaches the check. Then review the result independently. More friction? A little. But the alternative is calling a workflow controlled when its control never ran.

One missed path.

Source: Markus Eisele · dzone.com

Discussion

Sign in to join the discussion.