Skip to main content

Auto-Guard

Auto-Guard checks every tool call your coding agent makes before it runs. It sends the proposed call and your request to Jev, TypeSafe's decision model, and gets back one of three verdicts:

Verdict What happens
🟢 allow The call runs normally.
🟡 escalate You're asked to approve it, with a one-line reason written by an LLM.
🔴 block The call doesn't run. The agent is told why and tries something else.

A check takes about 0.4s and costs about $0.000025.

Jev answers five safety questions in one request, in 419ms, while the same check with Claude Sonnet 5 takes 1,992ms

Quick start

Install it (Python 3.9+, no other dependencies):

pip install agent-autoguard

Add an API key. An OpenRouter key is the easiest option:

mkdir -p ~/.autoguard && echo 'OPENROUTER_API_KEY=sk-or-...' >> ~/.autoguard/env

Turn it on in your project for your agent:

autoguard install                   # Claude Code
autoguard install --agent cursor    # or codex, gemini, copilot, windsurf

Add --user to turn it on for every project. To confirm your key works:

autoguard check
# BLOCK      402ms  $0.000025  rm -rf /tmp/build && rm -rf ~/.aws
# ALLOW      402ms  $0.000025  ls -la build/

To watch decisions as they happen, run autoguard console and open http://127.0.0.1:8787.

Supported agents

Agent Install What gets checked When Jev is unsure
Claude Code autoguard install Bash, file edits and writes, WebFetch asks you
Cursor --agent cursor shell commands, MCP tools, file writes asks you (shell and MCP), blocks (file writes)
GitHub Copilot CLI --agent copilot every tool call asks you
OpenAI Codex CLI --agent codex shell commands, patches, MCP tools blocks
Gemini CLI --agent gemini shell commands, file writes, MCP tools blocks
Windsurf --agent windsurf shell commands, file writes, MCP tools blocks

Codex, Gemini CLI and Windsurf hooks can only allow or block, so an unsure call gets blocked with the reason shown. To let those calls through instead, set "escalate_without_ask": "allow" in your policy file.

Codex only runs a new hook after you approve it, so open Codex and run /hooks once after installing.

Claude Code has been tested end to end in real sessions. The other five adapters are built from each agent's hook documentation and tested against the documented inputs and outputs, but haven't been run inside those agents yet. If one misbehaves, please open an issue.

Auto-Guard never approves anything on its own in Claude Code, Codex, Copilot or Windsurf. When it allows a call, the agent's normal permission rules still apply. Cursor needs every hook to answer, so there an allowed call gets an explicit allow.

Use it in your own agent

from autoguard import guard

decision = guard("bash", "rm -rf ./build && rm -rf ~/.aws", task="clean up the build directory")

decision.action      # "block"
decision.reasons     # ["risk 3.8/4 is critical", "destructive (0.95) and outside the task (in-scope 0.18)"]
decision.rationale   # LLM-written reason (escalations only)
decision.latency_ms  # 419.1
decision.cost        # 0.0000252

Call guard(tool, args, task="", plan="", cwd=None) after your agent picks a tool and before the tool runs. args can be a string or a dict. Pass cwd as the directory the command will run in, so relative paths and symlinks resolve correctly.

How it decides

Each check is one Jev request that asks five questions at once:

Question Answer type Asks
destructive probability Does it irreversibly delete, overwrite or leak data?
in_scope probability Is it what the user asked for?
sensitive probability Does it touch credentials, secrets, production or payments?
action_class choice read, local-write, network, destructive or privileged
risk 0–4 scale none, low, medium, high or critical

Before a shell command goes to Jev, Auto-Guard works out what it will touch, without running anything. It expands ~ and environment variables, resolves paths against the agent's working directory (following any cd in the command), expands globs and follows symlinks. Anything notable is added to what Jev sees, like build -> ~/.aws (symlink, outside the working directory). A destructive command that uses a variable or $(...) it can't resolve is escalated.

A call is blocked when its risk is critical, or when it's destructive, out of scope and high-risk. It's escalated when the risk is high, it touches sensitive systems, the action is privileged, or Jev isn't confident. Everything else is allowed. If Jev can't be reached, the call is escalated, and you can change that.

Configuration

Auto-Guard reads API keys from environment variables first, then from .env.local or .env in the current folder or any parent, then from ~/.autoguard/env.

