The two engines
Policy Engine
Pure function
evaluatePolicy(policy, input) → { allowed, requiresApproval, reason }. Deterministic, declarative, plan-tier-agnostic.Risk Engine
Stateful. 5 signals (velocity, amount-anomaly, geo, session, time-anomaly). Score 0–100 with tunable thresholds for review/deny/freeze.
Policy: what can be expressed
Policies are JSON-serializable objects attached to an agent (one policy per agent at a time). The full schema lives in/concepts/policies — here’s the surface:
Risk: signals and thresholds
Score is a weighted aggregate. Thresholds are tunable per policy (5min cache):
Where Control runs
decision_logs with the full signal payload, the score, the reason, and the action taken. Queryable via /audit and /risk/violations.
Card-controls sync
When you change a policy, the system translates the relevant fields into card-issuer-native controls (MCC rules, country rules, per-tx limits) and pushes them to the underlying card. Policy is the source of truth; the card mirror is best-effort and is reconciled on every update.Approval workflow
WhenenforcementLevel: "approve" or risk action is review, the intent enters pending_approval. Approve via:
POST /intents/:id/deny with an optional reason.
Quick example — read an agent’s policy
Pre-built presets
policy-presets.ts ships templates for common patterns: travel-only, subscriptions, dev-tools, etc. Use them as starting points in the dashboard create flow.
Surfaces
Next
Policies
Full field reference with examples for each rule.
Intents
The approval-bearing primitive Control gates.
Intelligence
What Control writes — decision logs, audit, anomaly detection.
Disputes
What happens when something Control allowed turns out to be wrong.
