A runtime policy gate for AI agents: every tool call is evaluated against declarative policy before it executes.
Project description
Gatehouse
A runtime policy gate for AI agents.
Gatehouse sits between an AI agent and its tools. Every action the agent proposes — a tool call, an API invocation — is intercepted and evaluated against declarative policy before it executes. Every evaluation resolves to one binding disposition:
| Disposition | Meaning |
|---|---|
allow |
The action proceeds. |
deny |
The action is blocked, with a reason. |
require_approval |
The action is held until a human approves it. |
allow_with_flag |
The action proceeds, but is marked for monitoring. |
Every evaluation is written to a structured audit log. The default posture is deny by default, explicit allow, every disposition explainable.
Status: v0.1.0 — the complete local gate: engine, registry, audit, approvals, CLI, dashboard, MCP proxy, and a runnable demo. Young software; interfaces may still move between minor versions.
The demo in one paragraph
A scripted travel agent books fictional flights through mock MCP tools with
Gatehouse in between: a permitted search streams into the dashboard as
allow, an over-budget booking comes back deny with the exact reason, a
watchlisted destination proceeds as allow_with_flag, and a cancellation
stops the terminal until you click Approve in the dashboard — then it
completes instantly. Run it yourself:
examples/travel-agent.
Features
- Policy engine — declarative YAML rules with agent/tool matching,
parameter constraints (bounds, allowlists, regex), selection predicates
(
whereselects,paramsenforces), time windows, and rate/cumulative limits with per-session or rolling clock scopes. Deny by default; when rules disagree, the most restrictive disposition wins. - Agent registry — agents are declared with a human owner, an autonomy
tier (
read_only/supervised/governed/human_only), an explicit tool grant, and a credentials reference, never a value. Unregistered agents are denied before policy is consulted. Tiers are ceilings: no rule can grant past them. - Audit log — append-only JSONL, one record per evaluation: disposition, reason, matched rules, policy version and digest, latency. Parameters are stored as a digest, not verbatim. Usage counters (budgets, rate limits) are rebuilt from the log on restart, so restarting the gate never resets them.
- Approval queue —
require_approvalactions are held with a TTL and resolved from another process; expiry fails closed. Every resolution is an appended audit record naming who decided and why. - Policy test harness — scenario files declare action → expected disposition; scenarios share usage state so limit behaviour is testable. Policies without tests are policies waiting to be bypassed.
- CLI —
gatehouse check(one-shot advisory evaluation, records nothing),gatehouse test,gatehouse audit tail|stats,gatehouse approvals/approve/deny,gatehouse ui. - Web dashboard — live disposition feed over WebSocket, approval cards with TTL countdowns, the agent registry with activity sparklines, and a read-only policy view with test results. Localhost only, no auth in v0.1.
Quickstart
pip install -e ".[ui]" # from a checkout (PyPI: gatehouse-ai, once published)
Declare an agent and a policy:
# agents.yaml
agents:
- id: trip-planner
owner: you@example.test
tier: governed
allowed_tools: [search_flights, book_flight]
# policy.yaml
version: 1
tools:
search_flights: {mutating: false}
book_flight: {mutating: true}
rules:
- id: allow-search
agents: [trip-planner]
tools: [search_flights]
disposition: allow
- id: book-within-budget
agents: [trip-planner]
tools: [book_flight]
disposition: allow
params:
price: {max: 500}
limits:
- {cumulative: price, max: 2000, per: session}
Ask the gate what would happen:
$ gatehouse check trip-planner book_flight -p policy.yaml -r agents.yaml --param price=812
deny trip-planner → book_flight
reason: rule 'book-within-budget': parameter 'price' = 812 exceeds the maximum 500.0
Gate any MCP server without changing the agent or the server — the agent connects to Gatehouse instead:
pip install "gatehouse-ai[mcp]"
gatehouse run --agent trip-planner -p policy.yaml -r agents.yaml -- <your MCP server command>
Or gate plain Python calls directly:
from gatehouse import ApprovalQueue, AuditLog, Gate, PolicyEngine, Registry
from gatehouse.adapters import gated
gate = Gate(
Registry.from_file("agents.yaml"),
PolicyEngine.from_file("policy.yaml"),
AuditLog("gatehouse-audit.jsonl"),
approvals=ApprovalQueue("gatehouse-approvals"),
)
@gated(gate, agent="trip-planner")
def book_flight(price: float, destination: str) -> str:
... # only runs if the gate says so; refusals raise ActionDeniedError
Watch it live:
gatehouse ui -p policy.yaml -r agents.yaml # http://127.0.0.1:8422
Documentation
- Writing policies — the tutorial; every command runs as written.
- Policy reference — every field, and the evaluation semantics.
- MVCP mapping — how each feature answers the five control-plane questions: identity, authority, visibility, containment, recovery.
- Design decisions — why tiers are ceilings, why an uncheckable constraint is a breach, what a "session" is, and every other choice that shapes the semantics, with rationale.
Background and attribution
The conceptual grounding is the Agentic Control Plane ("From Prevention to Control") and the Minimum Viable Control Plane ("From the Control Gap to the Agency Gap"). The four-disposition vocabulary deliberately echoes the four outcomes described in the Monetary Authority of Singapore's SAFR white paper (July 2026) — convergent framings of the same idea: agent actions should resolve to a small, closed set of binding outcomes.
Development
pip install -e ".[dev]"
pytest && ruff check . && mypy gatehouse tests
The frontend source lives in ui/; built assets are committed under
gatehouse/ui/ so installed users never need npm. Rebuild with
cd ui && npm install && npm run build.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gatehouse_ai-0.1.0.tar.gz.
File metadata
- Download URL: gatehouse_ai-0.1.0.tar.gz
- Upload date:
- Size: 2.4 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4a780c18fa7bef4d549f97d844ce8af9df9e3a44d10a14ea7ae760986f00cc54
|
|
| MD5 |
84679ef6339e0aa9a0d1edeb945df0dc
|
|
| BLAKE2b-256 |
cf63f90ffcc0fc4bc732a7f5aecd0d5e3592801d9b8372355777ac0a464c4531
|
File details
Details for the file gatehouse_ai-0.1.0-py3-none-any.whl.
File metadata
- Download URL: gatehouse_ai-0.1.0-py3-none-any.whl
- Upload date:
- Size: 109.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
51296e909db1d41ebc9df350a73c8df07a8ef6506c7f3f3ad7fe63e49f6f1b45
|
|
| MD5 |
5207ea41056319064d1bc802fb4a2f3e
|
|
| BLAKE2b-256 |
3d329e0b7e01d9a4fe02273a1892c51250f6ac4dcf088f95b3ab5b13cbffcc9b
|