Skip to content
Press / to search

Decision Catalog

Typed Decision Specs — the catalog layer between model reasoning and governed business action.

Implementation GuideLast reviewed: Edit on GitHub
At a glance

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

  1. Author a DecisionSpec for a kind of decision (e.g., support.refund.execute).
  2. Bind policy rules and tool capabilities to the decision_key via decision_binding.
  3. Compile — the ContextPackCompiler includes the spec in decision_layer.decision_specs[].
  4. Verify — at the decision checkpoint, the Critic checks required_evidence is resolved and the chosen outcome ∈ allowed_outcomes.
  5. Record — the runtime emits a DecisionRecord against 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

FieldMeaning
decision_keystable identifier the policy and adapter layers bind to
required_evidencethe evidence_ref keys that must be resolved before commit
allowed_outcomesthe closed set of legal outcomes the runtime may emit
approval_modethe highest mode this decision can produce; routed through Orchestrator’s propose/approve/execute for destructive and delegated
eligibility_rulesJsonLogic predicate that gates whether this spec applies to a given Run Context
decision_rightone of propose, recommend, execute, escalate — what the runtime is allowed to do under this spec
owner_rolegovernance 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

  • DecisionRecord with 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_mode on 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.