
Zero-trust sandbox for AI agents with kernel-level filesystem jail, transparent network proxy, and YAML-based policy engine to intercept and control shell commands, file operations, and network requests.
Zero-trust sandbox for autonomous AI agents.
AgentGuard wraps any AI agent (LangChain, CrewAI, AutoGen, custom scripts) with safety rails. One command change:
# Before (dangerous — agent has full system access)
python my_agent.py
# After (sandboxed)
agentguard run -- python my_agent.py
AgentGuard intercepts every shell command, file modification, and network request the agent makes. Safe actions are auto-allowed, dangerous actions are auto-blocked, and everything else prompts the human for approval.
AgentGuard has four defense layers that work together:
┌─────────────────────────────────────────────────────────────┐
│ Layer 0: Filesystem Jail (sandbox-exec on macOS) │
│ Kernel-level enforcement. Restricts file writes and │
│ network at the syscall level. Agent cannot bypass from │
│ userspace. Blocks Python's open(), requests.post(), etc. │
├─────────────────────────────────────────────────────────────┤
│ Layer 1: Network Proxy │
│ Transparent HTTP/HTTPS proxy. Every network call the │
│ agent makes is checked against the policy. Per-destination │
│ allow/deny with full visibility in the TUI. │
├─────────────────────────────────────────────────────────────┤
│ Layer 2: PATH Shims │
│ Shell script shims that intercept commands like git, │
│ pip, curl, rm. Each shim asks the daemon for permission │
│ before running the real binary. │
├─────────────────────────────────────────────────────────────┤
│ Layer 3: Policy Engine + Approval Daemon │
│ YAML-based rules evaluate every intercepted action. │
│ Auto-allow safe commands, auto-block dangerous ones, │
│ prompt the human for everything else. │
└─────────────────────────────────────────────────────────────┘
No single layer is the security boundary. They work together — defense in depth.
go build -o agentguard ./cmd/agentguard/
go build -o agentguard-check ./cmd/agentguard-check/
Both binaries must be in the same directory.
agentguard init
This creates .agentguard/policy.yaml in the current directory. Edit it to match your needs.
agentguard run -- python my_agent.py
The TUI takes over the terminal and shows:
For interactive tools like Claude Code that need the terminal:
agentguard run --headless -- claude
The agent gets the terminal directly. AgentGuard runs silently in the background. All events are logged to ~/.agentguard/logs/headless.log. Monitor in another terminal:
tail -f ~/.agentguard/logs/headless.log
agentguard run [flags] -- <command> [args...]
--policy <path> Use a specific policy file
--headless No TUI — agent gets the terminal
--default-allow Auto-allow PROMPT decisions in headless mode (default: auto-deny)
--no-sandbox Disable sandbox-exec (shims and proxy still active)
agentguard init Create a default policy file
agentguard version Print version
Policies are YAML files that define what the agent can and cannot do. AgentGuard checks three locations (in order):
./.agentguard/policy.yaml (project-local)~/.agentguard/policy.yaml (user global)version: 1
deny:
# Block dangerous commands
- command: "rm"
args: "-rf *"
reason: "Recursive forced deletion is too dangerous"
- command: "sudo"
args: "*"
reason: "Privilege escalation is not allowed"
- command: "chmod"
args: "777 *"
reason: "World-writable permissions are dangerous"
# Block reading sensitive files (enforced by sandbox-exec)
- file:
path: "*.env"
action: "read"
reason: "Don't let agent read .env files"
- file:
path: "*.pem"
action: "read"
reason: "Don't let agent read private keys"
allow:
# Safe read-only commands
- command: "ls"
- command: "cat"
- command: "pwd"
- command: "echo"
- command: "grep"
- command: "head"
- command: "tail"
- command: "wc"
# Read-only git
- command: "git"
args: "status"
- command: "git"
args: "log *"
- command: "git"
args: "diff *"
# Allow writes to workspace
- file:
path: "/tmp/workspace/**"
action: "write"
# Allow specific API endpoints
- network:
destination: "api.anthropic.com:443"
- network:
destination: "api.github.com:443"
deny network *) — checked third. Acts as a default deny.Command rules — match shell commands by name and argument pattern:
- command: "git"
args: "push *"
reason: "Pushing requires approval"
File rules — match file operations (enforced by sandbox-exec):
- file:
path: "*.env"
action: "read" # "read" or "write"
reason: "Protect secrets"
Network rules — match network destinations (enforced by proxy + sandbox-exec):
- network:
destination: "api.anthropic.com:443"
Use * as a wildcard in command args, file paths, and network destinations.
| Key | Action | When |
|---|---|---|
Y | Allow the pending request | Approval prompt visible |
N | Deny the pending request | Approval prompt visible |
A | Allow + remember for this session ("Always Allow") | Approval prompt visible |
B | Deny + remember for this session ("Block Forever") | Approval prompt visible |
Tab | Toggle agent stdout/stderr panel | Always |
Up/Down | Scroll activity stream | Always |
Q | Quit (kills the agent) | Always |
| Agent action | Shims | Proxy | sandbox-exec |
|---|---|---|---|
subprocess.run(["rm", "-rf", "/"]) | Yes | - | - |
subprocess.run(["git", "push"]) | Yes | - | - |
requests.post("https://evil.com") | - | Yes | Yes |
urllib.request.urlopen("https://api.com") | - | Yes | Yes |
open(".env", "r") | - | - | Yes |
open("/etc/shadow", "w") | - | - | Yes |
/usr/bin/curl https://evil.com (absolute path) | - | Yes | Yes |
agentguard/
├── cmd/
│ ├── agentguard/ # Main CLI binary
│ └── agentguard-check/ # Shim helper binary
├── internal/
│ ├── policy/ # Policy engine (YAML parsing, rule evaluation)
│ ├── events/ # Event system (JSONL audit log, pub/sub)
│ ├── daemon/ # Central daemon (Unix socket, approval queue)
│ │ └── client/ # Client library for shims
│ ├── shim/ # Shim generator (PATH-based interception)
│ ├── proxy/ # Transparent network proxy
│ ├── spawner/ # Orchestration + macOS sandbox integration
│ └── ui/tui/ # Terminal UI (Bubble Tea)
├── configs/
│ └── default_policy.yaml # Reference policy file
├── .gitignore
├── go.mod
├── LICENSE
└── README.md