signet-eval

Deterministic policy enforcement for AI agents. Control what your agent can do — spending limits, destructive command blocking, credential gating — without putting an LLM in the decision path.

25ms
hook eval (e2e)
14–63μs
in-process eval
14
condition functions
17
MCP tools
cargo install signet-eval

Three Steps

1. Install: cargo install signet-eval

2. Hook into Claude Code:

{
  "hooks": {
    "PreToolUse": [{
      "matcher": "",
      "hooks": [{"type": "command", "command": "signet-eval", "timeout": 2000}]
    }]
  }
}

3. Done. Every tool call now passes through policy evaluation.

Default Policy

Self-protection rules are LOCKED — the agent cannot remove, edit, or reorder them, even through the MCP management server.

ActionDecision
Write/Edit/Bash to .signet/ LOCKEDDENY
Tamper with signet-eval binary LOCKEDDENY
Modify settings.json LOCKEDASK
Kill signet processes LOCKEDDENY
rm, rmdirDENY
git push --forceASK
mkfs, format, dd if=DENY
curl | sh, wget | shDENY
Everything elseALLOW

Custom Rules

# ~/.signet/policy.yaml
version: 1
default_action: ALLOW
rules:
  - name: books_limit
    tool_pattern: ".*purchase.*"
    conditions:
      - "param_eq(category, 'books')"
      - "spend_plus_amount_gt('books', amount, 200)"
    action: DENY
    reason: "Books spending limit ($200) exceeded"

  - name: protect_prod
    tool_pattern: ".*"
    conditions: ["contains(parameters, 'production')"]
    action: ASK
    locked: true
    reason: "Production access requires confirmation"

Condition Functions

FunctionDescription
contains(parameters, 'X')Tool input contains string
any_of(parameters, 'X', 'Y')Any string present
param_eq(field, 'value')Field equals value
param_ne(field, 'value')Field not equal
param_gt(field, N)Field > number
param_lt(field, N)Field < number
param_contains(field, 'X')Field contains substring
matches(field, 'regex')Field matches regex
has_credential('name')Credential exists in vault
spend_gt('cat', N)Session spend exceeds limit
spend_plus_amount_gt('cat', field, N)Cumulative spend + amount exceeds limit
not(condition)Negate any condition
or(A || B)Either condition true
true / falseLiteral boolean

Features

Self-Protection

Four locked rules prevent the agent from disabling its own guardrails. Locked rules can't be removed or edited via MCP. Direct file edits break the HMAC signature, triggering fallback to hardcoded safe defaults.

Encrypted Vault

Argon2id + AES-256-GCM. Three tiers: public ledger, session-encrypted state, compartment-encrypted credentials. Session key encrypted with device-specific key. Brute-force lockout after 5 failed attempts.

Spending Limits

Track cumulative spend per category. "Don't spend more than $200 on books" just works. Vault ledger enforces across every tool call. Reset with signet-eval reset-session.

Scoped Credentials

Store credentials with domain, purpose, amount caps, and one-time constraints. signet_use_credential enforces all constraints before releasing. One-time tokens auto-invalidate.

MCP Management

Manage policies by talking to Claude. "Add a $50 limit for amazon orders." 17 MCP tools: rules, credentials, testing, validation, reordering, signing, credential use.

MCP Proxy

Wrap upstream MCP servers with enforcement. Hot-reloads policy on every call. The agent connects to the proxy, not directly to servers.

Policy Integrity

HMAC-sign your policy file. Hook verifies integrity on every evaluation. Tampered files fall back to safe defaults automatically. MCP mutations auto-sign.

Locked Rules

Mark rules as locked: true in YAML. MCP tools refuse to modify them. Unlocked rules can't be reordered above locked ones. Self-protection rules ship locked by default.

Architecture

Part of the Signet personal sovereign agent stack. The core principle: the authorization layer must not be an LLM. It processes structured data only. No natural language, no context window, no persuasion surface. A rule either matches or it doesn't.

Agent proposes action  ->  signet-eval evaluates policy  ->  allow / deny / ask
                           (deterministic, 25ms, no NLP)

Security Model

signet-eval is a seatbelt, not a cage. It enforces policy within a cooperative protocol — Claude Code calls signet-eval before every tool use and respects the response. This reliably blocks destructive commands, enforces spending limits, and gates credential access during normal operation.

It does not protect against an adversarial agent with shell access. Any process at the same privilege level can use shell indirection (alias, eval, base64 | sh) to evade string matching, read the session key, or replace the binary. No amount of pattern matching fixes this — it's an infinite regress.

True containment requires OS-level controls: separate user accounts, containers, stripped $PATH, seccomp/AppArmor, or sandboxed environments. signet-eval is the policy engine inside such a perimeter. The OS enforces the perimeter. Neither replaces the other.

All Commands

CommandPurpose
signet-evalHook evaluation (default, 25ms)
signet-eval initWrite default policy with locked self-protection
signet-eval rulesShow current rules (locked rules tagged)
signet-eval validateCheck policy for errors
signet-eval test '<json>'Test a tool call
signet-eval setupCreate encrypted vault
signet-eval unlockRefresh vault session
signet-eval statusVault status and spending
signet-eval store <n> <v>Store Tier 3 credential
signet-eval delete <n>Delete credential
signet-eval logRecent action log
signet-eval reset-sessionClear spending counters
signet-eval signHMAC-sign policy file
signet-eval serveMCP management server (17 tools)
signet-eval proxyMCP proxy for upstream servers