clavenar‑proxymTLS MCP ingress. Stamps a UUID‑v4 correlation_id on every request, runs the Brain + Policy pipelines to completion, returns the verdict. The single piece every other component fans out from.
Clavenar runs every agent action through four decision layers, folds independent security signals into one verdict, parks the risky ones for human approval, and writes the result into a hash‑chained ledger you can hand to an auditor. Production deployments add supporting services around those layers; they do not change the decision model.
MCP or SDK wrapper emits a normalized request.
Stamps correlation_id and fans out checks.
Semantic signals and deterministic policy fold together.
Allow, park for HIL, or deny before the side effect fires.
Every terminal outcome becomes a chained proof row.
An LLM with tool access can read inboxes, query production databases, move money, deploy code. Existing controls — WAFs, IAM, RBAC — assume a human at the keyboard or a programmatic API client with a fixed surface. They don't understand intent, can't detect prompt injection, and don't track which prompt caused which tool call at audit time.
Clavenar sits between the agent and its tools. Every tool_use block goes through inspection, policy, optional human approval, and lands as one row in an append‑only ledger. The agent doesn't have to be aware Clavenar exists — the SDKs wrap the provider client transparently.
Each layer owns one concern and runs to completion before the next. HIL, identity, sandbox, and console are supporting services around the four-layer decision path; they are not extra verdict layers. The split exists so a failure in one concern is bounded — a Brain outage doesn't stop policy evaluation; a Ledger outage doesn't block the data plane.
clavenar‑proxymTLS MCP ingress. Stamps a UUID‑v4 correlation_id on every request, runs the Brain + Policy pipelines to completion, returns the verdict. The single piece every other component fans out from.
clavenar‑brainThree independent security signals run in parallel: intent classification (a pluggable inspector LLM — Claude Haiku 4.5 by default, swappable via CLAVENAR_BRAIN_MODELS_FILE), persona drift (cosine distance against a golden embedding), indirect‑injection detection (a separate inspector call with a security‑only system prompt).
clavenar‑policy‑enginePure‑Rust Rego evaluator (regorus). Deterministic anchor when the LLM heuristics shouldn't fire. Operator‑authored policies; ships with seven starter templates.
clavenar‑ledgerSHA‑256 hash‑chained, SQLite or Postgres‑backed append‑only audit. Every row chains SHA256(prev_hash · row_bytes); GET /verify walks the chain end‑to‑end.
Adjacent services: clavenar‑hil (orchestrates yellow‑tier human approval), clavenar‑identity (mints SVIDs and delegation grants — the only component that issues credentials), clavenar‑sandbox (static MCP‑call analyzer; annotates HIL pendings with predicted blast radius), clavenar‑console (operator UI). Wire contracts in TECH_SPEC.md.
A single risky tool call produces a verdict, a human-review state, and a replayable audit trail. The agent code only sees the SDK exception; operators and auditors see the full chain.
POST /mcp
{
"method": "call_tool",
"params": {
"name": "stripe.refund",
"arguments": { "amount": 84210 }
}
}
Privileged Action0.31 below hard thresholdfalseHTTP/1.1 202 Accepted
{
"status": "pending",
"tier": "yellow",
"correlation_id": "6d28bb41...",
"ttl_secs": 300
}
The ledger stores the parked verdict, the operator decision, and the upstream outcome under the same correlation_id.
GET /audit/correlation/6d28bb41...GET /verifyThe Brain runs all three signals on every cache‑miss request. Either persona drift over the threshold OR injection detected forces authorized=false regardless of the classifier's verdict. Three orthogonal gates, any one of which can hard‑veto.
An inspector‑LLM call buckets the request as Direct Execution / Information Retrieval / Privileged Action / Meta‑Reasoning. The provider is pluggable — Claude Haiku 4.5 ships as the default fast path, with Claude Opus 4.x routed in on destructive‑keyword params, and any provider (OpenAI, Google, Bedrock, Vertex, Ollama) swaps in via CLAVENAR_BRAIN_MODELS_FILE. The classifier sees the persona text and the request body; it does not see the result of the other two signals.
Numeric, not an LLM opinion. The agent has a frozen "golden persona" file (personas/<agent_id>.md); drift is 1 − cosine_similarity(request_embedding, persona_embedding) using Voyage AI's voyage‑3 model. A hard threshold (0.6) flips the verdict — there is no LLM judgement in the loop.
A separate inspector‑LLM call (Claude Haiku 4.5 by default; any provider via CLAVENAR_BRAIN_MODELS_FILE) with a security‑only system prompt evaluates the payload for hijack attempts. Zero‑knowledge isolation: a payload that successfully prompt‑injects the agent's own model still has to defeat a different model with a different system prompt to slip past Clavenar.
Accuracy, false positives, false negatives, latency, caveats, and reproduction commands live in clavenar‑brain BENCHMARK.md. Methodology is open‑sourced; bring your own competitor for a side‑by‑side.
Policy decides which tier each call lands in. green auto‑allows; red auto‑denies; yellow parks at the HIL service until an operator decides via the console, Slack deep‑link, or the SDK resolve() helper.
Reads, list operations, scoped low‑risk writes. Rego decides; the operator never sees the call.
ClavenarPendingMoney moves, prod‑DB writes, off‑hours actions, persona drift edges. Sandbox annotates predicted blast radius. Operator approves or denies in the console / Slack.
ClavenarDeniedDrop‑table, IAM rewrites, persona drift hard threshold, injection detected. SDK throws; the agent never sees the response.
The OSS edition supports an async HIL flow via X‑Clavenar‑Callback‑URL: clavenar‑lite POSTs the operator's decision to the supplied URL when the human decides, so an agent doesn't have to long‑poll.
A new policy can deny in shadow before it denies in production. Both clavenar‑lite and the multi‑service stack ship the same observe‑vs‑enforce switch.
allow, logs everything, exposes a would_deny counter in /metrics. Use this for the first week of any new policy. Set CLAVENAR_LITE_MODE=observe or CLAVENAR_MODE=observe.ClavenarDenied, yellow throws ClavenarPending.The console dashboard renders would_deny alongside live deny so an operator can see "what would have broken" before flipping the switch.
The control plane is security infrastructure, so the important question is not only what it blocks, but how it behaves during rollout, cache hits, provider latency, and service degradation.
| Concern | Operator expectation | Where to verify |
|---|---|---|
| Rollout safety | observe mode forces allow, logs every verdict, and exposes would_deny before enforcement. |
/metrics, console dashboard, audit rows |
| Hot path latency | Exact verdict-cache hits avoid provider round trips; published mock-mode p95 at proxy boundary is 2.20 ms. | clavenar-perf-harness, benchmark notes |
| Cache miss latency | Clavenar overhead is measured separately from live LLM provider RTT; provider calls dominate uncached live inspection. | Benchmark caveats, provider logs |
| Brain outage | Policy evaluation remains deterministic and can still deny known-bad actions. | Policy verdict rows, service health |
| Ledger outage | The data plane is not blocked by the forensic store; operators should alert on proof-path health. | GET /verify, ledger health, export sink lag |
| Human review | Yellow calls park before the upstream side effect and resolve through console, Slack deep-link, callback, or SDK helper. | ClavenarPending, HIL queue, callback logs |
The ledger is append‑only. Each row contains the request, the verdict, the policy version, the operator's NameID (if HIL), and a SHA‑256(prev_hash · canonical_row_bytes) chain pointer. Any tampering — even a one‑byte change — breaks the chain at the next /verify walk.
GET /audit/correlation/{uuid}GET /audit/agents/{agent_id}/narrative (rolling 1d / 7d / 30d / 90d window; "everything agent‑X did this week" rendered as a story, not rows)GET /verifyStorage backend is pluggable (SqliteLedgerStore or PostgresLedgerStore) behind a Cargo feature; the hash‑chain shape is byte‑identical across both, so a SQLite ledger snapshot can be replayed against a Postgres restore without re‑hashing.
These are the short definitions behind the wire format and operator UI.
Model Context Protocol traffic carrying tool calls between an agent runtime and tools.
Human‑in‑the‑loop review for yellow‑tier calls before side effects fire.
SPIFFE Verifiable Identity Document minted by identity for workload authentication.
The SAML subject recorded when an operator approves or denies a pending call.
Policy language evaluated by the Rust policy engine for deterministic governance.
Distance between the request and the agent's frozen golden persona embedding.
UUID stamped at ingress and carried through verdict, HIL, upstream, and audit rows.
Shadow mode that logs would‑deny decisions without blocking the agent.