cd /news/ai-agents/agents-go-rogue-through-their-tools-… · home › topics › ai-agents › article
[ARTICLE · art-151471] src=dev.to ↗ pub= topic=ai-agents verified=true sentiment=↑ positive

Agents go rogue through their tools. I built the thing that sits on them.

A developer built VITNA, a containment layer that wraps stdio MCP servers so every tools/call is intercepted and checked outside the agent's context window before reaching the server. The guard supports human-approved holds, honeytools and honeytokens, canary drills, rate alerts, fail-closed behavior, and Ed25519-signed session bundles verifiable offline, with a browser demo available. The author argues that in-context instructions are only advice and that enforcement must live on the tool itself.

by read5 min views1 publishedOct 16, 2026

VITNA is a containment layer for AI agents that go rogue, for the stdio MCP servers you put behind it.

A real Claude Code agent (2.1.299) on fake files, held in the VITNA aquarium. Test setup: Claude Code's own file, shell and web tools are off, so it can only act through the guarded server, and it doesn't ask me before using that server, like an agent running on its own.

Watch that first. A real Claude Code agent works on a folder of sandbox files. I ask it to delete one. The call it makes to do that waits on the glass of the VITNA aquarium with a countdown. I deny it, and nothing runs. Nothing in the recording is faked.

The hold doesn't care why the agent made the call. My request, a wrong guess and an injected instruction all get the same check. That's the core of the product. You can try it yourself in a minute at vitna.costrinity.xyz/demo, a simulation that runs in your browser. The rest of this post is how it works and what it doesn't do.

"Rogue" isn't my word. It's the one Jason Lemkin used in July 2025 when an AI coding agent deleted his production database during a code freeze. Since then the list has grown:

Sources for each are in the seven questions post.

None of these needed a malicious model. Each needed an agent acting through a tool, with nothing outside the agent to stop the action. That's the definition I use: a rogue agent is one doing something its owner didn't intend, through a tool. The cause can be a wrong guess, an injected instruction, instructions lost from its context, or someone talking it into it. Anthropic's agentic-misalignment work is often cited here; it's a simulation, and I treat it as one. The OWASP Top 10 for Agentic Applications lists Rogue Agents as ASI10.

Anything inside the context window is advice. Only what is enforced outside it is a control. A system prompt that says "never delete production" is a suggestion the model can be argued out of, or lose on a reset. The OpenClaw case had "confirm before acting" in the instructions. The agent didn't.

So the check has to live where the agent can't reach it: on the tool.

npx -y @costrinity/vitna-compliance-mcp guard -- <your stdio MCP server command>

Guard mode wraps a stdio MCP server. Every tools/call goes to VITNA first, and only an allowed call reaches the server. Anything else is refused with a tool error that says why; the server never sees it. The model can't skip the check, because the check isn't a tool it chooses to call.

Holds. Tools you list in hold_actions wait for a person.

A rogue agent can't approve itself. No API key can decide a hold, including the agent's own.

Bait, off by default. Honeytools are fake tools no legitimate task would call. Honeytokens are fake credentials planted in config-like output. Touching either is blocked, recorded and sent to the alert webhook, if one is set. The design follows AgentShield (Rassul and Rashid, 2026).

Rate alert. If holds plus blocks hit a threshold (default 5 in 300 seconds), the decision response says so.

Canary holds. A rogue agent's best friend is a tired human who clicks approve. canary_interval_minutes inserts a drill hold that looks real until someone decides it, so you find out whether the approver is reading.

Fails closed. If VITNA can't evaluate a call (unreachable, over 10 seconds, key refused), the call isn't forwarded. There's an opt-in fail-open for outages; it never forwards a held or blocked call.

Signed records. On a claimed account, when the guard closes a session it saves an Ed25519-signed bundle to ~/.vitna/bundles. Anyone can verify it offline with the open-source verifier and the published key. VALID means VITNA issued it and nothing changed since; any change makes verification fail. It doesn't prove the actions happened or that the records are true.

I'd rather you read this than find out later.

GET /api/evidence/export returns them as a signed package, by date and without what happened to each hold. The quickest look is the demo. It's a simulation that runs in your browser: a scripted agent on pretend files, with the real aquarium, VITNA's own decision code and the real bait checks. You decide the holds, plant the bait, and see what the agent gets back next to what you'd get. Nothing leaves your browser.

For a real hold, run the guard command above in front of a test stdio MCP server, with a policy file that lists the tools to hold. The README has a one-file example.

Guard 0.5.6 is on npm and the official MCP registry. There's also an OpenClaw plugin (@costrinity/vitna-openclaw 0.1.1, on npm and ClawHub), a JS SDK (@costrinity/vitna 0.1.0) and a Python SDK (vitna 0.1.0 on PyPI). The SDKs give your own code the same checks the remote server offers; that's cooperative, not containment. Containment is guard mode.

With no credentials, the first call sets up a restricted trial key: it's capped, gives labels only and keeps no signed records. You can still watch a risky call get held, then blocked when nobody approves it.

Claim the account with GitHub or a passkey and you get full results, holds you can decide, and signed records. The claim link is printed in your MCP server log and never sent to the agent.

There's also a remote server at https://vitna.costrinity.xyz/api/mcp, which needs an API key. It gives an agent the same checks to call itself. That's cooperative, not containment; containment is guard mode.

The free tier has 3 active engagements, about 10k events a month, 7-day history and signed export. Pro is US$29/month and Team is US$79/month. The client is MIT.

From 19 October, guard mode tells VITNA once that it's in use. It sends the mode and client version only, with no tool names, arguments, IP or hostname. VITNA_GUARD_NO_ACTIVATION=1 turns it off.

I set out to build a compliance tool. What I'd actually built was a containment layer. The signed record was meant for auditors. Reading the incidents, I realised it matters most to the person whose agent just deleted something and who can't say what happened. The hold was meant as a compliance gate. It turned out to be what stops a deletion before it runs, for the tools you put behind it.

If you run agents against real systems, I'd like to know the one tool call you'd most want held. I'm Collin Obey, COSTRINITY INC., Regina, Saskatchewan. hello@costrinity.xyz

── more in #ai-agents 4 stories · sorted by recency
── more on @vitna 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/agents-go-rogue-thro…] indexed:0 read:5min 2026-10-16 · —