Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content
Concepts

The learning loop

How traces become lessons, lessons earn trust through outcomes, and the runtime maintains memory quality underneath.

Mubit's learning loop is what makes an agent better on run 50 than on run 1 without retraining the model. Raw experience goes in as traces, outcomes attach reward signals to the memories that produced them, reflection distills reusable lessons, and those lessons are injected into future queries — with a promotion ladder deciding how widely each lesson applies. Read this page to understand what each stage does and which parts run automatically.

Mental model: the loop is experience → attribution → distillation → injection → promotion. You drive the first three with API calls; injection and promotion happen at query time and in the background.

The five stages

  1. Ingest experience

    Your agent writes what happened — remember() for facts and observations, raw ingest for traces. Ingestion is asynchronous: an ingestion agent classifies each item into a typed entry (fact, trace, observation, …). If you need a write to be immediately recallable, poll the ingest job until done=true (see How Mubit works).

  2. Record outcomes

    When an attempt succeeds or fails, record_outcome() attaches the result to the memories that produced it. This is the reward signal everything downstream feeds on.

  3. Reflect

    reflect() distills the run's evidence into lessons — each with a lesson_type (success, failure, observation, rule, preference), a scope (run, session, global), an importance (low → critical), and conditions describing when it applies. A validation gate scores each fresh lesson: it becomes active once its evidence score crosses the acceptance threshold (default 0.6), is rejected at or below 0.25, and stays pending in between. An auto-reflection cadence can be enabled per instance so reflection fires after every N ingests or on a negative-outcome streak, without an explicit call.

  4. Lesson injection

    On later queries, relevant lessons ride along as a lesson_overlay — even across runs. The overlay is relevance-gated (embedding similarity between the query and stored lesson embeddings) and token-budgeted (default ~1,600 tokens; the first item is always admitted so one long critical lesson cannot starve the overlay). Rules always inject; lessons compete on relevance.

  5. Promotion

    Lessons that keep proving useful climb the scope ladder: run → session → global. Promotion to org-wide sharing is shadow-gated — a candidate lesson is trialled against a control group and only promoted when the outcome delta justifies it.

Outcomes close the loop

record_outcome() is the highest-leverage call in the loop — without it, reflection has only "what happened", never "what worked".

FieldMeaning
reference_id (required)The lesson or entry ID this outcome is about
outcome"success", "failure", "partial", "neutral"
signalNumeric reward in [-1.0, 1.0] — positive reinforces, negative penalizes
entry_idsAdditional entry IDs that contributed (multi-entry attribution). Each listed entry's reinforcement counters update; the primary reference_id is never double-counted
verified_in_productionMarks the outcome as observed in live production, not a test — the strongest trust signal (see Trust, confidence, and staleness)
rationaleFree-text why, kept for audit

For dense per-step signals inside a single run, use record_step_outcome() — see Step-level outcomes.

ℹ️Note

The outcome request also accepts an idempotency_key so a retried call is applied at most once. From SDK v0.12.0 the typed record_outcome() helpers forward it directly in all three languages (record_outcome(..., idempotency_key="...")); on earlier versions it is a wire-level field — send it directly over the transport (POST /v2/control/outcome).

What the runtime maintains for you

Alongside the loop you drive, hosted instances run always-on maintenance (each is per-instance configurable):

FeatureWhat it does
Write-time lesson reconciliationA re-learned near-duplicate lesson becomes a recurrence bump on the canonical entry instead of a new copy, so outcome history never splits across duplicates.
Bi-temporal supersessionWhen a belief is superseded, the old entry is excluded from current-state answers but kept for history (flagged is_stale, with superseded_by pointing at its replacement).
Sleep-time consolidationWhile a run is idle, near-duplicate guidance entries missed at write time are merged and clusters of entity facts are distilled into consolidated observations.
Workflow inductionRepeated successful traces of the same procedure are distilled into reusable workflow entries.
Guardrail distillationRepeated failure traces are distilled into preventive lessons with trigger preconditions.
Utility-weighted forgetting (opt-in)Aged episodic evidence that is never retrieved or reinforced is moved to an archive tier — reversible, and entries stay reachable by ID.

Nimbus example: the bad regex becomes a guardrail

Nimbus's support agent Ari ships a regex fix that takes down the export pipeline. The incident run contains the failure traces; closing the loop turns it into prevention:

# The fix failed in production — attribute the failure to the memories used.
client.record_outcome(
    session_id="support:incident-0142",
    reference_id=lesson_id,           # returned by an earlier reflect()
    outcome="failure",
    signal=-0.9,
    rationale="Regex change broke multi-line CSV rows in the export pipeline",
    verified_in_production=True,
    entry_ids=recalled_entry_ids,     # every entry that informed the fix
)
 
# Distill the incident into lessons.
lessons = client.reflect(session_id="support:incident-0142")

Reflection produces a failure lesson ("test regex changes against multi-line CSV fixtures before deploying") with conditions attached. Because similar failure traces recur, guardrail distillation reinforces it into a preventive lesson. Weeks later, when Ari recalls context for another regex change, the guardrail arrives via lesson_overlay — and this time Rex, the reviewer agent, blocks the deploy until the fixture test passes. When it holds up, a record_outcome(..., outcome="success", verified_in_production=True) strengthens the lesson toward global scope.

ℹ️Note

Configuration. The maintenance features are instance configuration, controlled by MUBIT_CL_* environment variables on the instance (e.g. MUBIT_CL_BITEMPORAL=0 to disable supersession, MUBIT_CL_FORGET=1 to opt in to forgetting, MUBIT_CL_OVERLAY_TOKEN_BUDGET to resize the lesson overlay). The lesson validation gate is likewise instance-level (MUBIT_CONTROL_LESSON_VALIDATION_ENABLED). On hosted instances the defaults above are already in effect.

Related