Skip to main content

Policy Engine & Decision Gate

How the policy engine (NSR) governs agentic action execution inside the Temporal orchestration engine, with the control plane as the authoring and sync layer.
The decision gate is rolled out per brand in stages, so whether it is authoritative for a given brand depends on that brand’s configuration. Do not assume a mutating action is gated β€” check the brand’s rollout stage before relying on it.

The three planes

The system separates who decides policy, who reasons about it, and who executes into three planes with clean contracts between them.

Policy lifecycle

  1. Author β€” a human writes policy in natural language; prompt-to-rule compiles it into NSR rules. Structured limits β€” max auto-refund, blocked actions β€” live in AutomationConfig.policy_controls and the unified GuardrailPolicy.
  2. Sync β€” sync-org-rules and bootstrap-guardrails push the org’s rules into NSR’s per-org knowledge base. The engine never holds the rule store; it references the org KB that NSR hydrates server-side.
  3. Enforce β€” at runtime the workflow asks NSR to authorize each mutating action.
  4. Learn β€” record_decision_outcome feeds executed and reverted outcomes back into NSR’s forward chain so rules sharpen over time.

Two NSR touchpoints

NSR is consulted twice, for different jobs. Keeping them separate is the core design decision. The reasoning call shapes what the agent says and proposes. The decision gate governs whether a mutating action is allowed to run.
A confidence number from the reasoning surface is not an authorization. That is the gate’s job β€” and the gate can refuse, escalating to a human, rather than guess.

Where it sits in the workflow

evaluate_action_policies is a pure function applying the structured action_rules β€” blocked, require_review, and max_auto_amount. The decision gate runs alongside it; where enabled, its verdict is the source of truth.

The verified decision gate

Read-only actions skip the gate entirely. For each mutating proposed action:

Two safety properties

These are baked into gate_outcome and unit-tested:
  • Grounded-only approvals β€” an Approved verdict only executes when its proof status is grounded. A confident-but-ungrounded approval escalates instead.
  • Fail-closed β€” Refused and the transport-failure fallback always escalate. An unreachable policy engine never yields execution.
Fail-closed means an NSR outage degrades into human review, not into unauthorized automation. Capacity-plan the review queue accordingly.

Why host the gate in Temporal

Putting the gate in a durable workflow rather than a synchronous API guard buys three properties:
  1. Deterministic, auditable replay β€” the verdict and proof chain that authorized an action live permanently in the workflow’s event history. Replays reuse it, so the audit trail is the execution itself rather than a separate log that can drift.
  2. Durable human review β€” Refused is a first-class state, not an error. The workflow parks on a signal and waits hours or days for a human verdict. A synchronous guard cannot do this.
  3. Safe rollout β€” new gate logic is patched()-gated, so in-flight workflows replay deterministically on the old path while new executions take the new one.

Key types