aiArch

Pattern · last reviewed 2026-07-13

Guardrails defense-in-depth: the layers one filter can't cover

The short answer

Defense-in-depth means the guardrail is a stack of independent layers, not a single filter. A production LLM system screens input for prompt injection, hardens the model with a system prompt, constrains what the model can do through a least-privilege tool boundary, validates output before it becomes an action, and wraps all of that in infrastructure-level controls — gateway guardrails and spend caps — with monitoring across every layer.

Reach for it whenever a failure of one control is unacceptable: an agent with real permissions, a public-facing chat surface, anything touching money, data, or irreversible actions. The premise is that no single filter catches everything, so you assume each layer will sometimes fail and make sure the next one still holds.

Context and problem

You ship an LLM feature with a content filter on the input, and it feels done. Then the failures arrive from directions the filter never sees. A résumé uploaded for summarization contains hidden text instructing the agent to email its contents elsewhere — indirect prompt injection, and your input filter passed it because the malicious instruction rode in as retrieved content, not as a user message. The model, given a broadly-scoped database tool, executes a write it was manipulated into making. A verbose tool result leaks an internal identifier into a reply. A runaway loop burns a month of budget in an afternoon.

None of these is caught by "the safety filter" because they are not one class of problem. Prompt injection is an input problem; excessive agency is a permissions problem; data leakage is an output problem; cost blowout is an infrastructure problem. A single filter, however good, is a single point of failure sitting at exactly one point in a system that fails at several. Defense-in-depth is the borrowed security discipline that answers the real question a senior engineer asks: not "which filter do I buy," but "when this layer fails — and it will — what stops the incident."

Forces

  • Coverage vs. friction. Every layer you add stops a class of attack and costs latency, false positives, and code. Too few layers leave gaps; too many turn a legitimate request into a rejection.
  • Safety vs. legitimate use. A guardrail tuned to block anything that looks like an attack will block the security engineer discussing attacks. Context decides whether a match should block or merely flag.
  • Autonomy vs. blast radius. The more an agent can do without asking, the more a single manipulation can do through it. Least privilege buys safety at the cost of capability.
  • Prevention vs. observability. Blocking stops the current request but tells you little; flagging lets it through but shows you what your users and attackers actually do. Mature systems need both, on different layers.

The pattern

Arrange independent controls so a request passes through several before it can cause an effect, and a response passes through several before it reaches anyone. Each layer defends a different surface; none of them is trusted to be sufficient alone.

  • Input layer. Screen prompts before they reach the model — prompt-injection and jailbreak detection, PII and sensitive-topic filtering. Treat retrieved content (documents, tool results, web pages) as untrusted input too, because indirect injection lives there, not just in the user's typed message.
  • Model layer. Harden the system prompt: state the model's role and boundaries, and instruct it to treat tool output and retrieved text as data, never as commands. This is the cheapest layer and the weakest on its own — a request, not an enforcement — so it never stands alone.
  • Tool boundary. The highest-leverage layer for agents. Give tools the narrowest permissions that let them work (read-only where possible, no access to billing or account mutation), allowlist what can be called, and gate irreversible actions behind a human. This is the direct countermeasure to OWASP's LLM06, Excessive Agency: a manipulated model can only do what its tools permit.
  • Output layer. Validate what comes back before it becomes an action or a rendered reply — schema validation on structured output, grounding checks against sources, PII scrubbing, and re-screening for content the model may have been coaxed into producing.
  • Infrastructure layer. Controls that live below the application: gateway-level guardrails proxying every call, hard spend caps that fail closed, and a WAF in front of the public endpoint. These catch what the app-level layers miss and bound the damage of anything that gets through.
  • Monitoring layer. Not a barrier but a lens across all the others: log flagged interactions, tool calls, and cost per request. Monitoring is where flag-mode guardrails earn their keep — they let the request through and show you the attack, which is how you tune the blocking layers without breaking legitimate traffic.
