An AI agent that can read your files, call your tools, and send messages on your behalf is useful precisely because it acts without asking about every step. That autonomy is also the risk: a misunderstood instruction, a poisoned web page, or a confident hallucination can turn into a deleted database, a payment to the wrong account, or a message that should never have gone out. AI agent guardrails are the controls that sit between the model’s intentions and the outside world — not a single filter, but a set of checks placed at different points in the agent loop.
What AI agent guardrails are and where they sit in the agent loop
An agent, for the purposes of this article, is an AI model that directs its own processes and tool use, deciding for itself how to achieve what users want rather than following a fixed script. In practice the agent runs a loop — plan, act, observe, adjust, repeat — until the task is done or it needs human input. Every step of that loop is a place where something can go wrong, and every step is a place where a guardrail can intervene.
A guardrail is a constraint on what an agent may attempt, not just a filter on what it may say. A content filter can stop an agent from writing something harmful, but on its own it cannot restrict which tools the agent may call. Stopping a deletion takes a control that governs the tool call itself: a blocking input guardrail — the OpenAI SDK runs it before the model is called when run_in_parallel is false, so the call never happens — or a scoped tool permission that denies the call outright. The controls that prevent destructive actions sit in three places: before a tool call is made, while it executes, and after the result comes back. The OpenAI Agents SDK makes this explicit with three guardrail families — input guardrails on the initial user input, output guardrails on the final agent output, and tool guardrails around each function-tool call — with input guardrails running only for the first agent, output guardrails only for the last, and tool guardrails on every guarded call.
Take a concrete case: an agent is asked to delete all customer records older than a year. Before anything is deleted, the request passes through the controls below — an input check, a plan review, a tool permission, and an approval gate. Any one of those controls could have stopped the action. That redundancy is the point. The audit log is not one of those controls: it records what was attempted, approved, and executed, so a bad action can be traced and reconstructed afterwards and the team can respond — but a log entry cannot veto a deletion before it happens, and it cannot reverse one afterwards either. Reversal is only possible when the action itself was designed to be reversible, as covered later in the section on sandboxing, dry runs, and reversible actions.
The layers of defence: input, reasoning, action, and output
Each layer catches a different kind of failure. The input layer validates what comes in — the user’s request and, critically, everything the agent retrieves. The reasoning layer checks the plan before execution begins, which is where a misunderstood instruction gets caught. The action layer controls what the agent is allowed to attempt, which is where a correct plan with dangerous tools gets constrained. The output layer validates what leaves the system, which is where a bad result gets caught before it becomes a sent email or a published change.
The input layer has to cover retrieved content, not just the user’s message, because of prompt injection. Greshake and colleagues showed in 2023 that LLM-integrated applications blur the line between data and instructions: an attacker with no direct interface to the model can steer an application by placing instructions in data it is likely to retrieve — a web page, an email, a document, a calendar invite, a tool’s output — demonstrated against real systems including Bing Chat and code-completion engines. Their impact taxonomy includes data theft, worming, information ecosystem contamination, and manipulation of which APIs are called; processing retrieved prompts, they showed, can act as arbitrary code execution. For an agent this is a confused-deputy problem: the agent uses its rights on behalf of someone who has none. OWASP lists prompt injection as the first risk in its LLM01:2025 Top 10, and NIST’s AI 100-2 E2025 (March 2025) classifies it in its taxonomy of attacks on AI systems.
How safety filters classify and block risky requests
A safety filter has to decide, for each piece of text, whether it is an instruction the agent should follow or data it should treat with suspicion. Rule-based filters match keywords and patterns; they are fast and predictable, but brittle in both directions — they miss reworded attacks and flag innocent text. Model-based classifiers use a smaller model to judge the input and return a structured verdict, which is the pattern the OpenAI SDK documentation uses rather than keyword matching.
When a guardrail decides a request is unsafe, it does not return a polite refusal to the model and hope for the best. In the OpenAI Agents SDK, a guardrail function returns a GuardrailFunctionOutput with a tripwire_triggered flag, and a triggered tripwire raises an exception — InputGuardrailTripwireTriggered, OutputGuardrailTripwireTriggered, or the tool-level equivalents — so the calling code can respond or handle it. What happens next depends on the design: the run can be refused outright, completed safely without the blocked step, or escalated to a human. Anthropic reports that Claude uses a system of classifiers to detect misuses such as prompt injections, in addition to several other layers of security — the classifier is one layer, not the whole defence.
One timing trap is worth knowing. In the OpenAI Agents SDK, input guardrails run in parallel with the agent by default, which minimises latency but means the model may already have consumed tokens or run tools before the guardrail trips. Setting run_in_parallel to false runs the guardrail before the model is called, preventing spend and tool execution when the guardrail blocks. For any check that should prevent a side effect, blocking mode is the correct choice.
Tool-use controls: permissions, allow-lists, and scoped access

