Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.kaireonai.com/llms.txt

Use this file to discover all available pages before exploring further.

KaireonAI models follow the same deployment workflow as Pega CDH adaptive models — a candidate model starts in draft, runs in shadow mode against production traffic to validate its predictive power without affecting business decisions, gets promoted to challenger to take a slice of real traffic via the champion-challenger split, and finally replaces the active model as the new champion.

Lifecycle states

StateMeaningAffects /recommend?
draftCreated, not deployed. Training and inspection only.No
shadowScores in parallel with the active model on production traffic. Outputs are recorded in DecisionTrace.scoringResults[].shadowScores for offline evaluation.No — recorded only
challengerTakes a configured slice of traffic via ScoreNode.championChallenger (e.g., 20% of customers). Drives real recommendations for the assigned customers.Yes (for routed customers)
championThe active model. Drives every decision that isn’t routed to a challenger. At most one champion per (tenant, family).Yes (default for all customers)
archivedRetired. Preserved for audit but never scored.No

Allowed transitions

draft      → shadow, challenger, archived
shadow     → challenger, champion, archived, draft
challenger → champion, shadow, archived, draft
champion   → challenger, shadow, archived
archived   → draft
Illegal transitions return 400 Bad Request with code = "invalid_transition". Promoting a candidate to champion automatically demotes the prior champion in the same family to archived in the same database transaction.

POST /api/v1/algorithm-models//promote

Change a model’s lifecycle status. Wraps lib/ml/registry.promoteModel which enforces transition legality, the “one champion per family” invariant, the auto-rollback guard (W6.2), and writes an AuditLog entry.

Path parameters

ParameterTypeDescription
idstringModel UUID or unique key. Resolved via resolvePathId.

Request body

{
  "toStatus": "shadow",
  "family": "premium_card_v2",
  "metricsSnapshot": { "auc": 0.84, "errorRate": 0.02 },
  "bypassRollbackGuard": false
}
FieldTypeDescription
toStatus"draft" | "shadow" | "challenger" | "champion" | "archived"Target state. Required.
familystringGroup label — at most one champion per (tenantId, family). Defaults to the model’s name when omitted.
metricsSnapshotobjectMetrics at promotion time. When toStatus === "champion" and auc is present, the auto-rollback guard compares against the incumbent champion’s baseline AUC.
bypassRollbackGuardbooleanWhen true, the guard logs a warning but lets the promotion through. Default false.

Response 200

{
  "modelId": "alg_001",
  "previousStatus": "shadow",
  "newStatus": "champion",
  "demotedChampionId": "alg_old_champ"
}

Error codes

CodeReason
400Invalid toStatus or illegal transition (e.g., champion → draft).
403Insufficient role (requires editor or admin).
404Model not found.
409Auto-rollback guard tripped — pass bypassRollbackGuard: true to override.

GET /api/v1/algorithm-models/resolve-lifecycle

Returns the active champion + challengers + shadow models for the tenant, optionally scoped by family. The UI uses this to materialize a ScoreNode config in one click.

Query parameters

ParameterTypeDescription
familystringOptional. When set, scopes the lookup to one family.
championWeightnumber [1, 99]Weight assigned to the champion. The remainder (100 - championWeight) is split evenly across challengers. Default 80.

Response 200

{
  "championModelKey": "premium_card_v3",
  "championModelId": "alg_001",
  "challengers": [
    { "modelKey": "premium_card_v4_beta", "modelId": "alg_002", "weight": 20 }
  ],
  "shadowModelKeys": ["premium_card_v5_candidate"],
  "family": "premium_card",
  "warnings": []
}
warnings contains soft-validation messages — e.g., when more than one champion exists for a family (a hard invariant violation that promoteModel prevents going forward, but legacy data may still trip it).

Shadow scoring

When a ScoreNode config has shadowModelKeys set (or models with registryStatus = "shadow" are wired in via the UI’s “Apply lifecycle to flow” action), every shadow model also scores each candidate alongside the active model. Shadow scores are recorded in DecisionTrace.scoringResults[].shadowScores and never affect ranking, candidate.score, or business outcomes. This matches Pega CDH’s “shadow mode” pattern (academy.pega.com/topic/shadowing-adaptive-model) — a candidate model receives production traffic for evaluation purposes only; promotion to challenger or champion happens after the operator is satisfied with the candidate’s performance.

Trace shape

{
  "scoringResults": [
    {
      "rank": 1,
      "score": 0.953,
      "offerId": "off_001",
      "modelType": "scorecard",
      "shadowScores": {
        "premium_card_v5_candidate": { "score": 0.964, "engineType": "scorecard" }
      }
    }
  ],
  "experimentAssignment": { "variant": "premium_card_v3" }
}
experimentAssignment.variant records which model actually drove the decision (champion or one of the challengers). shadowScores records what the shadow models would have scored — useful for offline AUC comparison before promotion.

Untrained model behavior

For Bayesian and logistic-regression model types, the propensity for every (action, customer) pair starts at 0.5 (a coin flip) until the model has accumulated enough labelled outcomes to differentiate. This matches Pega’s adaptive-model behavior — academy.pega.com/topic/adaptive-model-outputs notes that “the propensity for every action starts at 0.5 or 50% (the same as a flip of a coin) because in the beginning, the model has no response behavior on which to base its predictions.” Kaireon tracks evidence per-offer in AlgorithmModel.modelState.interactionCounts and applies hierarchical fallback (offer → category → channel → global priors) via ModelAdaptation rows once the evidence threshold is met. Until then the 0.5 prior is intentional, not a bug.

Roles

admin, editor for promote / resolve-lifecycle. viewer is allowed for resolve-lifecycle (read-only).