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.

What it does

When a multi-turn negotiation session reaches status: "accepted", its finalProposal represents the agreed terms (discount, term, bundle, final price). Apply-mode promotes that proposal into the realtime /api/v1/recommend response so downstream callers see the negotiated terms alongside the next-best-action ranking. Each ranked decision is decorated with one of:
  • appliedNegotiation: { sessionId, proposal } — every gate passed; the caller can present the negotiated terms.
  • appliedNegotiationReject: { sessionId, reason } — a session existed but a gate blocked the apply (e.g., daily cap exceeded, regulator review still required, kill switch tripped).
When no session exists for a given (tenant, customer, offer), the decision is returned unchanged.

Configuration

{
  "aiAnalyzerSettings": {
    "negotiation": {
      "applyModeEnabled": true,
      "regulatorReviewCleared": true,
      "dailyApplyCap": 50,
      "killSwitchTenant": false,
      "killSwitchGlobal": false,
      "recentValidationFailureRate": 0.0,
      "autoKillThreshold": 0.2
    }
  }
}
FieldDefaultMeaning
applyModeEnabledfalseMaster flag. When off, the wire short-circuits with zero I/O — no latency cost for non-opt-in tenants.
regulatorReviewClearedfalseOnly flip to true after the 30-day eval-harness run shows zero violations across the negotiation eval set. Without this flag every apply rejects with regulator_review_required.
dailyApplyCap50Hard cap on auto-applies per tenant per day (UTC).
killSwitchTenantfalsePer-tenant emergency stop. Trips immediately when set to true.
killSwitchGlobalfalseOrg-wide emergency stop, set centrally.
recentValidationFailureRate0Rolling 0..1 ratio. When ≥ autoKillThreshold the gate auto-trips.
autoKillThreshold0.2Threshold for the auto-trip above.

Response shape

{
  "decisions": [
    {
      "offerId": "off_premium_savings",
      "rank": 1,
      "score": 0.84,
      "appliedNegotiation": {
        "sessionId": "sess_5f0a…",
        "proposal": {
          "rationale": "loyal customer, 24mo tenure",
          "discountPct": 12,
          "termMonths": 12,
          "finalPriceCents": 8800,
          "currency": "USD"
        }
      }
    },
    {
      "offerId": "off_basic",
      "rank": 2,
      "score": 0.73,
      "appliedNegotiationReject": {
        "sessionId": "sess_a1b2…",
        "reason": "apply_budget_exceeded"
      }
    }
  ],
  "meta": {
    "negotiationApply": { "applied": 1, "rejected": 1 }
  }
}
meta.negotiationApply is omitted when the wire is in noOp (flag off or no relevant sessions found).

Reject reasons

reasonWhen
apply_mode_disabledThe flag is off (rare — short-circuits earlier; surfaces only in audit rows).
offer_not_negotiableOffer.negotiable !== true.
kill_switch_trippedOne of the three kill switches fired. The audit row’s changes.reject.source says which: tenant, global, or auto_error_rate.
regulator_review_requiredregulatorReviewCleared is false.
apply_budget_exceededToday’s apply count ≥ dailyApplyCap.
guardrail_violationsThe session’s finalProposal re-validation failed. The audit row carries the violation list.
guardrails_missingOffer is negotiable=true but has no negotiationGuardrails configured — fail-CLOSED.

Audit trail

Every apply and every reject writes one AuditLog row with:
  • action: "negotiate_apply_realtime" (apply) or "negotiate_apply_realtime_reject" (reject).
  • entityType: "negotiation_session", entityId: the session id.
  • changes: { sessionId, applied, proposal | reject }.
The route also runs appliesUsedToday from a count of these rows, so the audit chain is the source of truth for daily-cap accounting.

Failure modes — fail-CLOSED

ConditionBehavior
tenantSettings lookup throwsWire stays OFF; warn-level log surfaces the lookup failure; recommend response unchanged.
Offer / session lookup throwsWire degrades to noOp; warn-level log surfaces it; recommend response unchanged.
AuditLog.count throwsappliesUsedToday returns Number.MAX_SAFE_INTEGER so the daily-cap gate trips and every apply rejects with apply_budget_exceeded. Cap fails-CLOSED — an outage cannot silently lift the limit. Surfaces at error severity.
Apply-row AuditLog.create throwsLogged at error (compliance teeth) — the apply decoration is still returned to the caller, but the absence of the audit row is escalated for reconciliation.
Reject-row AuditLog.create throwsLogged at warn — informational.
Wire helper throwsThe route’s try/catch returns the recommend response without decoration; the apply-mode failure never breaks ranking.

Honest limits

  1. Concurrency under-counting. appliesUsedToday is read-once + per-call increment in memory; the audit row is written fire-and-forget. Two simultaneous /recommend calls for the same (tenant, day) can both read N and both apply up to cap, so the day total can exceed cap by (concurrency - 1) * applies_per_call before audit rows materialize. Acceptable for V1 because (a) the apply decoration is informational — no irreversible side effect — and (b) compliance retains the AuditLog rows for retroactive reconciliation. A Redis INCR with a TTL keyed negotiation:applies:{tenantId}:{YYYY-MM-DD} is on the roadmap and closes the gap.
  2. appliesUsedToday cost. AuditLog.count is correct but slow under very high tenant volume. Same Redis follow-up addresses both this and #1.
  3. Placements path not wired. The multi-placement /recommend response shape is decorated separately. Today the apply-mode wire only runs on the single-flow + auto-resolve paths. Wiring placements is a small follow-up.

Operational checklist

  • Enable applyModeEnabled for one tenant first. Watch the meta.negotiationApply counter on /recommend responses and the AuditLog rows.
  • Run the negotiation eval harness for 30 nights. When zeroViolationClearance >= 0.95 for the full window, flip regulatorReviewCleared to true.
  • A regression in any of: solverFailed > 0 on the realtime arbitration log line, sustained kill_switch_tripped: { source: "auto_error_rate" } rejects, or AuditLog write failures at error severity → flip applyModeEnabled to false immediately. The wire is designed so flag-off is bit-identical to the pre-W15 response.
See also: Negotiation eval harness · Decision flows