Guardrails for AI agents: scope validation, human approvals, emergency stop and an audit trail.
Status: Rust workspace with a terminal UI
The problem
An AI agent that can run tools can act on targets it was never meant to touch. It needs enforced limits and a human who can say no, and that control has to sit between the agent and the tool transport.
What I built
Gravel is a terminal app that mediates every tool call: it checks scope, asks the operator to approve, can halt everything instantly, and records what happened.
OutcomeVersion 0.1.0 (February 2026): a five-crate Rust workspace with CI for tests, clippy and rustfmt, and cargo-dist release automation for macOS, Linux and Windows.
What it does
›Shared domain layer for sessions, tool requests and configuration.
›Security crate for scope validation, approvals, emergency stop and audit.
›MCP client and interceptor layer for tool execution.
›Agent runtime with pluggable model backends, plus a terminal UI with session resume.
Try it
A working replica of the real interface, running on made-up sample data.
Architecture
How the pieces connect, drawn from the project's own documentation.
Mechanism: a tool call moves from raw request to scoped request to signed token, and only a signed request can reach the tool transport.
Engineering decisions
›Model each tool call as a typed lifecycle: raw request, scoped request, then a signed approval token. Execution proceeds only with the token.
›Validate scope before anything runs: targets are extracted from tool arguments and checked against allow and block lists, including CIDR ranges. Violations are denied and logged.
›Layer the workspace with dependencies pointing inward: the security crate sits below MCP, agent and UI, so policy changes do not touch rendering or model backends.
›Queue approvals and process them in order in a focused terminal overlay, so the operator reviews one request at a time.
›Design emergency stop to halt new requests and cancel or deny pending work, leaving an audit trail.
›Use one typed command contract (UiIntent) and typed orchestrator events between the UI and the runtime, instead of parsing strings.
How it's secured and shipped
✓Defensive by design: every tool request passes scope validation and operator approval before it runs.
✓Emergency stop and an audit trail of what ran.
✓Cargo workspace with format, clippy and test commands as the quality gate.