Skip to content
Press / to search

Tutorial 3: Wire a typed Decision Catalog entry

Author a DecisionSpec with required_evidence so the Critic produces a typed, replayable DecisionRecord.

TutorialLast reviewed:
At a glance

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

consumed by emits persisted replays feeds DecisionSpecCriticDecisionRecordAudit StoreEvaluation EngineImprovement Loop
DecisionSpec → Critic → DecisionRecord → Audit Store → Evaluation Engine → Improvement Loop
1
Author the DecisionSpec

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 a recommend-only spec.
2
Bind a policy rule to the 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.

3
Inspect the emitted DecisionRecord

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_refs resolves the actual artifacts, rather than merely repeating requirement names.
  • policy_decisions[] lists every rule that fired, with policy_decision_id for cross-correlation.
4
Validate the record against the spec

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.