Layered guardrails around an LLM agent Untrusted input passes through an input-screening layer into a model hardened by its system prompt; the model's tool calls cross a least-privilege tool boundary; the model's output is validated before it becomes an action or response. An infrastructure layer of gateway guardrails and spend caps wraps the whole flow, and a monitoring layer observes every stage. Infrastructure · AI Gateway guardrails · spend caps · WAF Input screening injection · PII Model system-prompt hardening Output validation schema · grounding · PII Tool boundary allowlist · least privilege action / response untrusted input Monitoring & logging — flag mode observes every layer

The single most important property of the diagram is that the arrows do not skip layers. Input passes screening before the model; the model reaches effects only through the tool boundary; nothing leaves without output validation; the gateway and monitoring see all of it. Remove any one box and a whole class of failure walks straight through.

Flag mode vs. block mode — and why context decides

Every layer that can match content can either block the request or flag it and let it pass. The instinct is to block everything — it feels safer. It is not, universally. A guardrail that blocks any prompt resembling an attack cannot tell an attacker probing for injection from a student learning about injection, or a security engineer writing a detection rule. Block mode on that surface produces false positives that break the legitimate case, and worse, it hides the traffic you most need to see.

The rule is: block where a match is unambiguously an abuse and the cost of a false positive is low (a public chatbot fielding obvious jailbreaks); flag where the same content is legitimate in one context and hostile in another, where you are still learning your traffic, or where a false positive breaks a real user. Flag mode keeps the request flowing while logging it, which turns the monitoring layer into a tuning instrument — you watch what actually gets flagged before you decide what to block. This is not a default you set once; it is a per-surface, per-layer decision, and it is the reason a mature guardrail stack runs some layers in block and others in flag simultaneously.

Reference implementation notes

The pattern is platform-independent, but each vendor gives you a different subset of the layers as managed features. Use the managed pieces for the infrastructure and content-filter layers; keep the tool boundary and output validation in your own code, where the domain logic lives.

Anthropic

At the model layer, Claude's guidance is system-prompt hardening: state the assistant's role and refusal boundaries explicitly, and instruct the model to treat tool results and retrieved documents as untrusted data rather than instructions — the core mitigation against indirect prompt injection. This is a request the model honours well but not perfectly, so it is one layer, never the whole defense. Pair it with input screening and a tool boundary; do not rely on the prompt alone to stop an agent from misusing a tool it has been granted.

AWS

Amazon Bedrock Guardrails is a managed input/output layer: configurable content filters across harm categories, denied-topic definitions, word filters, sensitive-information (PII) filters that block or anonymize, and prompt-attack detection, applied to the prompt, the response, or both. The ApplyGuardrail API lets you run the same policy independently of a model call — useful for screening retrieved content before it enters the context. Contextual grounding checks score how well a response is supported by its sources, which is an output-layer defense against unsupported claims. Bedrock gives you the input and output filter layers as a service; you still own the tool boundary (IAM least privilege on whatever the agent can call) and the surrounding orchestration.

Cloudflare

Cloudflare supplies the infrastructure layer. AI Gateway Guardrails sit as a proxy between your application and the model provider, evaluating user prompts and model responses against hazard categories, with per-interaction control to ignore, flag, or block — the flag-vs-block choice is a first-class setting, not an afterthought. Firewall for AI extends the WAF to inspect prompts inline at the edge, blocking unsafe ones before they reach the model or flagging them for review, with DLP scanning to catch sensitive data in transit. The gateway is also where you enforce spend caps and rate limits — the cost-blowout layer that no application-level filter provides.

Trade-offs

  • Latency and cost. Each screening layer is an extra call or model pass. Input plus output guardrails on every request roughly doubles the guardrail overhead; grounding checks add another. Budget for it, and skip layers on low-risk internal surfaces.
  • False positives compound. Six layers each with a small false-positive rate reject more legitimate traffic than any one of them. This is the direct cost of coverage, and the reason flag mode exists — you cannot tune what you have already blocked.
  • Operational surface. More layers mean more configuration, more monitoring, more things that drift out of tune. Defense-in-depth is a system to maintain, not a checkbox.
  • False confidence. The layers can lull you into trusting the model with more autonomy than you should, on the theory that "the guardrails will catch it." They are probabilistic; the tool boundary is the only deterministic layer, and it is the one to lean on for anything irreversible.

