Skip to main content
A Decision Flow is the brain of KaireonAI. Every time you need to decide which offer to show a customer, a Decision Flow runs behind the scenes. It loads the eligible inventory, pulls in customer context, filters out anything that should not be shown, scores what remains using ML models, and returns a ranked list of personalized recommendations — all in under 200ms. Think of it as a pipeline with a clear contract: a customer walks in one end, and the best offers come out the other.
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.
Phase 1 (Narrow) --> Phase 2 (Score & Rank) --> Phase 3 (Output)
PhasePurposeNode Types
1 — NarrowLoad candidates, enrich with customer data, filter by rules and policiesinventory, match_creatives, enrich, qualify, contact_policy, filter, conditional, call_flow
2 — Score & RankScore each candidate, optimize across objectives, rank, group into placementsscore, optimize, rank, group
3 — OutputCompute personalized values and format the responsecompute, set_properties, response
Cross-phaseCan appear in any phasecall_flow, extension_point
For a full reference of all node types, phase rules, and configuration options, see the Composable Pipeline page.

Keyboard Shortcuts

ShortcutAction
Ctrl/Cmd + ZUndo last action
Ctrl/Cmd + Shift + ZRedo last undone action
Undo/redo buttons are also available in the editor toolbar.

Starbucks Example

A Starbucks rewards Decision Flow might work like this:
  1. Inventory — Load all 10 Starbucks offers with their 60 creatives
  2. Enrich — Look up this customer’s purchase history, reward tier, and visit frequency
  3. Qualify — Drop “Buy 5 Get 1 Free” for customers who already redeemed it this month
  4. Contact Policy — Suppress email offers for customers who received 3 emails this week
  5. Score — Run a Bayesian model to predict which offers this customer is most likely to engage with
  6. Rank — Sort by PRIE score, return the top 3

PRIE Arbitration Formula

The PRIE formula is KaireonAI’s multiplicative scoring model. It produces a single priority score from four dimensions:
Priority = P x R x I x E
The multiplicative structure means a zero in any dimension eliminates the candidate entirely. This prevents irrelevant high-value offers from surfacing and ensures all four dimensions must be satisfied.

The Four Factors

FactorNameRangeSourceSet By
PPropensity0—1ML model predictionScoring engine (per offer-customer pair)
RRelevance0—1Channel match, recency, segment overlapComputed automatically
IImpact0—1offer.businessValue (0—100, normalized)Business user (per offer)
EEmphasis0—2offer.priority (0—100, normalized, scaled)Marketer (per offer)
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

  1. 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.
  2. 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 Starbucks offers scored for the same customer, with flow-level weights P=0.4, R=0.2, I=0.2, E=0.2:
FactorBOGO FrappuccinoEarn 3x Stars
P (model score)0.850.60
R (context)0.700.90
I (businessValue=80)0.800.40
E (priority=70)0.700.90
PRIE score0.85 x 0.70 x 0.80 x 0.70 = 0.3330.60 x 0.90 x 0.40 x 0.90 = 0.194
BOGO Frappuccino 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 an arbitrationScores 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

PRIE is the only scoring method. The Score node always shows four weight sliders (P, R, I, E) — there is no scoring method dropdown.
SettingDescription
Model selectorChoose a model for the Propensity factor. Leave empty for priority-based scoring (P defaults to offer.priority / 100).
PRIE weight slidersAdjust relative importance of each factor. Must sum to 1.0.
OverridesScope-specific overrides for different models and weights.

Overrides

You can add overrides scoped to a specific offer, category, subcategory, or channel. Each override can specify a different model AND custom PRIE weights.
Override ScopeExample Use Case
OfferUse a specialized model for a high-value offer
CategoryDifferent PRIE weights for beverages vs. merchandise
SubcategoryBoost emphasis weight for seasonal items
ChannelLower propensity weight for email where model accuracy is lower

Channel Score Overrides

The Score node supports a channelOverrides array for entirely different scoring strategies per channel:
{
  "scoring": {
    "modelKey": "default-scorecard",
    "weights": { "P": 0.3, "R": 0.3, "I": 0.2, "E": 0.2 },
    "channelOverrides": [
      {
        "channelId": "channel_web",
        "method": "scorecard",
        "modelKey": "web-scorecard-v2",
        "weights": { "P": 0.4, "R": 0.2, "I": 0.2, "E": 0.2 }
      },
      {
        "channelId": "channel_mobile",
        "method": "bayesian",
        "modelKey": "mobile-bayesian-v1",
        "weights": { "P": 0.6, "R": 0.1, "I": 0.2, "E": 0.1 }
      }
    ]
  }
}
The resolveScoreConfig() function checks the candidate’s channel against the overrides array. First match wins; no match falls back to the default config.

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.
HookPhaseWhen It FiresUse Cases
pre_scoreBefore scoringAfter enrichment and filteringExternal API enrichment, last-minute filters, real-time features
score_overrideDuring scoringAfter built-in scorer runsReplace/adjust scores with an external model, champion-challenger
post_rankAfter rankingAfter ranking, before responseBudget caps, diversity constraints, portfolio guardrails
Each extension point can link to a sub-flow (a separate Decision Flow that runs inline):
{
  "type": "extension_point",
  "hookName": "pre_score",
  "configured": true,
  "subFlowId": "df_custom_enrichment"
}
Extension points are the recommended way to integrate external ML models for score adjustment. Use score_override to call your model and blend or replace the built-in score.

Arbitration Influencers

