Airlock is a permissions-aware gateway that sits between your AI agents and the tools they use. Apply per-agent allow, ask, and deny policy, require human approval for sensitive actions, and audit every single call — all through one config file.
Agents act on untrusted content with real credentials and tools. Airlock keeps that access explicit, reviewable, and fail-closed.
npx airlock-bot --config airlock.yaml
Untrusted content — web pages, emails, documents, tool descriptions — can instruct your agent to take unauthorized actions with its available tools.
The agent misinterprets intent, hallucinates parameters, or calls the wrong tool — sending a message to the wrong person, deleting the wrong file, pushing to the wrong branch.
Today, agents either have full access to a tool or none at all. There's no way to allow reading but gate writing, or auto-approve safe commands while requiring approval for dangerous ones.
Airlock speaks the Model Context Protocol. Any MCP client connects, receives a filtered tool surface based on its agent profile, and all permission logic applies identically — regardless of the client.
Define which tools each agent may use, which calls need approval,
and which are denied. Unavailable tools are hidden from the
manifest. Supports wildcards like github/*.
Flag sensitive tools for manual approval. When an agent tries to create a PR or push code, approve or deny from Telegram, the dashboard, a native macOS prompt, or your terminal. Slack and generic webhooks can notify a team or feed a custom decision flow.
Every tool call is logged to SQLite — agent, tool, parameters, decision, latency. Redact sensitive fields automatically. Query your logs with a built-in management API.
Make HTTP requests and run shell commands through the gateway. Domain allowlists, blocked hosts, and command-level policies (allow/deny/require approval) — all enforced at the infrastructure level.
Generate Airlock configs automatically from CLI
--help output,
Fig autocomplete specs, shell completions, or OpenAPI 3.x specs. Start with generated
YAML instead of a blank file.
Define reusable permission sets like readonly and
developer, then compose them with
extends: [readonly, developer]. Profiles merge with
the same deny > ask > allow precedence.
Expose multiple names for the same tool with different security envelopes. Auto-approve the sandboxed variant, gate the full-power version behind approval. Reusable presets reduce config repetition.
Composable middleware on every tool call: prompt injection detection, canary tokens, PII classification, output scanning, rate limiting, schema validation, and LLM-powered output summarization.
Works with any MCP client — Claude Code, Cursor, OpenClaw, or your own. Connects over stdio, SSE, or streamable HTTP. The agent just sees a normal MCP tool server.
Everything lives in airlock.yaml. Define providers,
agents, reusable profiles, approval rules, and exec policies in
one place. Hot-reloads on save — no restarts needed.
Each agent gets a tailored tool manifest. Your coding agent sees filesystem and git tools. Your monitoring agent sees Sentry and PostHog. Your research agent sees HTTP GET and nothing else. Tools outside the agent's effective policy are invisible.
Sensitive actions pause and wait. The agent calls
github/create_pr and the gateway holds the
connection, sends you a notification with the details, and waits
for your approve or deny. The agent
just experiences a slow tool call — no special client
support needed.
Every call — allowed, approved, denied, timed out, blocked — is recorded with timestamps, parameters, decisions, and latency. Sensitive fields are automatically redacted. Query your audit log to understand exactly what your agents have been doing.
When an agent hits a gated action, you get a notification with all the context you need. Decide from Telegram, the dashboard, a native macOS prompt, or your terminal; use Slack webhooks for team-visible alerts.
APPROVE? [X9Y8Z7] Agent: claude-code Tool: exec/run Command: git push origin feature/auth-fix > approve X9Y8Z7 Approved. Executing...
Browser dashboard with live updates Airlock Approvals http://localhost:4112 exec/run claude-code git push origin main [A]pprove [D]eny keyboard shortcuts Syntax highlighting • Browser notifications Sound alerts • Full arg inspection modal
A native macOS app that lives in your menu bar. Get notifications, review tool calls, and approve or deny — without leaving what you're doing.
brew install airlock-dev/tap/airlock-companion
Requires macOS 14 (Sonoma) or later. Signed and notarized.
Point Airlock at your existing tools and it generates configs automatically. Three discovery strategies for CLIs. Full OpenAPI support for REST APIs. Interactive TUIs for fine-tuning.
Parse --help output, shell completion scripts (Cobra,
Click, Clap), or
Fig specs.
Airlock picks the richest source available.
airlock discover cli kubectl --fig
airlock discover cli docker --max-depth 2
airlock discover cli git --include status,push,log
Feed in any OpenAPI 3.x spec — local file or URL — and every endpoint becomes a namespaced MCP tool with the same permission engine.
airlock discover api ./petstore.json
airlock discover api https://api.example.com/openapi.json \
--include "GET *" --exclude "DELETE *"
airlock configure-cli lets you browse subcommand
trees, toggle commands, and export YAML interactively.
configure-agent assigns allow/ask/deny per tool with
keyboard shortcuts. Prefer a browser?
configure-web edits local config, while
airlock run adds provider health and live tool
discovery.
A composable middleware stack runs on every tool invocation — before and after execution. Each layer can inspect, block, transform, or annotate the call.
Scans inbound tool arguments for injection patterns. Regex-based by default, or plug in a DeBERTa ML classifier at a configurable confidence threshold.
Scans tool responses for prompt injection attempts before they reach the agent. Can flag or automatically mangle suspicious content.
Injects invisible markers into tool outputs. If a marker appears in a subsequent tool's input, Airlock catches the data exfiltration path and logs it.
Detects SSNs, credit card numbers, AWS access keys, private keys, JWTs, and API tokens in tool arguments. Heuristic or LLM-backed.
Wraps all tool responses in
<untrusted-output> tags so the agent's context
clearly delineates trusted vs. untrusted data.
Validates tool arguments against JSON Schema with Ajv before execution. Malformed calls never reach the downstream tool.
Sliding-window rate limiter, configurable per-agent or per-tool. Prevents runaway agents from hammering downstream services.
For large tool outputs, optionally calls a fast LLM (Haiku, GPT-4o-mini) to summarize before passing to the agent. Full output is saved to a temp file.
Expose multiple names for the same underlying capability with different security policies. Auto-approve the sandboxed variant. Gate the full-power version behind approval. Reduce approval fatigue without giving up control.
sandbox_presets:
local_transform:
filesystem:
allow_read: ['.']
allow_write: ['/tmp']
deny_read: ['~/.ssh', '~/.aws', '.env']
network:
allowed_domains: [] # No network access
agents:
claude-code:
allow:
- python/sandboxed # Auto-approved, local-only
ask:
- python/full # Needs approval, can pip install
sandbox:
enabled: true
presets: [local_transform]
tool_overrides:
python/sandboxed:
alias_of: exec/run
description: "Run Python for local transforms only"
python/full:
alias_of: exec/run
description: "Full Python with network after approval"
sandbox:
filesystem:
allow_write: ['.', '/tmp']
network:
allowed_domains: ['pypi.org']
Airlock wraps exec/run and its aliases with the
sandbox runtime. On supported platforms, filesystem and network
policy is enforced below the agent and audited with the call.
Define presets like local_transform,
github_only, or npm_registry once. Apply
agent-wide or per-tool variant. Deny lists are additive.
When a sandboxed tool needs approval, the notification includes the resolved sandbox context — which presets applied, which domains are allowed, where writes are permitted.
Define downstream providers, agents, reusable profiles, approval rules, and security policies in a single YAML file. Hot-reloads on save.
agents:
helena: # Personal assistant agent
allow:
- filesystem/read_file
- filesystem/list_directory
- github/* # Wildcard: all GitHub tools
- notion/*
- http/get
- exec/run
ask: # These require your approval
- github/create_pr
- github/push
- notion/update_page
- http/post
monitoring: # Read-only agent, no approval needed
allow:
- sentry/list_issues
- posthog/*
- http/get
ask: []
providers:
filesystem:
type: stdio
command: npx
args: ["-y", "@modelcontextprotocol/server-filesystem", "/workspace"]
github:
type: stdio
command: npx
args: ["-y", "@modelcontextprotocol/server-github"]
env:
GITHUB_PERSONAL_ACCESS_TOKEN: ${GITHUB_TOKEN}
exec: builtin
http: builtin
agents:
helena:
exec:
allow: # Auto-approved commands
- "git status"
- "git diff *"
- "git log *"
- "ls *"
- "cat *"
ask: # Require approval
- "git commit *"
- "git push *"
- "npm *"
deny: # Always blocked
- "rm -rf *"
- "sudo *"
- "curl *"
approvals:
timeout_ms: 300000 # 5 min default
batch_window_ms: 10000
provider:
type: telegram
bot_token: ${TELEGRAM_BOT_TOKEN}
chat_id: ${TELEGRAM_CHAT_ID}
# Slack is an outgoing notification webhook;
# pair it with a separate decision route.
# provider:
# type: slack
# webhook_url: ${SLACK_WEBHOOK}
# Or use the TUI for local dev
# provider:
# type: tui
profiles:
readonly: # Reusable permission set
allow:
- github/list*
- github/get*
- http/get
developer:
allow:
- github/*
- git/*
- exec/run
ask:
- github/create_pr
- github/merge_pull_request
agents:
claude-code:
extends: [readonly] # Inherits readonly permissions
helena:
extends: [readonly, developer] # Merge with deny > ask > allow
deny:
- exec/run # Override: deny always wins
middleware:
injection_detector:
backend: regex # or "deberta" for ML classifier
mode: escalate # detect | mangle | escalate
sensitivity_classifier:
mode: detect # detect | escalate
threshold: 0.7
canary_tokens: true # Detect data exfiltration
output_injection:
mode: mangle # Redact injection in responses
untrusted_envelope: true # Wrap outputs in <untrusted-output>
rate_limiter:
max_requests: 100
window_ms: 60000
per: agent # or "tool"
output_summarizer:
model: claude-haiku-4-5-20251001
threshold_chars: 10000
# airlock.yaml — start with the example and customize
curl -fsSL -o airlock.yaml https://raw.githubusercontent.com/airlock-dev/airlock/main/examples/airlock.yaml
# Streamable HTTP + SSE gateway for network clients
npx airlock-bot --config airlock.yaml
# Or stdio mode (for Claude Code)
npx airlock-bot --agent claude-code --config airlock.yaml
# In your MCP client config, connect to the data-plane:
http://localhost:4111/agents/claude-code/mcp # streamable HTTP
http://localhost:4111/agents/claude-code/sse # SSE
Route your OpenClaw instance through Airlock. Gate shell commands, require approval before sending messages, and block skills from exfiltrating data to unknown domains.
Give Claude Code full filesystem and git access, but gate
git push, rm, and deployments behind
human approval.
A read-only agent that watches Sentry and PostHog — no write tools exposed, no HITL needed, fully autonomous.
An agent that can fetch approved domains via HTTP GET but has zero access to write tools, exec, or internal services.
Non-MCP tools call the /hook endpoint on the
control-plane listener for policy decisions. CI scripts, Claude
Code hooks, or custom integrations get the same policy and
approval engine.
Query the audit log, list pending approvals, approve or deny via
REST on a separate control-plane listener. Defaults to
127.0.0.1:4113 and stays off the agent MCP socket.
Endpoints: /health, /audit,
/hitl/pending, /events,
/approve?code=.... Bearer token auth.
Unauthorized tools are omitted from the manifest. The agent doesn't know they exist.
Unrecognized tool calls and unmatched commands are denied by default.
Approval and audit routes live on a separate loopback management listener. Built-in HTTP tools block local and private hosts by default.
Built-in HTTP tools respect a blocked hosts list that prevents access to local network, internal services, and the gateway itself.
Downstream tool descriptions are sanitized. Override descriptions in config to prevent prompt injection via tool manifests.
Pending HITL approvals are persisted to SQLite. Restart the gateway and pick up where you left off.
Invisible markers injected into tool outputs detect data exfiltration when they appear in subsequent tool inputs.
Scans tool arguments and responses for prompt injection patterns. Regex or ML-backed (DeBERTa).
Detects API keys, AWS credentials, SSNs, credit cards, JWTs, and private keys in tool arguments before execution.
API secret comparison uses timingSafeEqual, not
string equality. No timing side-channel leaks.
Airlock is open source and free. Set it up in minutes.
npx airlock-bot --config airlock.yaml