Skip to content

Technical paper9 min read

The loosening hidden in a tightening: shipping agent policy changes with replay

One pull request against a procurement agent's policy, followed through rule tests, a 30-day decision replay, monitor mode, staged enforcement and an audit link to the commit, showing why peer review backed by a decision diff beats a change board.

IntertraceSecurity engineering

Field guides from Intertrace security engineering for the people who run AI programs.

October 4, 2026 · 9 min read

Policy as CodeAuthorizationChange ManagementAI Agents
Contents
  1. 01Policy edits fail like deploys do
  2. 02The policy has to be text before anyone can review it
  3. 03The rule tests passed, because they test what the author imagined
  4. 04Replay found what the tests could not
  5. 05Tighten-only layering is what made 17 cases findable
  6. 06Replay is the strongest evidence you have, not proof
  7. 07A week in monitor mode, then one agent at a time
  8. 08Which parts Intertrace runs and which you build
  9. 09The decision in front of you

One pull request against the procurement agent at Brackwater Freight, a fictional freight company, made three changes. Purchase orders over $25,000 would now ask a person. Direct calls to the payments API would be blocked, since payments are supposed to go through the ERP. And, to unblock an onboarding project, an exception let the agent update vendor records without asking. The agent reads purchase requests, checks budgets, creates purchase orders and maintains vendor records, so all three changes touched money.

Two of the three were tightenings, and the change would have been reviewed as one. The third reopened a path a person had been guarding. This paper follows that pull request through a release pipeline built to catch it. Our position: an authorization change is a production change and should ship like one, but the answer is not a weekly change board. It is handing an ordinary peer reviewer a decision diff.

Policy edits fail like deploys do

When an agent's tool list, approval rules or thresholds change, the next thousand calls behave differently. A rule meant to add an approval for large refunds that matches every refund stalls the support queue. An exception meant for one onboarding task that matches any vendor update lets an injected instruction rewrite bank details without a person seeing it. One is an outage of availability, the other of control.

Google's SRE team reports that in its experience a majority of incidents are triggered by binary or configuration pushes [1]. Authorization policy is configuration with unusually high stakes, and in many organizations it changes through an admin console with no review, no test and no record of what it replaced. NIST SP 800-53 already sets the bar for configuration in general: control CM-3 asks organizations to review proposed changes with explicit consideration of security and privacy impact, document the decisions, retain records and monitor change activity, and enhancement CM-3(2) asks that changes be tested, validated and documented before implementation is finalized [2].

The obvious way to meet that bar is the wrong one. DORA's research found that change approval works best as peer review during development backed by automation, that heavyweight approval by external bodies hurts delivery performance, and that there was no evidence a more formal external review lowered change failure rates [3]. Every stage below exists to give the peer reviewer evidence, not to add a committee.

A release pipeline for agent policyFig. 1
Pull requestreviewed diffRule testsunit cases30-day replaydecision diffMonitor moderecord, don't actStaged enforceby agentAudit linkdecision ↔ versionrollbackFLAG ANY LOOSENINGan authorization change is a production change · it ships through the same discipline as code

A change moves from pull request through rule tests, a 30-day replay that produces a decision diff, monitor mode, staged enforcement by agent, and an audit link from each decision to its policy version. Rollback from staged enforcement returns to the pull request, not to a console edit.

The policy has to be text before anyone can review it

Brackwater's change could be a pull request only because the policy lived in a repository: the organization's baseline, a file per agent or role, and named exceptions, all behind required review. If you generate policy, commit the generator's output, because the reviewer has to see the effective rules, not the script that produces them. A console that edits policy in place should be read-only, or should open pull requests instead.

The rule tests passed, because they test what the author imagined

Write rule tests the way Open Policy Agent expects them. In Rego, tests are ordinary rules whose names start with test_, the opa test command discovers and runs them, it can report coverage showing which rule bodies were exercised, and the with keyword replaces input data and functions with mocks [4]. Whatever your policy language, keep those properties: tests beside the rules, coverage that exposes rules no test touches, and mocked inputs so each test pins one call.

Test the boundaries, not the middle. For the $25,000 threshold that means an order just below it, exactly at it and just above it. For a destination rule, the address on file, a lookalike domain and a new address. Add one test for each incident or red-team finding that produced a rule, so that deleting the rule fails CI with the reason in the test name.

Brackwater's tests passed. They were supposed to: they checked the cases the author thought of, and the author thought the exception was about onboarding.

Replay found what the tests could not

Tests cover the cases you wrote; replay covers the cases you had. Take the proposed policy, evaluate it over the inputs of the last 30 days of real decisions for the affected agents, and compare each new outcome with the one that actually happened. The result is a decision diff: how many calls keep their outcome, how many become stricter and how many become looser, each with examples a reviewer can open.

Replay diff for one policy changeFig. 2
18,412 decisions unchangedthe change does nothing to the bulk of traffic, so review effort goes to the rows belowallow → ask236ask → block41ask → allow17NEEDS EXTRA REVIEWILLUSTRATIVE COUNTS · ONE EXAMPLE CHANGE

Illustrative counts from replaying 30 days of decisions: 18,412 unchanged, 236 allow → ask and 41 ask → block from the intended tightenings, and 17 ask → allow loosenings flagged as needing extra review.

Of 18,706 replayed decisions (illustrative counts), 18,412 were unchanged. The 236 that moved from allow to ask were almost all purchase orders above the new threshold, and the 41 that moved from ask to block were the direct payment calls. The 236 is a staffing question for the approvers, roughly eight extra asks a day, not a security one.