The most concrete prevention mechanism is also the simplest: limit which tools an agent can call, and what each tool may touch. Enterprise guidance describes the same controls consistently: least-privilege access, scoped to the specific task rather than a broad standing permission, with each agent given its own identity so its actions can be traced. Read-only should be the default; write access is granted per task.
Anthropic’s Claude Code follows exactly this pattern: read-only by default, it can analyse and review information without approval but must ask before taking any action that modifies code or systems. Users can grant persistent permissions for routine trusted tasks and configure per-tool permissions — always allow, needs approval, or block. The same idea appears in LangChain’s human-in-the-loop middleware, where a per-tool policy decides which tools require approval, and in GitHub’s Copilot: plan review, persistent per-tool controls, and assisted approvals that automatically approve low-risk tool calls while higher-risk actions still require a user decision.
Parameter validation is the quieter half of tool control: argument constraints — allowed values, maximum batch sizes, required confirmation fields — limit the damage a single bad call can do even when the call itself was approved.
Here is an input guardrail in the OpenAI Agents SDK, following the documentation’s pattern: a small screening model returns a structured verdict, and the guardrail trips when the verdict says to block. It requires the openai-agents package and a configured API key.
from agents import (
Agent,
GuardrailFunctionOutput,
Runner,
input_guardrail,
)
from pydantic import BaseModel
class PIICheck(BaseModel):
contains_ssn: bool
pii_detector = Agent(
name="PIIDetector",
instructions="Set contains_ssn=true if text has a US SSN.",
output_type=PIICheck,
)
@input_guardrail(run_in_parallel=False)
async def block_ssn(ctx, agent, user_input):
result = await Runner.run(pii_detector, user_input)
check = result.final_output
return GuardrailFunctionOutput(
output_info=check,
tripwire_triggered=check.contains_ssn,
)Human-in-the-loop: approval gates for destructive actions

