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, approval_mode, eligibility rules, schema-validated inputs and outputs. At runtime the contract produces a DecisionRecord carrying the chosen outcome, evidence_refs, approvals, controls_active, policy_decisions, and trace_id.
Why it exists
Without typed decisions, the runtime returns free-form text. Free-form text cannot be validated against a policy, cannot be replayed, cannot be compared across runs, and cannot be audited. Typed decisions move the contract above the model so the spec — not the prompt — is the source of truth for what the runtime is allowed to produce.
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 ContextPackCompiler includes the spec in
decision_layer.decision_specs[]. - 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.
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 | the evidence_ref keys that must be resolved before commit |
allowed_outcomes | the closed set of legal outcomes the runtime may emit |
approval_mode | the highest mode this decision can produce; routed through Orchestrator’s propose/approve/execute for destructive and delegated |
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 | governance owner; required for change-control review |
DecisionRecord
The runtime emits one record per decision checkpoint. The dedicated guide is Decision Record; the compact envelope appears in API Contracts.
Required minimum fields: record_id, decision_key, decision_version, timestamp, status, actor, outputs, evidence_refs, policy_decisions[], approvals[], controls_active, budget_usage, lineage, trace_id.
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": "decision.support.refund.execute"
}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 authored without
required_evidence— runtime accepts any decision (must reject at validate time). - Outcome chosen outside
allowed_outcomes— runtime rejects. approval_modeon the spec is lower than the policy decision’s effective mode — runtime escalates.- 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 (target: 100%).
- Approval-mode misclassification 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",
"status": "DECIDED",
"actor": { "type": "AGENT", "id": "agt_support" },
"outputs": { "eligible": true, "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": [] },
"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.