# How do I build a kill switch for an autonomous AI agent?

**Short answer:** A kill switch is a check that every risky action has to pass, kept outside the agent's own process, that you can flip without the agent's cooperation, and that blocks when it can't get an answer. Put it in the tool layer (a hook, wrapper or proxy every tool call goes through), make it fail closed, and back it with the things the agent holds: credentials you can revoke and payment cards you can freeze. Stopping the process is the last resort, not the switch. Then test it: flip it during a run and confirm the next action is refused.

## Checklist
1. Write down what the agent can touch: tools, API keys, OAuth tokens, payment methods, databases, outbound network. Each one needs a way to be shut off that doesn't depend on the agent.
2. Put one check in front of every tool call, in code the agent can't edit: a pre-tool hook, a wrapper around each tool, or a proxy that holds the real credentials. The check reads an on/off flag kept outside the agent's process.
3. Fail closed. If the check errors, times out or can't be reached, the action must be refused, not allowed. Many hook systems default the other way, so check yours.
4. Cover every path, not just your own functions. Built-in shell, browser and hosted tools often skip the hooks you add to custom tools.
5. Back it with revocable access: short-lived tokens you can revoke, one card per agent you can freeze, and keys that belong to the agent alone, so turning them off doesn't break anything else.
6. Make it reachable by the humans who need it: an owner (and an on-call backup) should be able to flip it from a phone in under a minute, and the flip itself should be logged with who and when.
7. Keep two levels: a pause you can lift (block new actions) and a revoke that's permanent (burn the credential, issue a new one if you resume).
8. Drill it. Flip the switch in a test run, confirm the next tool call is refused, then confirm resume works. A kill switch nobody has tested is a guess.

## Where the check goes in common agent frameworks (checked Oct 30, 2026)
- Claude Code: a PreToolUse hook runs before every tool call, MCP tools included, and can block it (exit code 2, or JSON with permissionDecision "deny"). Its docs say a hook that can't start, exits with any other code, times out or gets an HTTP error is a non-blocking error and the tool runs anyway, unless the hook sets onFailure: "block". Exit 1 does not block. Set onFailure: "block" on a kill-switch hook.
- Claude Code hooks merge across settings levels, and disableAllHooks can't disable managed hooks from outside managed settings, so a kill-switch hook in managed settings can't be switched off by a project file the agent can write. Command and HTTP hooks default to a 600-second timeout; set a short one.
- OpenAI Agents SDK: tool guardrails wrap function tools and run every time the tool is called; an input tool guardrail can skip the call or raise a tripwire. They don't apply to hosted tools (WebSearchTool, FileSearchTool, HostedMCPTool, CodeInterpreterTool, ImageGenerationTool), built-in execution tools (ComputerTool, ShellTool, ApplyPatchTool, LocalShellTool) or handoffs, so those need their own off switch.
- Agent-level input guardrails in the same SDK run in parallel with the agent by default, so the agent may already have run tools before a tripwire cancels it. Use blocking mode (run_in_parallel=False) for checks that must happen first.

## The layers under the switch
- Credentials: revoke or rotate the keys and tokens the agent holds. Short-lived, per-agent credentials make this quick and keep the blast radius to one agent.
- Money: with Stripe Issuing, setting a card's status to inactive declines every authorization and can be undone; canceled is permanent. An Issuing balance funded with only the agent's budget caps what it can spend even if every other check fails.
- Process: stopping the container or job ends the current run, but a scheduler, retry loop or second worker can start it again. Turn off the trigger as well, and don't treat a stopped process as proof the agent's access is gone.

## What can go wrong?
- The flag is checked once at startup, so a long run never sees it flip.
- The check fails open: the policy service is down and the hook's error is ignored.
- The agent can edit the file or setting that holds the switch, or holds the same credentials the switch is supposed to protect.
- Only custom tools are guarded; the agent reaches the same system through a shell, browser or hosted tool.

## Ask Rightshold (free, no key)
Add the MCP server https://www.rightshold.com/mcp to Claude, Cursor, ChatGPT, Grok or VS Code (one-click setup: https://www.rightshold.com/start?ref=seo), then ask: "My agent is misbehaving. Revoke its credential now so every Rightshold check refuses it, reason rogue_behavior."

```json
{
  "tool": "revoke_agent",
  "arguments": {
    "subject_id": "crd_YOUR_AGENT_CREDENTIAL",
    "reason": "rogue_behavior",
    "note": "looping refunds, stopped by owner"
  }
}
```
- Needs your owner account key; it's in the trust toolset (connect to /mcp?toolset=trust). Revocation is irreversible: resuming means issuing a new credential. Anyone can look it up for free with check_revocation, or follow GET /v1/revocations?since= and the signed list at GET /v1/revocations/signed.
- For a pause you can lift, use the guardrail gateway (Beta, free): POST /v1/guard/policies/{id}/kill denies every POST /v1/guard/check under that policy until POST /v1/guard/policies/{id}/resume. Its JavaScript and Python wrappers at GET /v1/guard throw on anything but allow, including network errors, so they fail closed.
- An account freeze (see /kill-switch) also makes every guard check deny.

_Rightshold's switches stop actions only where your code asks Rightshold first. It can't stop a process, revoke your other providers' keys or freeze your cards; put the check in a tool layer the agent can't bypass and keep the real credentials there._

## Sources
- [Claude Code: Hooks reference (PreToolUse, exit code 2, onFailure, managed hooks)](https://code.claude.com/docs/en/hooks)
- [OpenAI Agents SDK: Guardrails (tool guardrails, tripwires, execution modes)](https://openai.github.io/openai-agents-python/guardrails/)
- [Stripe API: Issuing Card object (status inactive and canceled)](https://docs.stripe.com/api/issuing/cards/object)
- [Stripe: Issuing for agents (freeze a card on suspicious spend)](https://docs.stripe.com/issuing/agents)

## Related
- [How to give an AI agent a virtual card with a spending limit](https://www.rightshold.com/answers/how-to-give-an-ai-agent-a-virtual-card-with-a-spending-limit)
- [How to stop an AI coding agent from deleting your production database](https://www.rightshold.com/answers/how-to-stop-an-ai-coding-agent-from-deleting-your-production-database)
- [How to give an AI agent a scoped, expiring credential instead of a long-lived API key](https://www.rightshold.com/answers/how-to-give-an-ai-agent-a-scoped-expiring-credential-instead-of-a-long-lived-api-key)
- [Agent guardrails](https://www.rightshold.com/agent-guardrails)

_Not legal advice. Updated 2026-10-30. JSON: https://www.rightshold.com/answers/how-to-build-a-kill-switch-for-an-autonomous-ai-agent.json_