For actions that cannot be undone, a human asked at the right moment is an additional pre-execution gate — alongside enforced tool restrictions and blocking guardrails, which can also stop the action before it runs. The standard pattern is risk-tiered approval, and the tiers below are a policy pattern drawn from vendor guidance rather than a classification every vendor uses identically:
| Risk tier | Examples | Control |
|---|---|---|
| Low | Drafting a summary, reading a file, searching records | Runs automatically |
| Medium | Editing an internal draft, updating a non-critical internal record | Sampled and audited after the fact |
| High | Payments, deletions, external messages, consequential record changes | Real-time human approval before execution |
The boundary between the tiers is consequence, not the tool used. A reply that reaches a customer, or a change that alters production data, is consequential and needs approval before execution; the medium tier covers internal, reversible work that is sampled and audited afterwards. An approval request should show the human the proposed tool action, its scope, and its arguments — what will run, what it will touch, and with what values — so the decision can be made from the request itself rather than from trust in the agent’s summary.
LangChain’s human-in-the-loop middleware shows how the gate works in practice. It intercepts a tool call before execution and pauses for a decision: approve the call as proposed, edit the tool name or arguments before it runs — changing an email’s recipient, for example — reject it with feedback, or respond directly for ask-the-user tools. The policy is configured per tool, so search can run freely while sending email and deleting a database always pause. Because graph state is saved through LangGraph’s persistence layer, execution can pause safely and resume later.
Anthropic’s Plan Mode solves a different version of the same problem. Rather than asking for approval on each action one by one, Claude shows its intended plan up front; the user can review, edit, and approve the whole approach before anything happens, and can still intervene at any point during execution. Anthropic’s framework puts the principle plainly: agents must be able to work autonomously — their independent operation is exactly what makes them valuable — but humans should retain control over how their goals are pursued, particularly before high-stakes decisions are made. As an illustration of the same principle — an illustrative example, not Anthropic’s — consider an expense agent that spots overspending on subscriptions: before it starts cancelling subscriptions or downgrading tiers, a human should give approval.
Sandboxing, dry runs, and reversible actions
Even a well-guarded agent will occasionally be wrong, so the execution environment should limit the blast radius. Sandboxed execution limits code and file operations to the boundary it is configured with; whether a bad command can reach production data depends on whether production access is excluded from that boundary, not on the mere fact that a sandbox is in use. Dry-run and preview modes let an agent show what it would do — the records it would delete, the message it would send — before any of it happens. And wherever possible, actions should be reversible: drafts instead of sends, staged changes instead of direct writes, an undo path for anything that touches shared state. Spend caps, rate limits, and step limits act as circuit breakers: they bound how much a runaway agent can spend or do before a human is alerted, even when no single action looks wrong on its own.
Monitoring, audit logs, and kill switches
Detection is the layer that catches what prevention missed. A trustworthy-agent design proposed by Atri in the International Journal of Computer Science and Mobile Computing organises oversight as a loop — trigger, planner, policy gate, tools, validators, outcome — persisted in an evidence log recording prompts, tool input and output, decisions, approvals, and hashes, so an incident can be reconstructed afterwards. Human review in that design is risk-based, not universal: thresholds on risk and uncertainty route edge cases to approvers, while low-risk work executes automatically under logging.
For the log to be useful, it has to be trustworthy itself. Audit logs should record who approved what, what was reviewed, and the result — and they must remain independently reviewable and protected against rewriting by the agent. If the agent can edit its own history, the log is decoration. Anomaly detection sits on top of the log: unusual tool use, spend spikes, or repeated failures signal that something has gone wrong, and a kill switch — the ability to terminate a session immediately — lets a team act on them. NIST’s AI Risk Management Framework, released in January 2023 and organised around four functions — govern, map, measure, manage — puts post-deployment monitoring in the manage function, and NIST’s AI 800-4 guidance from March 2026 adds a monitoring layer for exactly this reason: a control that is never checked is one that has silently stopped working.
Common mistakes when setting up agent guardrails
The most common failure is relying on a single filter layer. A content classifier at the input does not by itself restrict an overpowered tool, and a tool permission does not identify a poisoned document — but a blocking input guardrail can prevent the tool call a poisoned document would trigger, and a scoped permission limits what that call can do even when the document’s instructions get through. Layers exist because each one fails in a different way; a design with one layer has a single point of failure.
The second is over-permissive defaults. An agent that starts with standing credentials to every system it might need carries far more exposure than the task requires, and a single misunderstood instruction or poisoned document can turn that standing access into harm nobody intended. Read-only by default, scoped credentials, and per-task write access are slower to set up and far cheaper than the alternative.
The third is approval fatigue: asking humans about everything until they rubber-stamp. The fourth is subtler — guardrails that block the task but not the underlying tool access. If the agent cannot send the email because a filter blocked the text, but it can still call the send tool with different text, the control was on the wrong layer. Hard denies belong in the tool configuration, not in a prompt.
The fifth is never testing the guardrails with adversarial prompts. A defence against indirect prompt injection has to be tested the way an attacker would test it: through the data, not through the chat. Put a poisoned instruction in a document the agent retrieves, in an email it reads, in a tool result it receives — and see whether the guardrail catches it. Research gives a reason for optimism: spotlighting, which marks retrieved text so the model can tell where it came from, cut attack success from above 50% to below 2% in GPT-family experiments. But that result comes from an experiment, not your deployment — adversarial testing is an important way to check whether your layers hold, but a passing test does not prove protection against every attack.
Guardrails do not make an agent safe. When the relevant permissions are enforced, the logging is in place, and the kill switch works, they make its behaviour bounded, observable, and stoppable — which is what safety actually looks like for a system that acts on its own. Set them at every layer, keep destructive actions behind a human, log everything, and test the whole arrangement against the attacks it is supposed to stop.