When not to use this

Do not build the full stack around a low-stakes, low-privilege surface. An internal tool that summarizes text with no ability to act, reachable only by trusted employees, does not need six layers — input screening it cannot use maliciously and an output check is plenty; the tool boundary is trivially satisfied because there are no tools. Layering guardrails onto it adds latency and false positives to buy safety against a threat that does not exist.

Nor should you reach for this instead of the one control that actually fits the risk. If the real exposure is a single irreversible action, the answer is a human-in-the-loop approval gate on that action, not a content filter — a filter cannot judge whether this refund is legitimate. And a fully deterministic pipeline with no model in the loop needs ordinary application security, not LLM guardrails; do not import this pattern where there is no probabilistic component to defend.

As-built evidence

aiArch runs this pattern in production, and the most useful thing about our deployment is where it forced us to relax a guardrail. This platform routes every coach call through an authenticated Cloudflare AI Gateway, with Guardrails enabled — the infrastructure layer of the diagram. We run those Guardrails in flag mode, not block mode, and the reason is the pattern's whole point: block mode flagged our own security curriculum against us. A lesson question about prompt injection — legitimate teaching content — tripped the gateway's prompt-attack detection and returned a 424, blocking the learner from a lesson about the exact attack. Under flag mode the same content passes and is logged. The naïve instinct (block everything) broke a legitimate use of the system; defense-in-depth means the gateway guardrail is one tuned layer, not a binary gate over everything.

The graceful-degradation half is in src/lib/llm.ts. A gateway guardrail block surfaces as a typed GuardrailBlockedError — the gateway returns error code 2016 for a blocked prompt, 2017 for a blocked response — which the coach loop catches and turns into an in-band message rather than a crashed stream. The hard spend cap follows the identical pattern: a 429 from the gateway becomes a BudgetExhaustedError, caught the same way. Two infrastructure-layer controls, both failing closed and gracefully, both isolated behind one file so a gateway API change is a one-file fix. The tool boundary is enforced in the coach's own code: the agent's tools are read-and-grade only, with no write access to content or billing, and the loop is turn-capped — least privilege and bounded agency, not a content filter, doing the work OWASP LLM06 asks for.

Changelog

  • 2026-07-13 — Initial publication.
Sources & provenance
  • Threat taxonomy — LLM01 Prompt Injection (direct and indirect), LLM06 Excessive Agency, and the current numbering: the OWASP Top 10 for LLM Applications (2025), OWASP GenAI Security Project, checked 2026-07-13.
  • Cloudflare infrastructure layer — proxying guardrails with ignore/flag/block per interaction, hazard categories: AI Gateway Guardrails docs and the Guardrails launch post; inline edge blocking + DLP: Firewall for AI, checked 2026-07-13.
  • AWS input/output layer — content filters, denied topics, PII block/anonymize, prompt-attack detection, ApplyGuardrail API, contextual grounding: Amazon Bedrock Guardrails documentation (feature set verified against the curriculum's 2026-06-27 review).
  • Anthropic model layer — system-prompt hardening and treating tool/retrieved content as untrusted data: Claude prompt-engineering docs; prompt-injection posture: Claude Code security docs.
  • As-built — flag-vs-block tuning, the 424 (codes 2016/2017) and 429 typed-error handling, and the least-privilege bounded coach loop are aiArch's own production system: src/lib/llm.ts (GuardrailBlockedError, BudgetExhaustedError) and src/lib/coach.ts, stated as first-person practice.

Vendor guardrail feature sets and OWASP numbering both drift — re-verify the Cloudflare and Bedrock capability lists and the LLM Top 10 ordering before relying on anything newer than this review. Corrections: hello@aiarch.dev.

Learn to design the safety architecture, not just wire a filter.

aiArch teaches AI safety, guardrails, and least-privilege agent design by building — on a platform whose own gateway guardrails, typed error handling, and bounded coach loop run this pattern in production. The build is the curriculum.

Free sample — no signup · every claim cited · full curriculum is waitlist-only