Skip to main content

Overview

Computed values let you define formulas on offer categories that are evaluated dynamically for each customer during a Decision Flow. This enables personalization like custom pricing, dynamic discounts, and tailored messaging.

How It Works

  1. Define computed fields on a category with a formula and output type
  2. Configure enrichment in a Decision Flow to load customer data from schema tables
  3. Add a compute stage to evaluate formulas per candidate offer
  4. Access results in the Recommend API response under the personalization field
  5. Verify in the studio — the Recommendation Preview on the decision-flow detail view now renders the computed personalization values inline under each offer card, so authors can confirm a formula produces the expected value before any API client is wired up

Formula Syntax

The formula engine supports the following features. Each example is shown in a code block so it copies cleanly into the editor. Arithmetic
Comparison
Ternary
Functions — pick the smaller or larger of two values.
Rounding — round a number to N decimal places.
Null handling — return the first non-null argument.
String concatenation — join string fragments.

Variable Namespaces

The customer.*, <entity>.*, behavior.*, and journey.* namespaces come from the canonical decision context, which the engine assembles automatically on every Recommend call — no Enrich node is required. An Enrich node only overrides or extends the assembled context.
The formula engine uses a tokenizer and recursive-descent parser — it does not use dynamic code execution. All formulas are safely interpreted from an AST.

Example

A “Personal Loan” category with a computed field:
When the Recommend API runs, KaireonAI calculates each loan offer’s personalized_rate using the customer’s enriched loyalty_score and the offer’s base_rate.

Personalization patterns

The compute node covers a broad set of personalization use cases. Each pattern below is a copy-pasteable formula plus the inputs it expects and the output it produces. All formulas in this section have been verified against the live formula engine — see platform/scripts/test-compute-personalization.mts for the executable proof.

Greetings and templated copy

Inputs: attributes.first_name (optional). Output (string): "Hi Anuraag, welcome back!" — falls back to "Hi there, welcome back!" when the attribute is missing. coalesce chains as many fallbacks as you need.
Mixes a request attribute with an enriched field — useful when the channel template needs a personalized salutation that includes the segment.

Tier-based numeric output (credit limit, discount)

Inputs: customer.tier, base_rate (custom field on the offer). For a Platinum customer with base_rate = 5000, returns 25000. For a Gold customer with the same base_rate, returns 10000.

Multi-band ladder (credit score → limit)

Nested ternaries form a clean if/else-if/else ladder. With a score of 820 the customer gets 50000; at 620 the safe-default 5000.

Risk-adjusted APR

For base_apr = 5.5 and a score of 820, the personalized APR is 6.10. At 650 it becomes 9.50. round(x, n) is the safe way to format money values — never returns more than n decimal places.

Ceiling clamp (program-cap underwriting)

Computes 30% of income, capped at the program ceiling of 100,000.Acustomerearning100,000. A customer earning 500,000 gets exactly 100,000;oneearning100,000; one earning 250,000 gets 75000.

Conditional CTA / region-specific disclosure

Returns one of two CTA strings depending on tier. Useful for personalizing channel templates without authoring duplicate creatives.
Compliance copy that switches on the request’s region attribute. The same Compute node can emit disclosure_text alongside the numeric output.

Cross-field arithmetic on the offer

For customer.balance = 8500, current_rate = 24.99, new_rate = 12.99, returns 1020 — the estimated annual interest savings the response can show under each card offer.

Loyalty waiver

Loyal customers (≥ 5 years) see the string "WAIVED"; newer customers see the raw annual_fee value. The output type can be text even though the else-branch returns a number — the Recommend response carries the value through unchanged.

Null and error handling

The engine is null-safe and crash-free:
  • Missing variable → result is null. customer.balance * 0.05 with no customer.balance returns null, not NaN.
  • Divide by zero → result is null. 100 / 0 returns null, not Infinity.
  • Write-time validation → the /api/v1/categories endpoint checks, via a Zod superRefine, that every computed field has a non-empty formula and an outputType of number or text, rejecting with a 400 before persisting. A formula that is present but syntactically invalid is not rejected at write time — it evaluates to null at decision time, so use the Validate button in the Category editor to catch syntax errors early.
The engine is also injection-safe — Function(...), eval(...), and process.env are not recognized identifiers, so any such expression evaluates to null and is logged as a parse error.

Next Steps

Formula Reference

Complete list of operators, functions, and variable namespaces.

Decision Flows

See how computed values are evaluated in the Compute stage.

Scoring Strategies

How the same candidates produce different rankings under each scoring method.