Arbitration 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

  1. Load interaction history — Query the customer’s all-time interaction summaries (up to 50 most recent), map each offer to its category
  2. Compute category affinityboost = (positiveRate - negativeRate) * 0.1, clamped to -0.1 to +0.1 (max 10% adjustment)
  3. Apply to scoresadjustedScore = score * (1 + categoryBoost)

Example

A customer has interacted with 3 Starbucks beverage offers: 2 positive, 0 negative.
positiveRate = 2/3 = 0.667, negativeRate = 0/3 = 0.000
boost = (0.667 - 0.000) * 0.1 = 0.067 (6.7%)
All other beverage offers for this customer get a 6.7% score boost.
SettingTypeDefaultDescription
arbitrationInfluencersEnabledbooleantrueEnable/disable category-based score adjustments
Disable influencers during initial deployment or A/B testing if you want a clean baseline without feedback effects.

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

  1. Deterministic assignment — Hash of customerId + date decides group membership. Same customer, same day, same group.
  2. Random scoring — Control group requests still run the full pipeline (enrichment, qualification, contact policies), but scores are randomized.
  3. Response flag — The response includes controlGroup: true | false for downstream analytics segmentation.
SettingTypeRangeDefaultDescription
controlGroupPercentinteger0—102Percentage of Recommend calls in the control group
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 priority only (simple ordering)
  • No enrichment, scoring, filtering, or contact policy evaluation occurs
  • Response includes "mode": "fallback" flag
The kill switch is for emergency use — for example, if a flow misconfiguration is causing production errors. It does not disable the Recommend API itself; it only simplifies ranking to a safe fallback.

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
New channels and placements are immediately functional without manual routing setup. Override any auto-created route by editing it in the Decision Flow configuration or the Channel detail page.
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

When autoAssembly is enabled (the default), the flow’s inventory updates automatically as your catalog changes. Creating a new offer, activating a creative, or adding a qualification rule triggers reassembly. Assembly triggers: Offers (created/activated/archived), Creatives (created/linked), Channels, Sub-categories, Qualification rules, 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

SettingDescription
decisionTraceEnabledMaster toggle (boolean)
decisionTraceSampleRatePercentage of requests that generate a trace (0—100)
Configure in Settings > General > Retention > Decision Trace.

What a Trace Captures

FieldAlwaysWith debug: true
totalCandidatesYesYes
afterQualificationYesYes
afterContactPolicyYesYes
topScoresYesYes
afterConsentYes
afterGuardrailsYes
qualificationReasonsYes (per-offer detail)
contactPolicyReasonsYes (per-offer detail)
Use 100% sample rate during development. In production, 1—5% keeps storage costs manageable while giving enough data to investigate issues.

Outbound Batch Decisioning

For outbound campaigns (email, direct mail), process an entire customer segment in one API call:
POST /api/v1/recommend/batch
{
  "decisionFlowKey": "spring-campaign",
  "segmentId": "seg_high_value",
  "channel": "email",
  "limit": 3,
  "outputFormat": "json"
}
FieldTypeRequiredDefaultDescription
decisionFlowKeystringYesDecision Flow to execute
segmentIdstringYesCustomer segment to process
channelstringNoFilter by channel type
limitintegerNo3Max offers per customer
outputFormatenumNo"json"json or csv
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), the Optimize node produces a single composite score:
finalScore = w_revenue * revenue + w_margin * margin + w_propensity * propensity
             + w_engagement * engagement + w_priority * priority
Weights are configured per optimization profile and must sum to 1.0. 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.
StageWhat HappensCandidates
InventoryLoad all 5 offers with creatives5
EnrichmentQuery customers table: credit_score=745, income=92000, region="northeast"5
Qualificationoffer-D fails income >= 100000 rule4
Contact Policyoffer-C (email-only) hits 3/week frequency cap3
ScoringScorecard model: offer-E=0.910, offer-A=0.820, offer-B=0.5433
RankingTop 2 by score2: [offer-E, offer-A]

Trace Output

{
  "traceSummary": {
    "totalCandidates": 5,
    "afterQualification": 4,
    "afterContactPolicy": 3,
    "topScores": [
      { "offerId": "offer-E", "score": 0.910 },
      { "offerId": "offer-A", "score": 0.820 }
    ]
  }
}

Field Reference

Create (POST /api/v1/decision-flows)

FieldTypeRequiredDefaultDescription
keystringYesUnique identifier (1—255 chars)
namestringYesHuman-readable name (1—255 chars)
descriptionstringNo""Optional description
statusenumNo"draft"draft, active, paused, archived
autoAssemblybooleanNotrueAuto-update when catalog changes

Update (PUT /api/v1/decision-flows)

FieldTypeRequiredDescription
idstringYesFlow ID to update
namestringNoUpdated name
descriptionstringNoUpdated description
statusenumNoUpdated status
autoAssemblybooleanNoUpdated auto-assembly
draftConfigobjectNoPipeline configuration (validated against schema)
rowVersionintegerNoOptimistic concurrency control

Delete (DELETE /api/v1/decision-flows?id=…)

Soft-deletes the flow (retains record with deletedAt timestamp). Response: { "success": true, "cascaded": 0 }.

API Quick Reference

POST /api/v1/decision-flows     # Create
GET  /api/v1/decision-flows     # List (paginated)
PUT  /api/v1/decision-flows     # Update (returns 409 on rowVersion mismatch)
DELETE /api/v1/decision-flows?id=df_abc123  # Soft-delete
For complete request/response schemas, see the Decision Flows API Reference.

Composable Pipeline

Build flows from 16 modular node types across 3 phases.

Algorithms & Models

Scoring engines, experiments, and portfolio optimization profiles.

Qualification Rules

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.