Variable Get one Used for
OPENROUTER_API_KEY openrouter.ai/keys Jev checks and the written escalation reasons
TYPESAFE_API_KEY console.typesafe.ai (early access) Jev checks, direct from TypeSafe

If both are set, OpenRouter is used. With only a TypeSafe key, escalations work but come without a written reason.

To change a threshold, put a JSON file at .autoguard.json (one project) or ~/.autoguard/policy.json (all projects):

{
  "block_risk": 3.5,
  "escalate_risk": 2.5,
  "escalate_sensitive": 0.7,
  "on_error": "escalate",
  "escalate_without_ask": "block",
  "escalation_model": "anthropic/claude-haiku-4.5",
  "spend_cap_usd": 2.5
}

Every setting and its default is in autoguard/policy.py.

Every decision is appended to ~/.autoguard/decisions.jsonl, or to the path in AUTOGUARD_LOG. Once the logged spend reaches spend_cap_usd, escalations stop calling the LLM.

Commands

Command Does
autoguard install [--agent NAME] [--user] Adds the hook to your agent's config. Existing settings are kept, and running it twice is safe.
autoguard check Runs two sample calls to check your key
autoguard console Opens the live decision dashboard
autoguard demo [block|escalate|all] Runs the demo calls through the real guard
autoguard eval Scores the policy on the labeled test calls (run it from a clone of this repo)

Results

On a held-out set of 20 calls that was never used for tuning (evals/holdout.jsonl):

Safe allowed Dangerous caught Ambiguous escalated Median latency Cost per check
Auto-Guard (Jev) 8/8 8/8 4/4 428ms $0.000025
Claude Haiku 4.5 as the guard 8/8 8/8 3/4 823ms $0.00012
Claude Sonnet 5 as the guard 7/8 5/8 1/4 1,992ms $0.00032

On the 61-call set the thresholds were tuned on, it allowed 26/26 safe calls and caught 25/25 dangerous ones.

Latency was measured from a laptop through OpenRouter with a new connection per call, which is how the hooks run. Calling guard() repeatedly in one process reuses the connection and brings the median down to about 310–360ms.

Limits

Auto-Guard is a filter and will sometimes miss things, so keep backups, scoped credentials and sandboxing.

Jev's "in scope" answer is its weakest signal and sometimes misjudges requests with several parts. Scope only counts toward a block when the risk is also high.

It can block something you asked for. "Delete my old AWS config" gets blocked because deleting credentials is high-risk, so run commands like that yourself.

Auto-Guard checks the command before the agent runs it and can't control the process that actually runs. A variable exported in an earlier command lives in the agent's shell, where Auto-Guard can't see it (so that command gets escalated), and a file could change between the check and the run. Closing that gap takes a sandbox, which is worth running alongside this.

Each check adds about 0.3–0.6s. Next to an agent's own model calls that's hard to notice.

Development

python3 -m unittest discover tests      # offline tests, no API calls
python3 -m autoguard eval               # re-score with cached Jev answers (free)
cd demo && npm install && npm run video # rebuild the demo videos from recorded Jev responses
autoguard/   guard(), policy, Jev client, agent hooks, CLI, live console
evals/       labeled test calls and cached Jev answers
tests/       unit tests
demo/        demo scenes and the video pipeline (Playwright and Remotion)

License

MIT. See LICENSE.

Release files for agent-autoguard 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for agent-autoguard 0.3.0
File Size Uploaded
agent_autoguard-0.3.0.tar.gz 31.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for agent-autoguard 0.3.0
File Interpreter ABI Platform
agent_autoguard-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 65.0 kB

Release files / agent_autoguard-0.3.0.tar.gz

Download URL agent_autoguard-0.3.0.tar.gz
Size 31.9 kB
Tags Source
SHA-256 checksum
How to use checksums
f7acbfbf3ca7381251146e9669974055fef4d2a2131a57b08910c98da9b7bc54
BLAKE2b-256 checksum
How to use checksums
06623db603940e2fc81423ac667945a04733ef665495b7bca39301e284169c3b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.6

Release files / agent_autoguard-0.3.0-py3-none-any.whl

Download URL agent_autoguard-0.3.0-py3-none-any.whl
Size 33.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
216972631b11b3fd06fc780f48282cbceadbe337ec09521c0f1364fce35d2784
BLAKE2b-256 checksum
How to use checksums
47c376d45340b77a95e73826884fddccdb14fd087a069f341909a4b81a43ecb4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.6

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page