Skip to main content

Explain & Debugging

The Explain & Debugging APIs help you understand why a policy produced a specific decision.

This is one of the most important trust-building capabilities in the JavaScript SDK because it makes policy decisions transparent during development, testing, rollout, and production support.

The JavaScript SDK provides three real explain surfaces:

  • policy.explain()
  • runtime.explain()
  • runtime.explainCall()

Core Mental Model​

Same decision path, but human-readable output

Explain APIs use the same compiled policy evaluation flow while surfacing:

  • resolved action
  • actor
  • snapshot
  • final effect
  • matched rule

This makes them ideal for root-cause analysis.


policy.explain()​

Use when you already have a full evaluation input.

policy.explain({
action: {
type: "refund",
amount: 5000,
},
actor: {
role: "finance",
},
snapshot: {
is_locked: false,
},
})

This evaluates the policy and prints structured output for:

  • action
  • actor
  • snapshot
  • result

It also returns the Decision object.


runtime.explain()​

Use when debugging runtime decisions with resolvers.

runtime.explain({
type: "deploy",
environment: "production",
})

This automatically:

  1. resolves actor
  2. resolves snapshot
  3. evaluates policy
  4. returns decision

Best for:

  • local debugging
  • staging validation
  • rollout safety
  • live issue triage

runtime.explainCall()​

The strongest debugging API for protected functions.

runtime.explainCall(refundOrder, {
args: ["order_123", 5000],
actionName: "refund",
})

This reconstructs the exact action payload using:

  • object-first normalization
  • explicit field mapping
  • schema-driven mapping

Then it evaluates using the same runtime flow.

This is excellent for:

  • API route debugging
  • worker failures
  • CI function tests
  • agent tool tracing
  • production support

Example Debugging Workflow​

A common real-world flow:

const decision = runtime.explainCall(processRefund, {
args: ["order_123", 100000],
actionName: "refund",
})

console.log(decision.effect)
console.log(decision.matched_rule)

This helps answer:

  • why was it blocked?
  • why did approval trigger?
  • which rule matched?
  • did resolvers return expected context?

CI & Test Debugging​

Explain APIs are ideal for failing CI tests.

try {
policy.assertEffect(input, "allow")
} catch {
policy.explain(input)
}

This makes regression failures easy to diagnose.


Production Rollout Safety​

During staged rollout, combine explain with shadow mode.

const decision = runtime.explainCall(handler, {
args: requestArgs,
actionName: "deploy",
})

Use this for:

  • new policies
  • policy migrations
  • governance changes
  • incident debugging

Resolver Debugging​

A major use case is validating resolver correctness.

Explain surfaces let you confirm:

  • actor identity fields
  • snapshot state
  • missing resolver values
  • incorrect field names
  • stale business state

This is often the fastest way to debug policy mismatches.


Common Debugging Questions​

Why was my function blocked?​

Use:

runtime.explainCall(fn, ...)

Check:

  • effect
  • matched_rule
  • actor fields
  • snapshot fields

Why didn’t approval trigger?​

Check whether:

  • action payload mapped correctly
  • schema field names match
  • snapshot state was present
  • resolver returned expected values

Why didn’t any rule match?​

Use explain output to inspect:

  • action type
  • missing fields
  • incorrect role names
  • wrong snapshot state

Best Practices​

Use explainCall() for function issues​

This gives the closest representation of production execution.


Use policy.explain() for tests​

Best when full input fixtures are already available.


Use explain before rollout​

Always validate:

  • approval rules
  • destructive actions
  • production deploy gates
  • tenant isolation rules

Production Mental Model​

Incoming call
-> Build exact context
-> Explain decision
-> Inspect matched rule
-> Fix rule or resolver

This is the fastest way to build confidence in policy behavior.


Next Steps​

  • Add Observability & Audit
  • Build Testing Policies
  • Use Actor Resolvers
  • Use Snapshot Resolvers