Policies and actions

How policy rules with AND conditions are written and evaluated, and how the action and action_reason of every response are computed — policy, other option, low confidence, default or engine error.

Questions produce answers; policies turn answers into an action your code can switch on. Every successful response carries both the action and the action_reason that explains it.

Actions

ActionMeaning by convention
continueProceed with the automated path.
blockStop: reject, drop or quarantine the event.
escalateHand over to a person or a higher tier.
fallbackTake your fallback path — for example a larger model or more retrieval.

Actions are labels for your code. Dcision never blocks or reroutes anything by itself: a decision whose action is block still answers 200 OK, and your application applies the action.

Policy rules

A rule is one condition, optional and conditions, and the action to return when all of them hold:

{ "field": "route", "on": "output", "operator": "eq", "value": "spam", "action": "block" }
PropertyTypeDefaultDescription
fieldstring—The key of a question — or of a composite — in this decision.
onstringoutputWhat to compare: the answer (output), its confidence, or the weighted level of a score question (score).
operatorstring—eq, neq, gt, gte, lt or lte.
valuestring or number—The value to compare with (strings up to 255 characters).
andarray—Up to 5 more conditions — each with its own field, on, operator and value — that must also hold.
actionstring—continue, block, escalate or fallback.

A decision has up to 50 rules. What value and operator accept depends on the field and on on:

FieldonComparesvalueOperators
choice questionoutputthe chosen option (case and surrounding spaces ignored)an option, as a stringeq, neq
score questionoutputthe most likely level (1 = lowest)a level number or a level labelall six
score questionscorethe weighted level, from 1 — it can fall between levels, such as 2.4a numberall six
probability questionoutputthe probability of yesa number from 0 to 1all six
any questionconfidencethe answer's confidencea number from 0 to 1all six
compositeoutputthe composite's valuea numberall six

Rules that break these constraints make the schema invalid (422 INVALID_SCHEMA), for example "Choice outputs only support eq / neq.", "Unknown question \"intent\".", "Only score questions have a weighted level." or "Compare a composite's value with a number.".

AND conditions

Compound rules are what most patterns need. Every condition of a rule must hold for the rule to match. From the templates:

TemplateRule
ticket-triagecategory = bug_report AND bug_severity ≥ 4 → escalate
voice-bankingintent = approve_transfer AND confidence of intent < 0.9 → escalate
customer-service-routerintent = technical_issue AND weighted level of complexity ≥ 2.5 → escalate
resume-screeningsenior_ic < 0.35 AND eng_manager < 0.35 → block

As JSON, the first one reads:

{
  "field": "category",
  "on": "output",
  "operator": "eq",
  "value": "bug_report",
  "and": [{ "field": "bug_severity", "on": "output", "operator": "gte", "value": 4 }],
  "action": "escalate"
}

Conditions of one rule can use different questions and composites, or the same question twice — its answer and its confidence, as in voice-banking. For OR, write two rules with the same action.

How the action is computed

After the engine answers, Dcision computes the composites, then walks four steps and stops at the first that applies:

Policies, in order. The first rule whose conditions all hold sets the action. action_reason → { "type": "policy", "rule": 1 } — rule is the 0-based index of the rule (the app shows it as "Policy rule #2").

A choice answered other. The first choice question, in question order, whose answer is the reserved other option triggers the decision's fallback action (settings.fallbackAction, escalate by default). action_reason → { "type": "other_option", "question": "route" }

Low confidence. The first question, in question order, whose confidence is below its minConfidence triggers the fallback action. action_reason → { "type": "low_confidence", "question": "route", "confidence": 0.52, "minConfidence": 0.8 }

Default. Nothing applied: the action is continue. action_reason → { "type": "default" }

Policies always win: a rule such as route eq other → block takes precedence over the fallback action.

A fifth reason exists outside these steps. When the engine fails and the decision's onEngineError is fallback, there are no answers to evaluate: the response carries the fallback action and { "type": "engine_error", "code": "ENGINE_TIMEOUT" }.

Worked example

The Lead Qualification template has two rules and the default fallback action, escalate:

[
  { "field": "route", "on": "output", "operator": "eq", "value": "spam", "action": "block" },
  { "field": "purchase_intent", "on": "confidence", "operator": "lt", "value": 0.6, "action": "escalate" }
]
resultconfidence.purchase_intentactionaction_reason
route: "sales", purchase_intent: 0.94120.8824continue{ "type": "default" }
route: "spam", purchase_intent: 0.030.94block{ "type": "policy", "rule": 0 }
route: "sdr", purchase_intent: 0.450.1escalate{ "type": "policy", "rule": 1 }
route: "other", purchase_intent: 0.150.7escalate{ "type": "other_option", "question": "route" }

The confidence of a probability is |2p − 1|, so rule 1 escalates every lead whose purchase_intent falls between 0.2 and 0.8.

In the editor

The Policies card reads each rule as IF condition THEN action:

  1. Add rule creates a rule on the first question.
  2. Pick the field — questions, then composites — and what to compare: answer, confidence or, for a score question, weighted level. Then the operator and the value.
  3. + AND adds a condition, up to 5. Each one has its own field, comparison, operator and value.
  4. Pick the action after THEN.

Rules are evaluated top to bottom. Renaming or deleting a question updates or removes the rules that start with it; and conditions and composite terms that point at a question that no longer exists are flagged as issues to fix.

Acting on the result

switch (decision.action) {
  case "continue":
    return routeTo(decision.result.route);
  case "block":
    return discard(lead);
  case "escalate":
    return sendToHuman(lead, decision.action_reason);
  case "fallback":
    return askLargerModel(lead);
}

Engine errors: an error or an action — you choose

By default, when the engine times out or fails the API returns an error such as 504 ENGINE_TIMEOUT and no action: decide in your code what an error means — usually the same path as escalate. Set onEngineError to fallback to get a 200 with the fallback action and action_reason.type = "engine_error" instead; those answers aren't billed. See Decision settings and Errors.

Tips

  • Put the most specific rules first: the first match wins. Compound (and) rules usually come before the simple ones they refine.
  • Use on: "confidence" with lt to escalate answers the engine isn't sure about — or set minConfidence on the question to use the fallback action instead. Combine both for per-action thresholds.
  • Use on: "score" to act between levels — frustration ≥ 3.5 — instead of waiting for the top level to win.
  • Keep block for clear-cut outputs (spam, abuse) and let uncertainty escalate.
  • Policies are part of the schema: a change takes effect for API clients only when you deploy a new version.

On this page