Decision Catalog
Typed Decision Specs — the catalog layer between model reasoning and governed business action.
The Decision Catalog is the registry of typed DecisionSpec entries that the Critic and the Policy Engine consume. Every governed action in ContextOS resolves to a DecisionSpec and produces a DecisionRecord.
Definition
A versioned catalog of typed decision contracts. Each DecisionSpec declares decision_key, version, required_evidence, allowed_outcomes, the required v1 approval_mode compatibility ceiling, and optional eligibility/input/output contracts. A conforming implementation produces a DecisionRecord carrying the accepted outcome and its evidence, controls, policy decisions, approvals, lineage, budget, and trace.
Why it exists
Free-form explanations alone do not identify a governed outcome or its acceptance criteria. Typed decisions let the runtime validate a closed outcome set, compare results, and retain evidence for replay and audit. Explanatory text can accompany that record; it does not substitute for the typed outcome or authorize an effect.
How it works
- Author a
DecisionSpecfor a kind of decision (e.g.,support.refund.execute). - Bind policy rules and tool capabilities to the
decision_keyviadecision_binding. - Compile — the pack supplies
decision_layer.decision_specs[]; the ContextPackCompiler derives the applicable evidence gates and runtime controls.decision_layeris a pack field, not an additionalCompiledContextfield. - Verify — at the decision checkpoint, the Critic checks
required_evidenceis resolved and the chosenoutcome ∈ allowed_outcomes. - Record — the runtime emits a
DecisionRecordagainst the spec and persists it.
Evidence sufficiency and an allowed outcome establish decision eligibility. Before an external effect, the Gateway separately checks the exact ActionBinding and execution contract, current authority and policy, any required approval, boundary/data readiness, and reserved budget. A DECIDED record does not prove that a payment occurred; retain the operation’s verified effect observation and postcondition evidence.
DecisionSpec
{
"decision_key": "support.refund.execute",
"version": "1.0.0",
"owner_role": "support_ops",
"required_evidence": ["order_lookup", "policy.eval", "identity_verified"],
"allowed_outcomes": ["approved", "denied", "escalated"],
"approval_mode": "destructive",
"inputs_schema_ref": "schema://decision.support.refund.execute.inputs.v1",
"outputs_schema_ref": "schema://decision.support.refund.execute.outputs.v1",
"eligibility_rules": {
"and": [
{ "==": [{ "var": "intent" }, "support.refund"] },
{ ">": [{ "var": "request.context.refund_amount" }, 0] }
]
},
"decision_right": "execute",
"challenge_required": false
}Field semantics
| Field | Meaning |
|---|---|
decision_key | stable identifier the policy and adapter layers bind to |
required_evidence | requirement names resolved by admitted evidence’s satisfies[] entries or explicit structured request context; a name is not itself an immutable evidence artifact |
allowed_outcomes | the closed set of legal outcomes the runtime may emit |
approval_mode | required v1 compatibility ceiling; native capability and call risk remains multidimensional, and propose/approve/execute runs only when policy emits an approval obligation |
eligibility_rules | JsonLogic predicate that gates whether this spec applies to a given Run Context |
decision_right | one of propose, recommend, execute, escalate — what the runtime is allowed to do under this spec |
owner_role | optional in the base type; assign an accountable governance owner under the deployment’s change-control policy |
DecisionRecord
The runtime emits one record per decision checkpoint. The dedicated guide is Decision Record; the compact envelope appears in API Contracts.
Base-schema required fields: record_id, decision_key, decision_version, timestamp, status, actor, evidence_refs, policy_decisions[], approvals[], controls_active, budget_usage, lineage, and trace_id. The active DecisionSpec can additionally require typed outputs and other domain fields.
Decision binding (in policy rules)
A policy rule binds to a decision via decision_binding:
{
"rule_id": "R_HIGH_VALUE_REQUIRES_APPROVAL",
"applies_to": { "intent": "support.refund" },
"if": { "and": [
{ "==": [{ "var": "user.role" }, "support_agent"] },
{ ">": [{ "var": "request.context.refund_amount" }, 3000] }
]},
"then": {
"allow": true,
"approval_mode": "destructive",
"requires_approval_gate": "GATE_FINANCE_APPROVAL"
},
"decision_binding": "support.refund.execute"
}Use the exact registered decision_key. The decision. prefix inside this page’s illustrative schema URIs is not part of that key. An applicable policy-expression error stops compilation with a structured ContextCompileError; it must not silently select another outcome or authorize execution.
Status values
DECIDED, DEFERRED, REJECTED, ESCALATED, IN_FLIGHT, CLOSED. The Critic chooses the status based on its scoring verdict and the gate state.
Interfaces
Inputs
- Run Context (with claims, role, tenant)
- Compiled
evidence_manifest - Tool transcripts that produced the evidence
- Active policy decisions
Outputs
DecisionRecordwith all required fields populated- Memory write proposals tagged by decision_key
Failure modes
- Spec missing the required
required_evidencefield — reject the malformed spec. An intentionally empty list is structurally legal; the workflow’s admission and acceptance policy must determine whether it is sufficient. - Outcome chosen outside
allowed_outcomes— runtime rejects. - The DecisionSpec v1 ceiling is lower than the capability’s conservative projection — deny or escalate through an explicit policy path; never silently lower the capability projection.
- A governed capability lacks native
ActionRiskunder an activeaction_risk_policy— fail closed. - Decision Record emitted without
policy_decisions[]— audit gap; release-gate failure. - Spec versions drift across environments.
Operational concerns
- Spec versioning per environment; promotion is deliberate.
- Schema-ref availability is in the critical path.
- Append-only persistence of decision records for replay and audit.
- Owner-role assignment for every spec; orphan specs flagged.
- Evaluator scoring per spec, not just per intent.
Evaluation metrics
- Decision-correctness on golden set per
decision_key. - Outcome distribution drift across releases.
- Evidence-resolution rate for decisions admitted to commit (target: 100%); separately measure blocked and unresolved cases.
- Native-risk policy mismatch rate and v1 projection mismatch rate.
- Mean time from challenge to decision under
challenge_required.
Example
Refund-eligibility decision spec and one resulting record:
{
"decision_spec": {
"decision_key": "support.refund.eligibility",
"version": "1.2.0",
"required_evidence": ["order_lookup", "policy.eval"],
"allowed_outcomes": ["eligible", "ineligible"],
"approval_mode": "read_only",
"decision_right": "recommend"
},
"decision_record": {
"record_id": "dr_2026_05_04_a17",
"decision_key": "support.refund.eligibility",
"decision_version": "1.2.0",
"timestamp": "2026-05-04T09:31:42Z",
"status": "DECIDED",
"actor": { "type": "AGENT", "id": "agt_support" },
"outputs": { "outcome": "eligible", "reason": "within_window_and_idv_passed" },
"evidence_refs": ["tool:orders.lookup:tc_117", "tool:policy.eval:tc_119"],
"policy_decisions": [{ "policy_decision_id": "pol_9900", "rule_ids": ["R_REFUND_REQUIRES_IDV"] }],
"approvals": [],
"controls_active": { "must_refuse": [], "must_escalate": [], "approval_gates_active": [], "redaction_rules_active": [] },
"budget_usage": { "tokens": 1280, "tool_calls": 2, "cost_usd_cents": 0.22, "wall_clock_ms": 640 },
"lineage": { "pack_version": "ctxpack.support@5.2.0", "decision_spec": "support.refund.eligibility@1.2.0" },
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}
}Common misconceptions
- A decision is not a prediction. It is a typed, validated, evidence-bound outcome from
allowed_outcomes. - A DecisionRecord is not a log line. It is the audit and replay artifact.
- Decision binding is not optional for governed actions. Without it, policy and the spec drift apart.