Your AGENTS.md is advice, not a security control

    Paul Bleicher
    2026-10-13

    "We already put our security rules in AGENTS.md."

    It's one of the first things security teams tell us on Guardrails calls. It's a reasonable place to start. Every coding agent reads a root instruction file, so it's the obvious place to write down how your application handles tenants, roles and approvals: the business rules coding agents don't know.

    AGENTS.md is a good place for conventions and a weak place to rely on for security. The agent reads it at the start of a session, as advice, and nothing tells you whether it held on a given change. A security guideline has to reach the agent when the code it covers is edited, and something other than the agent has to check it.

    AGENTS.md is the right place for conventions

    Rules files earn their spot. Build and test commands, code style, where things live, which HTTP client to use. These are short facts that apply to almost every change, and the agent needs them on almost every turn.

    Security guidelines are the opposite. A real application has dozens of them, and each one matters to a handful of files.

    Every line loads on every request

    Anthropic's guidance for CLAUDE.md is to keep it "under roughly 200 lines", because "every line is loaded into context on every request, so each one should be worth its cost." The Claude Code docs add that "longer files consume more context and reduce adherence." Codex has a hard cap: it stops adding instruction files once they reach 32 KiB combined, by default.

    Now write down the rules a real application relies on. Every read of a Report is scoped to the caller's organization. Role changes are admin-only. Refunds over $10,000 keep their two-approver step. A plan downgrade revokes the seats above the new limit. That's one rule per resource and per sensitive action.

    AGENTS.md has a budget of about 200 lines, and conventions such as build commands, code style and project layout take most of it. The security section that fits says only: always check authorization. The rules a real application needs, one per resource and sensitive action, run past line 200.

    They don't fit next to the build commands. So the security section either gets compressed into "always check authorization", which the model already knew, or it grows until it crowds out everything else in the file.

    The rule arrives at session start, not at the edit

    Claude Code loads CLAUDE.md into every session. Codex "builds an instruction chain when it starts (once per run; in the TUI this usually means once per launched session)", in OpenAI's words.

    The agent then works through the task: reads files, runs tests, edits a migration. Forty tool calls later it opens billing/refunds.ts. The rule that matters is in a file it read before the task started, buried under everything that has entered the context since.

    The same coding agent session twice, from session start to tool call 41, an edit to billing/refunds.ts. With AGENTS.md, the whole file loads at session start with the refund rule on line 142, next to the build commands, and nothing arrives at the edit. With a Konvu Guardrails hook, nothing is added to context at session start; at the edit, the hook refuses it once with the rule: refunds over $10,000 need two approvers, call requireApproval() before issueRefund(). The agent resubmits, and the edit goes through.

    Compare the two versions of the same guideline:

    Always check authorization before returning or changing data.

    Refunds over $10,000 need two approvers. Call requireApproval() before issueRefund(), like the other refund paths in billing/.

    The first is what fits in a rules file. The second is what changes the code. It's also the kind of rule you can't afford to load into every session for every resource. We walked through seven rules like this one and how each one breaks.

    Nothing checks that it held

    An instruction file is input to a model, and the model decides what to do with it. Anthropic says so in the Claude Code docs: "Claude reads it and tries to follow it, but there's no guarantee of strict compliance." The same docs draw the line: "Unlike CLAUDE.md instructions which are advisory, hooks are deterministic and guarantee the action happens."

    One team we talk to pushes signed security instructions into every coding agent in their company. When it launched, "the expectation from leadership was, oh cool, now we've solved that problem, the LLM can never do anything bad." They've had to correct that:

    "It's steering the agent... It's not actually stopping the agents from doing something unless there is a hook that does that. So, you know, we can provide guidance, but it's not strict guardrails."

    The file also only reaches the agent. Code written by hand never sees it. And when the change lands, nobody has a record of whether the rule was considered. So you can't answer the question security teams ask us: "How do I know? How can I prove that?"

    Making it work takes full-time engineers

    That team built far more than a file: a small binary that installs alongside every coding agent on company machines. Every five minutes it pulls the latest instructions from their backend, checks the signature, and writes them into the root instruction file: CLAUDE.md, AGENTS.md or copilot-instructions.md. It loads different rules per project, one set for a C++ codebase and another for a React app. It installs hooks for dangerous actions like a force push, and it reports every time a hook steers the agent.

    They've spent about five months on it so far:

    "It took an awful lot of engineering effort... And it's taken, you know, 2 of my engineers out full-time."

    The work doesn't stop at launch. Every new kind of project needs its own rules, and every rule has to follow the code as it changes. Once a comparable product exists, they told us, it's "likely the thing that we would look to buy rather than to continue to build and maintain."

    The file is the cheap part. Distribution, refresh, per-project rules and hooks add up to a product, and someone has to staff it.

    What a security control needs that a rules file doesn't

    Scoped to the code it covers. The refund rule should reach the agent when it edits refund code, and stay out of the way when it edits the CSS.

    Delivered at the edit. The right moment is when the agent is about to change covered code, not when the session opens.

    Checked independently of the agent. Something other than the model that wrote the code has to confirm the rule held, on agent-written and hand-written code alike.

    Recorded. Every change that touched a rule should leave a decision: held, broken and fixed, or a new exception someone approved.

    Kept current. The rules have to follow the code. A guideline that points at a helper you renamed last month is worse than none.

    Nested AGENTS.md files, one per directory, get you part of the first one. A rules file gives you none of the others.

    Where Konvu Guardrails fits

    We built Konvu Guardrails around that list.

    What a security control needs, AGENTS.md next to Konvu Guardrails. Scoped to the code it covers: AGENTS.md partly, with one nested file per directory; Guardrails Controls match the files and code they cover. Delivered at the edit: AGENTS.md loads when the session starts; a Guardrails local hook steers the agent before each write. Checked independently of the agent: only the agent reads AGENTS.md; Guardrails runs a PR check on every pull request, hand-written code included. Recorded: AGENTS.md has no record of whether it held; Guardrails records every steer and every PR finding, per Control. Kept current: AGENTS.md is edited by hand, so it drifts from the code; Guardrails Controls are mapped from your code and kept current.

    Konvu maps the Controls you already have, from your security standards, pentest reports and code, and detects new ones from your threat model and business context. Each Control links to the code or document it came from, and Konvu keeps the mapped Controls current as the code changes.

    A local hook in Claude Code, Codex or Cursor matches each edit against the Controls, with no model and no network call. When an edit touches covered code, the hook stops it once and gives the agent the Control and the lines it's based on, then lets it carry on. The hook steers the agent rather than blocking it. In Claude Code, rolling it out to every developer is one managed setting.

    A PR check reviews every pull request against the same Controls, including code written by hand. Make it required and a failing check blocks the merge. Hooks and the PR check are independent: use either one, or both.

    The rules you already wrote don't go to waste. Add them in plain language and they become Controls, steered and enforced like the mapped ones. Lucas wrote up how it works in detail.

    The hook is still guidance. It puts the right rule in front of the agent at the right moment, and the agent can still get it wrong. That's what the PR check is for.

    Takeaway

    Keep your AGENTS.md. Put your conventions in it.

    Then take each security rule in it and ask one question: what checked that it held on the last change? If the answer is "the agent read it", you have useful advice and no control.

    Sources