Tutorial 3: Wire a typed Decision Catalog entry
Author a DecisionSpec with required_evidence so the Critic produces a typed, replayable DecisionRecord.
After the illustrative gated call in Tutorial 2, this walkthrough defines its typed DecisionRecord against a DecisionSpec. The implementing runtime performs execution, outcome validation and persistence; the compiler derives evidence gates rather than shipping that complete service. The execution attachments separately bind current authority, exact approval, stable operations and verified effects.
What we are building
A spec declares the closed contract for one kind of decision.
{
"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",
"decision_right": "execute",
"challenge_required": false
}These are obligations the implementing runtime must enforce, beyond JSON shape validation:
required_evidence— the Critic refuses to commit if any entry is unresolved.allowed_outcomes— the runtime rejects an outcome outside the closed set.approval_mode— required v1 compatibility ceiling; it must not understate any tool the decision may invoke, while native risk is evaluated separately.decision_right—propose/recommend/execute/escalate. The runtime refuses execute on arecommend-only spec.
The decision_binding field on the rule (from Tutorial 2) is what ties the policy decision to the DecisionRecord.
{ "rule_id": "R_HIGH_VALUE_REQUIRES_APPROVAL", "decision_binding": "support.refund.execute" }Use the exact registered decision key; the fragment is not a complete PolicyRule. Retain actual evaluated policy IDs/rule refs on the record. An applicable predicate error stops compilation with structured ContextCompileError, not false/else or a successful partial context.
After the canonical loop completes, the implementing runtime emits a schema-valid record like this:
This display assumes the refund effect and required postconditions have been verified. Abbreviated hashes are placeholders; a DECIDED record or approval receipt alone cannot prove a payment occurred. Keep exact action/stored approval/operation artifacts correlated under the admitted profile.
{
"record_id": "dr_2026_05_04_a17",
"decision_key": "support.refund.execute",
"decision_version": "1.0.0",
"timestamp": "2026-05-04T09:31:42Z",
"status": "DECIDED",
"actor": { "type": "AGENT", "id": "agt_support" },
"outputs": { "outcome": "approved", "refund_amount_inr": 4200, "currency": "INR", "transaction_id": "txn_q9..." },
"evidence_refs": [
"kg:order:ord_881#snapshot_kg_2026_05_03_T0930",
"tool:adp_orders.lookup:tc_117",
"tool:adp_policy.eval:tc_119",
"tool:adp_payments.issue_refund:tc_121"
],
"policy_decisions": [
{ "policy_decision_id": "pol_9900", "rule_ids": ["R_REFUND_REQUIRES_IDV"] },
{ "policy_decision_id": "pol_9901", "rule_ids": ["R_HIGH_VALUE_REQUIRES_APPROVAL"] }
],
"approvals": [{ "gate_id": "GATE_FINANCE_APPROVAL", "approver": "user_finance_lead_77", "approval_mode_effective": "destructive", "evidence_snapshot_hash": "sha256:b2a1...", "decided_at": "2026-05-04T09:31:30Z" }],
"controls_active": { "must_refuse": [], "must_escalate": [], "approval_gates_active": ["GATE_FINANCE_APPROVAL"], "redaction_rules_active": ["pan", "credit_card"] },
"budget_usage": { "tokens": 4720, "tool_calls": 4, "cost_usd_cents": 0.91, "wall_clock_ms": 1840 },
"lineage": { "pack_version": "ctxpack.support@5.2.0", "snapshot_version": "kg_2026_05_03_T0930" },
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}Notice three properties:
- Pack/snapshot lineage is part of the complete replay input; request, Run Context/budget, policy, supplied evidence/memory/conflicts and recorded model/tool artifacts also matter.
- Evidence requirement names are matched through admitted
satisfies[]or authenticated structured context;evidence_refsresolves the actual artifacts, rather than merely repeating requirement names. policy_decisions[]lists every rule that fired, withpolicy_decision_idfor cross-correlation.
The Decision Catalog component re-validates every record on emission. Failures are typed:
{ "error_code": "OUTCOME_OUT_OF_RANGE", "detail": "Outcome 'partial_refund' is not in allowed_outcomes." }
{ "error_code": "EVIDENCE_MISSING", "detail": "Requirement 'identity_verified' has no admitted current verified evidence or authenticated context." }
{ "error_code": "APPROVAL_MODE_TOO_LOW", "detail": "Tool emitted delegated below its registered capability's destructive projection." }These are illustrative local decision-validation diagnostics, not new base error enums. The runtime reports denial/escalation or a bounded replan as appropriate; it must not dispatch a protected effect on failed evidence. Compilation can separately throw the structured policy error described above. A replan shares the original aggregate budget and cannot authorize repeating an unknown external effect.
What’s next
Tutorial 4: Close the improvement loop — turn an operator correction into a release-gated StrategyRule.