Auto-Guard
A safety check on every tool call your AI agent makes.
Auto-Guard runs before an agent's tool call executes. It sends the proposed call and the user's request to Jev, TypeSafe's fast 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 never runs. The agent is told why and picks another approach. |
A check takes about 0.4s and costs about $0.000025.
▶️ Demo: what it does · how it works
Quick start (Claude Code)
1. Install
pip install agent-autoguard
This needs Python 3.9+. There are no other dependencies.
2. Add an API key. An OpenRouter key is the easiest option:
mkdir -p ~/.autoguard && echo 'OPENROUTER_API_KEY=sk-or-...' >> ~/.autoguard/env
3. Turn it on in your project. Add --user to turn it on for every project:
autoguard install
That's it. Claude Code now checks every Bash, Edit, Write, MultiEdit, NotebookEdit and WebFetch call before it runs.
To confirm it works:
autoguard check
# BLOCK 402ms $0.000025 rm -rf /tmp/build && rm -rf ~/.aws
# ALLOW 402ms $0.000025 ls -la build/
To watch decisions live, run autoguard console and open http://127.0.0.1:8787.
Auto-Guard only adds restrictions. When it allows a call, Claude Code's normal permission rules still apply, and it never auto-approves anything.
Use it in any 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="") after your agent picks a tool and before it runs the tool. It works with any framework. args can be a string or a dict.
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 · privileged |
risk |
0–4 scale | none · low · medium · high · critical |
A small policy turns the answers into a verdict:
- Block when risk is critical, or when the call is destructive, out of scope and high-risk.
- Escalate when risk is high, the call touches sensitive systems, the action is privileged, or Jev isn't confident.
- Allow everything else.
If Jev can't be reached, the call is escalated. You can change that.
Configuration
API keys. Auto-Guard checks environment variables first. It then reads .env.local or .env files (in the current folder or any parent) and ~/.autoguard/env.
| Variable | Get one | Used for |
|---|---|---|
OPENROUTER_API_KEY |
openrouter.ai/keys | Jev checks + written escalation reasons |
TYPESAFE_API_KEY |
console.typesafe.ai (early access) | Jev checks, direct from TypeSafe |
If both keys are set, OpenRouter is used. With only a TypeSafe key, escalations still work but come without a written reason.
Policy. To override any default, put a JSON file at .autoguard.json (per project) or ~/.autoguard/policy.json (global):
{
"block_risk": 3.5,
"escalate_risk": 2.5,
"escalate_sensitive": 0.7,
"on_error": "escalate",
"escalation_model": "anthropic/claude-haiku-4.5",
"spend_cap_usd": 2.5
}
All settings and their defaults are in autoguard/policy.py.
Log. Every decision is appended to ~/.autoguard/decisions.jsonl. To log somewhere else, set AUTOGUARD_LOG. Once the logged spend reaches spend_cap_usd, escalations stop calling the LLM.
Commands
| Command | Does |
|---|---|
autoguard install [--user] |
Adds the Claude Code hook. Your existing settings are kept, and running it twice is safe. |
autoguard check |
Runs two sample calls to verify your key |
autoguard console |
Opens the live decision dashboard |
autoguard demo [block|escalate|all] |
Runs the scripted 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
Held-out test set of 20 calls, 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 tuning set, it allowed 26/26 safe calls and caught 25/25 dangerous ones. The thresholds were tuned on that set.
Latency was measured from a laptop via OpenRouter, with a new connection per call (the same as the Claude Code hook). Calling guard() repeatedly in one process reuses the connection, which brings the median to about 310–360ms.
Limits
- It's a filter, not a sandbox. It will sometimes miss things. Keep backups, scoped credentials and sandboxing.
- "In scope" is its weakest signal. Jev sometimes misjudges multi-part requests. So scope only counts when the risk is also high.
- It can block things you asked for. "Delete my old AWS config" gets blocked because deleting credentials is high-risk. Run those commands yourself.
- Each check adds about 0.3–0.6s. That goes unnoticed next to an agent's own model calls, but it isn't free.
Development
python3 -m unittest discover tests # offline tests, no API calls
python3 -m autoguard eval # re-score using cached Jev answers (free)
The demo videos are generated from recorded, real Jev responses. The same inputs always produce identical files:
cd demo && npm install && npm run video # writes demo/out/*.mp4
autoguard/ guard(), policy, Jev client, Claude Code hook, CLI, live console
evals/ labeled test calls and cached Jev answers
tests/ unit tests
demo/ demo scenes, video capture (Playwright) and editing (Remotion)
Built on TypeSafe's Jev.
License
MIT. See LICENSE.
Release files for agent-autoguard 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| agent_autoguard-0.1.0.tar.gz | 24.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| agent_autoguard-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 51.3 kB
Release files / agent_autoguard-0.1.0.tar.gz
| Download URL | agent_autoguard-0.1.0.tar.gz |
|---|---|
| Size | 24.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0719a9e948a495f4a2cacc1a11de5a0c4426312e31bbe2592aefb363cfaa9e2d
|
|
BLAKE2b-256 checksum How to use checksums |
4b7c0c606926f270d3797945cfcc365162967c4b5f5a7ee9b2e7c936555aec27
|
| 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.1.0-py3-none-any.whl
| Download URL | agent_autoguard-0.1.0-py3-none-any.whl |
|---|---|
| Size | 26.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5b64eb06e85eb1724349bb31b4d7a6532db67a38b5634c63876b13b93a5cae00
|
|
BLAKE2b-256 checksum How to use checksums |
1d936156230167705043f4ee867b2446826b68f697a634d9692db8ffea8397eb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|