The 17 ask → allow results came from the exception, and opening them showed the problem. The exception had been written for vendor updates on any record, and several of the 17 were bank-detail changes on existing vendors that a person had previously reviewed. The fix narrowed the exception to new vendor records created by the onboarding job and gave it a 14-day expiry. The rerun showed zero loosenings.

That is why the pipeline reads the direction of each change, not just the count. Tightenings cost friction, so the question is whether the volume is acceptable. Loosenings cost risk, so each needs a reviewer to confirm it was intended, and the check should fail on any unacknowledged loosening, however small.

Replay outcome classes and what each needs from the reviewer
Change in outcomeDirectionMain riskReview action
UnchangedNoneNone from this changeSample a few to confirm the replay ran against the intended agents and window
Allow → askTighterApproval volume and stalled workEstimate approver load per day and check whether a scoped pre-approval could absorb routine cases
Ask → blockTighterLegitimate work left with no pathConfirm each blocked case has another route or was never legitimate
Allow → blockTighterSilent breakage of a working flowNotify the agent's owner and stage the change by agent
Block → askLooserCalls that used to stop now reach a personConfirm approvers know what to refuse
Ask → allow or block → allowLooserConsequential calls run with nobody involvedOpen every case, require a second reviewer, and record a named reason in the change

Tighten-only layering is what made 17 cases findable

A reviewer can judge a change quickly only if they can reason about it without reloading the whole policy. Layering makes that possible when inner layers can only narrow. The organization layer sets a floor: what is always blocked, what always asks, the data-protection minimums. Each agent's policy tightens that floor for the agent's job. Loosening happens only through exceptions that are named, scoped to one agent and set to expire.

Under that rule most changes are monotonic. An edit to an agent layer can only make that agent stricter, so the reviewer's question is whether it breaks legitimate work, which replay answers. A change to the organization floor touches every agent and gets the widest replay. The only loosening paths are exceptions and floor changes, both rare and both visible in the diff, which is why Brackwater's exception stood out at all. Without the rule, any agent edit might quietly override a baseline, and every review becomes a global analysis.

Replay is the strongest evidence you have, not proof

Replay only sees traffic that happened, so it says nothing about a tool the agent has never called. It sees inputs as they were logged, so if your logs redact arguments, argument-based rules replay against the redacted form. And it cannot predict how agents and the people who run them will adapt to a new ask. Those gaps are what the next two stages are for.

A week in monitor mode, then one agent at a time

Monitor mode shows what happens this week: the new policy evaluates live calls and records its decision beside the enforced one without acting. Run it through at least one full weekly cycle of the agent's work and compare the live diff with the replay diff. If they disagree, either the agent's traffic has shifted or the replay inputs were incomplete, and you want to know which before enforcing.

Then enforce in stages, starting with one agent or with non-production environments. The SRE workbook defines canarying as a partial and time-limited deployment of a change together with its evaluation, with later stages exposing a larger population once earlier ones pass [1]. For authorization the population is agents rather than hosts, and the signals are ask volume, new blocks on calls that used to run, and reports from each agent's owner.

Rollback should mean redeploying the previous policy version from git: one command, no hand edits. Two cautions. Rolling back a tightening is a loosening, so look at what it reopens. And approvals or pre-approvals granted under the new version may not mean the same thing under the old one.

Every decision names the commit that made it

This is the stage that pays off during an incident. Each enforced decision should carry the identifier of the policy version that produced it, beside the deciding rule and layer: held by the organization's payment rule, say, rather than by the agent's own list. Then the question of why a payment ran on the 12th has an answer that names a commit, a pull request and its reviewer, and the question of which decisions a bad change affected becomes a query instead of an investigation. It is also what CM-3 means by documented change decisions, retained records and monitoring of change activity [2]. Record the source commit rather than a build number, so the link survives rebuilds.

Which parts Intertrace runs and which you build

Intertrace supports parts of this directly. Agent policy can be exported, edited and applied with the itr CLI, so changes flow through ordinary code review; proposed access and policy changes can be replayed against the last 30 days of real decisions; layering runs organization → agent → exception, with exceptions that expire after seven days by default and 90 at most; and each decision records its rule and layer. Monitor-then-enforce staging and commit stamps are practices you build around it.

The decision in front of you

Most of this pipeline is engineering work. The part that needs a decision from whoever owns agent risk is narrower: whether the admin console stays a way to change what agents may do. While it does, every control above is optional, because the fastest path to a change skips review, tests and replay. Close that path, require a second reviewer on every loosening the diff reports, and the Brackwater pull request becomes routine.

Sources

Reporting, research and specifications this piece draws on. Links go to third-party sources; analysis and recommendations are Intertrace’s own.

  1. 01The Site Reliability Workbook, Chapter 16: Canarying Releases · Google
  2. 02NIST SP 800-53 Rev. 5: Security and Privacy Controls for Information Systems and Organizations · NIST
  3. 03DORA capabilities: Streamlining change approval · DORA
  4. 04Open Policy Agent documentation: Policy testing · Open Policy Agent

About this desk

Intertrace

Security engineering

Field guides from Intertrace security engineering for the people who run AI programs.

All 22 pieces by Intertrace

Dated October 4, 2026 · added to intertrace.ai October 19, 2026

+ Runtime enforcement

See these controls on your own agent traffic.

Intertrace sits inline between your agents and the models, tools and MCP servers they call, and decides every call before it runs.

Keep reading

All insights →