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