Skip to main content
[AVAILABLE]. packages/policy, 72 tests. CLAIMS.md 2.2/2.3.

Purpose

Evaluates a PolicySignals object against a Policy’s ordered rules and returns exactly one Decision. See Policies and the decision for the concept, this page is the export reference.
PolicyEngine.evaluate() alone does not check Policy.boundSignals — that binding is enforced one layer up, by SignalIntentBinder, which RuntimeEngine (@parmana/runtime) invokes immediately before calling PolicyEngine.evaluate(). Calling PolicyEngine.evaluate() directly, as the minimal example below does, bypasses signal/intent binding entirely — verified by actually running it. See Policies and the decision for why this split exists.

Install

Not published to npm. This is an internal package of this repository, used from a clone of it: npm ci at the repository root links every workspace package. The packages published to npm are @parmana/sdk, @parmana/connector-sdk and @parmana/sign.

Key exports

Engine, [AVAILABLE]

Routing and loading, [AVAILABLE]

Validation, [AVAILABLE]

boundSignals coverage is fail-closed, not advisory. A rule can decide on a fact (e.g. amount) that isn’t declared in boundSignals, silently forfeiting SignalIntentBinder’s protection for that fact. PolicyValidator.validate() throws PolicyValidationError for any such fact unless it’s explicitly acknowledged in unboundSignalReasons with a reason. A fact with no genuine Intent-side equivalent (vendorVerified, riskScore) still doesn’t belong in boundSignals; it belongs in unboundSignalReasons instead, with a reason.
Every approve rule needs a signed human approval. PolicyValidator.validate() also throws PolicyValidationError (approves without a signed human approval) for any approve rule that does not require a fact declared in approvalSignals with is_true, as its whole condition or directly inside its top level all. No AI agent action is authorized without a signed human approval, reads included. See Human approval.

Types

Policy (including its optional boundSignals: Record<string, string> and unboundSignalReasons: Record<string, string> fields — see the note below), PolicyRule, PolicyCondition, PolicyRuleOutcome, PolicyInput, PolicySignals, PolicyDecision, PolicyAction (enum: APPROVE, REJECT), PolicyOutcome (enum: APPROVE, REJECT), SignalIntentBindingViolation ({ signalKey, intentPath, signalValue, intentValue }).
Both enums previously also had a third value, REQUIRE_OVERRIDE: defined but never used by any real policy, and DecisionBuilder collapsed it to the same DecisionOutcome.REJECTED as an ordinary REJECT in any case. Removed as dead code.

Minimal example

Full runnable version: Write your first policy.

Next

Write your first policy

Write a policy and confirm both the approve and reject paths.

@parmana/runtime

Where PolicyEngine is actually invoked as part of executing a transaction.