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

Guardrails from failures

An agent that merely logs its failures repeats them; an agent whose failures become preventive memory doesn't. This pattern turns each failure into something that changes future behavior — a rule that always injects, a confidence penalty on the memories that misled, or a distilled guardrail lesson with trigger conditions. Use it whenever a class of failure is expensive enough that "we'll notice next time" isn't good enough.

How it works

Failures harden into guardrails at three tiers, from fully manual to fully automatic:

TierYou doMemory gets
Explicit ruleWrite the invariant yourselfA rule entry — always injected, exempt from relevance competition
Attributed failurerecord_outcome(outcome="failure") on the entries that misledConfidence penalties that demote bad guidance in ranking
Automatic distillationNothing — instance featureRepeated failure-credited traces distilled into guardrail lessons with trigger preconditions

Tier 1 — explicit. When you already know the invariant, don't wait for the system to learn it. A rule entry is a hard constraint: context assembly injects it in the always-on Active Rules section (see context priority), it never has to win a relevance contest, and it is authored — never produced or promoted by the automatic loop.

client.remember(
    session_id="nimbus:ari:support",
    content="Never deploy a regex change to the export pipeline without a green run "
            "of the multi-line CSV fixture suite.",
    intent="rule",
)

Tier 2 — attributed. When a task fails, penalize the memories that led it there. record_outcome(outcome="failure", signal=-0.8, entry_ids=[...]) drops each entry's knowledge_confidence, so the same misleading guidance stops outranking better candidates. This is the negative half of the outcome attribution loop.

Tier 3 — automatic. Hosted instances run guardrail distillation as an always-on maintenance feature (per-instance configurable): when similar failure-credited traces recur, they are distilled into a preventive lesson with trigger preconditions — "before doing X under condition Y, check Z" — that competes into the lesson overlay of future queries. You feed it simply by doing tier 2 consistently.

diagnose(): have I hit this error before?

Guardrails also need a read path at the moment of failure. diagnose() takes the error your agent just hit and retrieves the failure lessons that match it — returning failure_lessons (scored evidence items), a summary, and total_failure_lessons. Call it in your error handler, before the retry:

hits = client.diagnose(
    session_id="nimbus:ari:ticket-2107",
    error_text="Export worker crashed: catastrophic regex backtracking on multi-line row",
    error_type="RegexTimeout",       # optional coarse class
    limit=5,
)
print(hits["summary"])
for lesson in hits["failure_lessons"]:
    print(lesson["content"])

Walkthrough: the bad regex becomes a guardrail

Ari ships a regex "fix" that takes down Nimbus's export pipeline. Here is the incident becoming prevention, tier by tier:

# Tier 2 — the incident run attributes the failure to the memories used.
client.record_outcome(
    session_id="nimbus:incident-0142",
    reference_id=misleading_lesson_id,        # the lesson that suggested the quick fix
    outcome="failure",
    signal=-0.9,
    entry_ids=recalled_entry_ids,             # everything that informed the change
    verified_in_production=True,              # it failed in prod — that is a verdict too
    rationale="Regex change broke multi-line CSV rows in the export pipeline",
)
 
# Reflection distills the incident into a failure lesson with conditions.
client.reflect(session_id="nimbus:incident-0142")
 
# Tier 1 — the postmortem writes the invariant down as a hard rule.
client.remember(
    session_id="nimbus:ari:support",
    content="Never deploy a regex change to the export pipeline without a green run "
            "of the multi-line CSV fixture suite.",
    intent="rule",
)

Tier 3 does the rest: because export-regex failures have now recurred, guardrail distillation reinforces the pattern into a preventive lesson with its trigger precondition attached.

Weeks later, Ari attempts another regex change. The rule arrives unconditionally in Active Rules; the guardrail lesson arrives via the lesson overlay because the query matches its conditions; and when the deploy still throws, diagnose(error_text=...) surfaces the incident lesson at error time — so Rex, the reviewer agent, blocks the deploy until the fixture suite passes. When the guarded attempt succeeds, record_outcome(..., outcome="success", verified_in_production=True) strengthens the guardrail instead of the shortcut.

ℹ️Note

verified_in_production=True applies to failures as much as successes — "this guidance demonstrably failed in prod" is exactly the trust signal that should demote it hardest. See Trust, confidence, and staleness.

When not to use it

  • Transient faults — a network blip or a 503 is not a lesson; handle it with plain retries and backoff. Persisting one-off noise as failure memory dilutes the guardrails that matter. (For behavioral pathologies like retry loops, see Loop safety.)
  • Failures with no recurring shape — distillation and diagnose() both work off similarity; a truly unique failure is better captured as a plain observation.
  • Secrets in error texterror_text is stored and retrieved like any memory. Scrub tokens and customer data before recording.

Related

ℹ️Note

Configuration. Guardrail distillation is instance configuration — MUBIT_CL_GUARDRAIL_DISTILL on the instance, enabled by default on hosted instances alongside the other maintenance features listed in The learning loop.