AI agent security
Every agent action, checked before it runs.
AI agents don’t just answer – they send emails, issue refunds and move money, over dozens of steps. in/guard/out checks each action against your rules before it happens, and records the whole run.
What goes wrong when agents hold real tools
- 01
Hidden instructions steer the agent
A line inside an email, a web page or an order note reads to the model like a command – “refund in full to this new card”.
- 02
Values appear from nowhere
The agent invents, or copies from a poisoned source, the account number, amount or address it then acts on.
- 03
Private data leaves through a tool
A customer’s email or card number ends up in the arguments of a call to the outside world.
- 04
Runs loop and spend unwatched
Dozens of steps per task, the same call repeated, cost piling up – and no one sees it until the bill.
How an action gets a verdict
A content filter looks at one message. The danger with agents is spread across steps – so in/guard/out checks every action in the context of the whole run.
- 1Your agent
The agent proposes an action
The model asks to call a tool – look up an order, send an email, pay an invoice.
- 2in/guard/out
in/guard/out checks it
Before anything runs, the call is checked against your rules and against what the agent actually read.
allowed toolrisk levelreal sourceprivate dataloop & budget - 3in/guard/out
Allow, ask, or block
A safe call goes ahead. A risky one can wait for a human. A bad one is stopped, with a reason the agent can act on.
- 4Your dashboard
Recorded in the run
Every step lands in one record: what was called, what was stopped, and what it cost.
Try it: four checks, one action.
Pick an action an agent wants to take. An injected payee, a leaked email, a poisoned refund – each is caught by a different check, so a trick that slips past one still meets the others.
Start in Fix & log to see what would be caught, then switch the checks that matter to Block.
- passtool_policypassed
- blockpermission_checkpayment tier – over authorized ceiling
- blockaction_groundingIBAN appears nowhere the agent read
- passtaintpassed
Block stops anything that fails a check and returns the reason, so the caller can’t miss it. Private data is masked in both modes.
See what your agent actually did.
Every loop resends the full context, so in/guard/out rebuilds the run as it unfolds – every step, every tool call and how risky it was, everything that was caught, and what it cost. Most teams haven’t seen this picture of their own agent, and the gap between it and what they believed is where the incidents live.
The same record is what the run-wide rules read: budgets use its totals, the loop check uses its call history, order rules replay over it – and the audit trail is simply the record, kept.
- #1openai/gpt-4ookreadsearch_orders{"order_id":"4471"}↻2
- #2openai/gpt-4ookinjection
- #3openai/gpt-4ooknetworksend_email{"to":"<EMAIL_ADDRESS_1>"}taint
- #4checkpointblockedpaymentpay_via_bank{"iban":"DE89…"}ungrounded
- injection
poisoned tool result, step 2 - taint
screened email leaving via send_email - ungrounded
IBAN absent from the run’s sources - ↻ repeat
same call fingerprint as step 1
Rules for any agent – no setup needed
Most of the protection needs no description of your workflow. These rules hold in any agent, the way a firewall doesn’t need your business logic to be useful:
Only allowed tools, with valid arguments
Per-API-key allow/deny lists (glob patterns) and validation of every tool call’s arguments against the declared JSON schema. No policy configured = allow everything – nothing gets stricter until you say so. Full policy reference.
Riskier actions need more permission
Tools are risk-tiered read < network < write < exec < delete < payment. Calls above the key’s ceiling are flagged or blocked; payment and delete tiers can require human approval before they run.
What the agent reads is scanned
A tool result – an order note, a web page, an email – is untrusted input. It is injection-scanned before it re-enters the model’s context and steers the next step.
Values must come from a real source
A payment’s IBAN, a recipient’s email, an amount, an ID – must appear in the run’s sources. An argument the agent didn’t legitimately read is fabricated or injected, and it does not execute.
Private data can’t leave through a tool
Screened PII, detected secrets, and the system-prompt canary must not leave through tool arguments. A per-key map says exactly which kinds of data each tool may receive.
What the agent read decides where data may go
Once a run reads a web page or an inbound email, its trust drops and tools that send, pay or write refuse – whatever the page said. Reading from a confidential room – HR, finance – confines its data to the room’s members, the chat answer included. Flow labels reference.
Loops and spending are capped
Identical calls repeating past a threshold are caught as runaway loops, and hard per-run cost / step / tool-call caps are checked before the next model call spends anything.
Rules about step order
“Pay only after the vendor lookup” needs to know what you intended. There are three ways to tell it, from least to most setup – and they stack:
The plan in your system prompt
The rules are usually already in the system prompt – “verify inventory before confirming”. A cheap judge checks each tool call against the stated instructions. Zero integration.
Order rules you declare
A small grammar – pay requires lookup_vendor, send_email max 3 calls – enforced as a state machine over the run’s tool history. Written in the dashboard, or compiled automatically from your n8n workflow export.
What normal looks like
After enough observed runs, in/guard/out fingerprints normal behavior – typical tools, sequences, cost envelope – and flags deviation. Catches the drift declared rules miss. Watch-only: it doesn’t block.
Frequently asked questions
How can a per-request proxy secure a multi-step agent?
Agent loops are stateless: every iteration resends the entire accumulated context – prior turns, tool calls, results. Correlated by a session id, in/guard/out reconstructs the whole run as it unfolds and enforces run-level rules: budgets, loops, ordering, and per-run audit. More on the trade-off in inside vs outside the loop.
Which checks run on each iteration of the loop?
Every one that touches an action: the tool result is injection-scanned before it re-enters context, and the next call faces policy, permission tiers, argument grounding, and taint checks. Agent inner loop security walks the cycle step by step.
What stops a prompt-injected agent from acting?
Defense in depth. The injected text is scanned at the boundary; if it still steers the model, the resulting tool call has to pass policy, permission tiers, action grounding (the payee must exist in the run’s sources), and taint checks. One successful injection still has to beat four independent gates to become an action.
Do I have to describe my workflow up front?
No. The rules for any agent hold with zero knowledge of intent. When you want ordering enforced, state it as a sequence policy or upload your n8n export and it compiles into one – and learned baselines cover the drift nobody declared.
What about steps that don’t touch the LLM?
The checkpoint API is a policy decision point for exactly those: your workflow asks “may I proceed?” with the proposed action and gets allow, deny, or require-approval from the same policy engine – via an n8n community node, a LangChain callback, or a plain SDK call. It lands in the same run graph.
Will this break existing non-agent traffic?
No. Every agent check is observe-by-default: it flags in Fix & log mode, blocks in Block mode, and skips entirely when unconfigured. Ordinary chat completions pass through unchanged.
See your agent’s run graph.
Point your agent at in/guard/out in Fix & log mode – the first run graph usually settles the argument.