See also: Decision Flows REST API reference for request/response shapes, status codes, and error semantics.
Decision Flows are executed through the Recommend API. Pass a
decisionFlowId in the request body and the engine does the rest.How It Works
Decision Flows use a composable pipeline with 16 node types organized across 3 phases. You assemble a pipeline by choosing which nodes to include and configuring each through a visual canvas editor.Two structural rules the validator enforces at save time:
- The
optimizenode is deprecated — at runtime it passes scores through unchanged. Configure multi-objective weighting withstrategyProfileIdon the Score node instead. rankandgroupare mutually exclusive — a flow may contain aranknode or agroupnode, not both (RANK_AND_GROUP_CONFLICT). Userankfor single-placement top-N, orgroupfor multi-placement allocation.
priority_weighted, propensity, formula) plus channel/strategy overrides and the propensity score floor, see Scoring Strategies.
Keyboard Shortcuts
Undo/redo buttons are also available in the editor toolbar.
Lifecycle & publication — draft vs active vs published
A flow has astatus (draft, active, paused, archived) and a list of publishedVersions[]. The engine refuses to run a flow unless its status is active (or published) AND at least one published version exists. This is the publish-or-refuse gate — drift between “still building” and “live in production” is intentionally hard to cross by accident.
- Edits land on
draftConfig(live as you type). POST /api/v1/decision-flows/publishsnapshotsdraftConfigintopublishedVersions[]as a new versioned entry with optionalnotes.- The engine reads the latest entry of
publishedVersions[]— notdraftConfig— when resolving the route. Save without publishing → engine still serves the old version. paused,archived, anddraft(or any status with no published version) are refused. Recommend calls against them throwDecision flow "<key>" is not in a runnable state (status="...", publishedVersions=...), unlesspreviewDraftis set.
previewDraft: true in the engine context, which suspends the gate for that one call. This is studio-only — the public POST /api/v1/recommend endpoint never accepts the flag from the network.
The decision context (auto-assembled)
At the start of every Recommend call, the engine assembles one canonical, entity-namespaced decision context for the customer — automatically, before any node in the flow runs. Gates, compute formulas, and scoring predictors all read from this single flat record. Its namespaces:
Assembly is resilient: a broken join, a failed metric load, or a journey-state error never fails the decision — that piece is omitted with a logged warning and the pipeline continues.
Previewing the namespace:
GET /api/v1/decision-context/preview returns the full key catalog available for authoring — every customer.* column, each active join’s rollup keys (and its raw <entity>[] collection), every active behavior.* metric, the journey.* keys, and the documented attributes.* entries, each with its type and source. Pass ?flowKey= to apply a specific flow’s excludeJoinIds[] opt-outs. This is what the Decisioning Gates attribute picker autocompletes from.
Enrichment is automatic — the Enrich node is an override. You do not need an Enrich node for
customer.*, <entity>.*, behavior.*, or journey.* to be available. Add an Enrich node only to override or extend the assembled context: attach a schema that isn’t auto-joined, use a custom prefix / lookup key / field subset, or exclude specific joins. Enrich-node output wins over the auto-assembled context on key conflicts.id to EnrichNodeConfig.excludeJoinIds[]. The Enrich-node panel exposes this with an × button on each green auto-join chip — click it and the chip becomes struck-through, indicating that join is skipped for this flow only. Other flows are unaffected. Use this for flows that don’t need a specific join’s data (saves a request-time lookup), or where you want a manual Enrich source to fully replace an auto-join rather than just override its fields. The original behavior (zero exclusions) remains the default. When a flow has multiple Enrich nodes, their excludeJoinIds are unioned.
Implicit Contact Policy
The engine auto-applies all active Contact Policy rules (DNC, frequency caps, cooldowns, suppression windows) at the end of Phase 1, even when the flow has no explicitcontact_policy node wired in. This is intentional — Contact Policies are safety rails that protect against compliance breaches (e.g. forgetting to enforce a do-not-contact list). The opt-out is the flow-level skipContactPolicy: true flag, reserved for flows that must legitimately bypass these rails (transactional notifications, OTPs, system-of-record updates).
How the engine decides which path to take:
If you want a flow to run some policies (e.g. only DNC, skip frequency caps), add an explicit
contact_policy node with mode = "selected" and pick the specific contactPolicyIds[]. The implicit injection happens only when no explicit node is present.
Retail Rewards Example
A retail rewards Decision Flow might work like this:- Inventory — Load all 10 retail rewards offers with their 60 creatives
- Enrich — Look up this customer’s purchase history, reward tier, and visit frequency
- Qualify — Drop “Buy 5 Get 1 Free” for customers who already redeemed it this month
- Contact Policy — Suppress email offers for customers who received 3 emails this week
- Score — Run a Bayesian model to predict which offers this customer is most likely to engage with
- Rank — Sort by PRIE score, return the top 3
PRIE Ranking Formula
The PRIE formula is KaireonAI’s multiplicative scoring model. It produces a single priority score from four dimensions:The Four Factors
Impact vs. Emphasis: Impact (
businessValue) captures objective business value — how much is the offer worth if the customer converts. Emphasis (priority) is a subjective lever for marketers to boost or suppress offers based on campaign strategy. See Offers — Business Value for details.Two-Layer Architecture
- Flow-level weights — Configured on the Score node, these control how much each factor matters relative to the others. Weights must sum to 1.0. They are global tuning knobs for your decisioning strategy.
- Per-offer factor values — Each offer provides its own values for each dimension. These are the raw inputs that get weighted and multiplied together.
Worked Example
Two retail rewards offers scored for the same customer, with flow-level weightsP=0.4, R=0.2, I=0.2, E=0.2:
BOGO Iced Beverage wins despite lower relevance and emphasis, because its higher propensity and business value outweigh the other factors.
When
explain=true is passed to the Recommend API, each decision in the response includes a rankingScores object with the individual PRIE factor values (propensity, relevance, impact, emphasis) and the final composite score. This makes it easy to debug why one offer outranked another without needing to reconstruct the math manually.Score Node Configuration
The Score node supports three methods —priority_weighted, propensity, and formula. PRIE is the formula method — the multiplicative model described above — and it exposes four weight sliders (P, R, I, E). The other two are simpler strategies; see Scoring Strategies for when to use each.
Overrides
You can add overrides scoped to a composite offer_channel, category_channel, or subcategory_channel tuple, or to a single axis — offer, category, subcategory, or channel. Each override can specify a different model AND custom PRIE weights.Override priority
The default priority order isoffer_channel → category_channel → subcategory_channel → offer → category → subcategory → channel → default. Composite (two-axis) scopes rank above their single-axis components — a category_channel override beats a plain category override for candidates on the matching channel. The most-specific match wins; the resolver short-circuits on the first hit. Operators can customize via score.overridePriority: ["offer_channel", "category_channel", ..., "default"] — the order in the array is the order checked.
A matching override always wins over the node’s static
defaultModel / modelKey (and over a legacy channelOverrides entry). Previously the overrides ladder only ran when no defaultModel was configured; overrides now take precedence exactly as the priority chain documents.Channel Score Overrides
The Score node supports achannelOverrides array for entirely different scoring strategies per channel:
Extension Points
Extension Points let you inject custom logic at three critical moments in the pipeline without modifying the core flow. They appear as dashed-border placeholder nodes on the canvas and are no-op when unconfigured.
Each extension point can link to a sub-flow (a separate Decision Flow that runs inline):
Ranking Influencers
Ranking Influencers create a feedback loop between past customer outcomes and future scoring. When a customer has positive interactions with offers in a category, other offers in that same category receive a score boost. Negative outcomes lead to a demotion.How It Works
- Load interaction history — Query the customer’s all-time interaction summaries (up to 50 most recent), map each offer to its category
- Compute category affinity —
boost = (positiveRate - negativeRate) * 0.1, clamped to -0.1 to +0.1 (max 10% adjustment) - Apply to scores —
adjustedScore = score * (1 + categoryBoost)
Example
A customer has interacted with 3 retail rewards beverage offers: 2 positive, 0 negative.Control Groups
KaireonAI supports an always-on control group for measuring the true incremental lift of your Decision Flows. A configurable percentage of Recommend API calls receive randomized scores instead of model-driven scores, creating a baseline for lift measurement.How It Works
- Deterministic assignment — Hash of
customerId + datedecides group membership. Same customer, same day, same group. - Random scoring — Control group requests still run the full pipeline (enrichment, qualification, contact policies), but scores are randomized.
- Response flag — The response includes
controlGroup: true | falsefor downstream analytics segmentation.
A 2% default means roughly 2 out of every 100 calls get randomized scores — enough for statistically meaningful lift measurement without materially impacting business outcomes.
NBA Kill Switch
The NBA Kill Switch is a tenant-level safety control that instantly disables Decision Flow execution across your entire tenant. Setting:nbaEnabled (boolean, default true) in Settings > General.
When nbaEnabled = false:
- Recommend API bypasses all Decision Flow execution
- Offers are returned ranked by
priorityonly (simple ordering) - No enrichment, scoring, filtering, or contact policy evaluation occurs
- Response includes
"mode": "fallback"flag
Auto-Routing
KaireonAI reduces manual wiring by automatically creating FlowRoutes when you add channels and placements.- First flow created is automatically marked as the default
- New channel — FlowRoute created to the default flow
- New placement — FlowRoute created to the default flow
Auto-routing only creates routes to the default flow. To route a channel to a different flow, create the route manually or change the default flow first.
Auto-Assembly
WhenautoAssembly is enabled (the default), the flow’s inventory updates automatically as your catalog changes. Creating a new offer, activating a creative, or adding a decisioning gate triggers reassembly.
Assembly triggers: Offers (created/activated/archived), Creatives (created/linked), Channels, Sub-categories, Decisioning gates, Contact policies.
Each trigger is logged in the flow’s assemblyLog with a timestamp, source entity, and changes applied. Set autoAssembly: false for full manual control.
Decision Traces
Decision traces are forensic records that answer: “Why did customer X get Offer Y instead of Offer Z?”Configuration
Configure in Settings > General > Retention > Decision Trace.
What a Trace Captures
afterGuardrails is the real candidate count after the
guardrail stage
removes any hard-blocked candidates. It runs once per request at rank-node
entry (or the response node when a flow has no rank node), so ranking and the
result limit operate on the survivors. guardrailReasons[] lists each failed
guardrail evaluation as { ruleKey, ruleName, severity, passed, reason?, offerId? }.
Outbound Batch Decisioning
For outbound campaigns (email, direct mail), process an entire customer segment in one API call:
The response includes per-customer recommendations plus an aggregate summary with
avgOffersPerCustomer, topOffers, and categoryDistribution.
Batch decisioning runs the same pipeline as real-time Recommend — enrichment, qualification, contact policies, scoring, and ranking all apply. The only difference is iteration over a segment instead of a single customer.
Portfolio Optimization
When you need to balance competing business objectives (revenue vs. customer experience vs. margin), attach a ranking (strategy) profile to the Score node viastrategyProfileId — or a per-scope strategyOverrides[] entry keyed by category / productType / channel. The profile’s objective weights are mapped onto the PRIE factors (e.g. conversion → propensity, margin → impact), replacing the inline formula weights when set. For details on creating profiles, see Algorithms & Models.
Worked Example: Full Pipeline
Walk through a complete Recommend API call to see how each stage transforms the candidate list. Setup: 5 active offers (offer-A through offer-E), 1 Decision Flow, customer C-4821 with credit_score = 745, PRIE scoring with a scorecard model, ranking: topN, maxCandidates = 2.
Trace Output
Field Reference
Create (POST /api/v1/decision-flows)
Update (PUT /api/v1/decision-flows)
Delete (DELETE /api/v1/decision-flows?id=…)
Soft-deletes the flow (retains record withdeletedAt timestamp). Response: { "success": true, "cascaded": 0 }.
API Quick Reference
Related
Composable Pipeline
Build flows from 16 modular node types across 3 phases.
Algorithms & Models
Scoring engines, experiments, and portfolio optimization profiles.
Decisioning Gates
Define eligibility gates that control which offers reach each customer.
Contact Policies
Frequency caps, cooldowns, and suppression rules.
Computed Values
Formula syntax, supported functions, and variable namespaces.
Glossary
Definitions for Offer, Creative, Decision Flow, and other key terms.