Architecture¶
Overview¶
Rampart is a policy enforcement layer between AI agents and their tools. Every tool call passes through Rampart, which evaluates it against YAML policies and returns allow, deny, or log.
graph TB
A[Agent] -->|tool call| R[Rampart]
R --> PE[Policy Engine]
PE --> I[Interceptors]
I --> D{Decision}
D -->|allow| T[Tool Executes]
D -->|deny| B[Blocked]
D -->|log| L[Flagged + Allowed]
R --> AU[Audit Sink]
AU --> J[JSONL Files]
AU --> S[Syslog/CEF]
AU --> W[Webhooks] Design Decisions¶
Fail-open by default. If Rampart crashes, tool calls pass through. Fail-closed locks you out of your machine. Configurable for strict environments.
Custom YAML over OPA/Rego. The domain is narrow — "should this tool call run?" Custom engine evaluates in <10μs vs OPA's 0.1-1ms.
Local-first. No data leaves the machine. No cloud dependency. No telemetry.
Deny-wins evaluation. Any policy says deny → denied. No ambiguity.
Components¶
Policy Engine (internal/engine/)¶
The hot path. Loads YAML policies, evaluates tool calls.
Evaluation order:
- Collect matching policies by tool type
- Within each policy, rules evaluate top-to-bottom (first match wins)
- Across policies: any deny → denied
- Nothing matches → default action
Hot-reloads via fsnotify.
Interceptors (internal/intercept/)¶
Per-tool normalization before the engine sees the call:
| Interceptor | What It Does |
|---|---|
| exec | Command pattern matching, binary extraction |
| read/write | Path normalization, glob matching |
| fetch | URL parsing, domain extraction |
Audit Sink (internal/audit/)¶
Append-only JSONL with SHA-256 hash chaining.
- ULID event IDs (time-ordered)
- External anchor every 100 events
fsyncon every write- Log rotation with chain continuity
Proxy Server (internal/proxy/)¶
HTTP server for tool evaluation. Bearer token auth, localhost-only.
| Endpoint | Purpose |
|---|---|
POST /v1/tool/{name} | Evaluate and execute |
POST /v1/preflight/{name} | Dry-run check |
GET /v1/approvals | Pending approvals |
POST /v1/approvals/{id}/resolve | Approve/deny |
GET /healthz | Health check |
Approval Store (internal/approval/)¶
Thread-safe store for require_approval decisions. ULID-keyed, configurable timeouts.
Wrap Command¶
Starts embedded proxy → generates shell shim → sets $SHELL → execs child. Transparent to the agent.
Preload Library (preload/)¶
~500 lines of C. Intercepts execve, execvp, system(), popen(), posix_spawn(). HTTP client via libcurl. Fail-open on server unreachable.
Project Layout¶
cmd/rampart/ CLI (cobra)
internal/
engine/ Policy evaluation (the core)
audit/ Hash-chained JSONL audit trail
intercept/ Tool-specific interceptors
proxy/ HTTP proxy server
approval/ Human approval flow
daemon/ OpenClaw WebSocket integration
watch/ Terminal dashboard (bubbletea)
pkg/sdk/ Public Go SDK
policies/ Built-in profiles
preload/ C library for LD_PRELOAD
Integration Patterns¶
| Pattern | How | Best For |
|---|---|---|
| Native hooks | Agent's hook system calls rampart hook | Claude Code, Cline |
| Wrap | $SHELL shim intercepts commands | Aider, OpenCode |
| MCP Proxy | Transparent MCP protocol proxy | Claude Desktop, Cursor |
| LD_PRELOAD | Syscall interception | Codex CLI, any process |
| HTTP API | Direct REST calls | Python agents, custom |
| Go SDK | Embed engine in Go code | Go agents |