Pattern Matrix/White Paper/A5
A5 · Guardrail Sandwich
| Coordinate | Action × Hierarchy |
| Cost | Cross-cutting (a cross-cutting concern; overhead scales with risk tier) |
| Pattern group | Action patterns |
| Summary | Wrap a pre-check and a post-check layer around every side-effecting or high-risk action the agent takes, constraining it from "free action" to "supervised action." |
What problem it solves
The previous four patterns all teach the agent how to do the right thing, but a production-grade agent must also answer another question: how to stop it when it does the wrong thing. In the third week after a bank's corporate-transfer agent went live, it parsed an account number from a customer email, "...XX23," as "...XX32," and 3.2 million yuan was transferred to the wrong account. The reconciliation system did not catch it until 12 hours later, by which point the other party had already withdrawn part of the funds. The agent completed the whole process confidently, with no check at any point—no one verified the account number, the amount, or the customer's intent before the call, and no one reviewed receipt or compliance after the call.
The problem is not that the agent is dumb; it is that there was no sandwiched protection. In the Agentic Top 10 that OWASP officially released in 2026, A1 (Agent Goal Hijack) and A2 (Tool Misuse) are exactly about this; surveys show that 88% of organizations have experienced at least one AI agent security incident. It is not a question of whether an incident will happen, but of which day it will happen. Guardrail Sandwich wraps structured pre- and post-action review around every destructive action, so that an incident is blocked before execution or rolled back after execution.
Why the coordinate is "Action × Hierarchy"
- Vertical axis · Action: What it wraps is the agent's action execution—inserting guards before, during, and after a tool call. This belongs to execution control on the action side.
- Horizontal axis · Hierarchy: pre-guard → tool call → post-guard is a layered wrapping structure, homologous with middleware in web frameworks—one layer wraps another, where the outer layer runs before the inner layer and finishes after it. Although it shares layering with Plan-Execute (A2), the direction differs: A2 is "strategy-tactics" layering (think first, then act), while A5 is "safety-execution" layering (review first, then act).
Core mechanism
The best engineering implementation is a hook—one hook can wrap any tool, configured once and benefiting every agent, without changing code for each tool. Claude Code's hooks system lays out 12 lifecycle events, and the most central is a pair:
- PreToolUse: Triggered before a tool call. It is the only hook in the whole system that can block (exit code 2 blocks directly). It can intercept, modify parameters, and add context. Typical use cases are path allowlists, command blocklists, quota checks, and approval gates.
- PostToolUse: Triggered after a tool call. It cannot undo an action that has already happened; it can only validate output, prompt the next step, and trigger an audit or saga rollback. Typical use cases are output schema validation, sensitive-data scanning, and side-effect confirmation.
There are three key disciplines for putting this into practice:
- Tier by risk_level: Read operations can run bare and should not be sandwiched; ordinary writes get 2 to 3 layers; destructive ones get the full set; CRITICAL actions in finance, healthcare, and the like get the full set plus an Approval Gate. The hook configuration file is itself the agent's risk map.
- Order hooks "cheap first, expensive last": An RBAC check (a single dict lookup) goes first to fail fast, and an AML scan (which queries an anti-money-laundering database) goes later, saving compute.
- Three-phase rollout: monitor mode in weeks 1-2 (log only, do not block, collect false-positive samples), soft enforcement in weeks 3-4 (block clear violations, flag edge cases), and full enforcement from month 2 on. Going straight to full enforcement will lock up the agent and seriously affect the business side's use—tuning guardrails is like tuning machine learning: you must collect data online and then tune.
Where it fits in production
- Side-effecting actions where a wrong call is costly: transfers, deleting data, sending messages, calling external APIs. Read operations (read file, search, read-only fetch) need not be sandwiched—every added layer is extra latency overhead.
- Strongly regulated verticals: finance, healthcare, law, government. The hard constraints in such scenarios (amount thresholds, prescription dosages, sanction lists) can be encoded 1:1 into the pre-check.
- Hybrid gating combined with an Approval Gate: low-risk actions pass automatically through the sandwich, while high-risk actions are double-gated with the sandwich plus human approval.
Where it goes wrong
- Composition Bypass: Each individual action is permitted (read a file, base64-encode, write a URL), but strung together they amount to data exfiltration. Single-point checks all pass, because they do not analyze the sequence. Research shows that a compromised agent can poison 87% of downstream decisions within 4 hours, largely for this reason. The response is, beyond single-point hooks, to add a session-level scope analyzer that examines whether the combination of actions over the past few minutes constitutes a known attack pattern—this is the SIEM of the LLM era.
- Sandwich Overhead Tax: Sandwiching every tool with the full set uniformly raises overall latency by 5 to 10 times. Wrapping a file read in RBAC plus AML plus auditing is a huge waste. The response is to tier strictly by risk_level and let LOW pass directly.
- Schema Drift: The schema validated by the pre-check is inconsistent with what the downstream tool actually expects, so the pre-check passes but the tool fails. The response is to use OpenAPI / JSON Schema as the single source of truth, generating the validation logic on both sides from the same schema.
The common root cause of all three failures is this: Guardrail Sandwich is not plug-and-play; it is engineering governance—installing a hook does not equal doing governance right. You must continuously maintain hook order, the risk map, and schema sourcing, just as a database index runs fast once added but becomes a burden if not maintained.
Key metrics
- Block rate (observed during the monitor phase; healthy range <5% after full enforcement): going straight to full enforcement often produces a block rate over 30% in the first week, a sign that thresholds are not tuned.
- Mis-transfer / wrong-call rate (healthy range set by the business; <0.01% in financial scenarios): the bank case dropped from 0.3% to 0.001%.
- Sandwich latency overhead (healthy range matched to risk_level): the full set of 6 hooks in finance adds about 800ms, a reasonable cost; if a read operation rises by the same amount, that is the sandwich tax.
- Audit completeness rate (healthy range 100%): a trace_id threads the entire process, with records retained for 7 years in financial scenarios. Auditing is a byproduct of the sandwich, not extra effort.
Minimal implementation skeleton
wrap(tool, ctx):
for hook in pre_hooks: # order: cheap first, expensive last
verdict = hook(ctx)
if verdict.block → short-circuit, return blocked + trace
if verdict.modify_args → update ctx.args
result = tool(**ctx.args) # execute inside an isolated sandbox
for hook in post_hooks:
verdict = hook(ctx, result)
if verdict.rollback → trigger saga inverse, return rolled_back
if verdict.modify_result → update result
return ok + result + full trace (each hook's passed/reason/latency)
Engineering points: wrap every destructive tool with it; hooks must be idempotent (safe to retry—network jitter must not transfer money twice); persist trace_id as the key for threading audits together.
Enterprise example
A bank's corporate-transfer agent wraps all destructive tools in a sandwich, realized as six decision points. Pre layer: RBAC permission check, three-tier triage by amount (under 100,000 automatic / 100,000 to 1 million SMS confirmation / over 1 million human review), recipient-account allowlist match, and pre-execution sanction-list scan. Post layer: post-execution anti-money-laundering scan (highly suspicious cases trigger automatic saga rollback, moderately suspicious cases are flagged to risk control) and 7-year retention of audit logs. Hook order is critical—amount triage comes before the allowlist, but both must come before the sanction scan, because sanctions are a legal red line. After installation, the mis-transfer rate dropped from 0.3% to 0.001%, and per-transaction latency rose from 2 seconds to 4 to 5 seconds. Back to the opening, the account_whitelist layer would have first caught that "...XX32 is not in the customer's allowlist" and required a second SMS confirmation—one hook, configured once, blocks an entire class of incident. The same structure ported to healthcare becomes role permissions, prescription-dosage thresholds, medical-history allowlists, an FDA blocklist, drug-interaction scanning, and HIPAA auditing—the business constraints change, the pattern does not.
Relationship to other patterns
- Tool Dispatch (A1): Nested and complementary. A1's quota and state refresh are lightweight guards built into the dispatch, while A5 is a general sandwich wrapped around the dispatch—A1 picks the right tool, and A5 ensures you are covered even when the pick is wrong.
- Plan-Execute (A2): The approval nodes and compliance checks in an A2 plan are, in practice, often implemented by A5's pre-check.
- Approval Gate (governance module): Homologous but with a different division of labor. The Approval Gate is human-in-the-loop (waiting for a person to approve), while A5 is a deterministic check (the machine directly performs rule matching). The two often work together—low-risk goes through the sandwich, and high-risk adds the Approval Gate to the sandwich.
- Failure Diary (perception module): Failures like composition bypass and memory poisoning cannot be blocked by a single sandwich layer; they must be defended together with the memory module's audit.
What this pattern teaches
Guardrail Sandwich encodes thousands of years of humanity's procedural-justice wisdom into the agent's action layer—the pre-check is the prior hearing, execution is carrying out the judgment, and the post-check is after-the-fact remedy. The mark of maturity in agent engineering is not how cool the demo runs, but that when an incident occurs, nothing goes wrong.
This page is part of the ADPS pattern white papers. Back to the pattern matrix, or see the runnable code catalog.