causal-memory

USE CASE

Causal memory for an on-call agent

An incident timeline records what happened. Causal memory records which mitigation actually prevented the worse outcome — and which one only looked like it did.

Updated · English

Who this is for

For teams using an agent to triage alerts, draft postmortems or suggest mitigations, where the same incident class returns every few weeks.

The failure mode it fixes

These are not hypothetical; each one is a direct consequence of storing text instead of causal structure.

  • The timeline is not the lesson

    Postmortems list events in order, but the useful part is causal: this change caused the latency, that rollback prevented a full outage, this other mitigation did nothing. An agent reading a timeline has to re-infer causality from prose under time pressure.

  • Root cause and blast-radius limiter get confused

    The fix that removes the cause and the action that stops the bleeding are different things. Treating the limiter as the fix leads to the incident returning; treating the fix as urgent leads to a risky change during an outage. CausalEval separates them as C4 inhibition.

  • The obvious mitigation is the one that failed before

    Restart the pod, fail over the primary, flush the cache. Each has a history, and some of those histories include making things worse. An agent without that history will suggest the same action with the same confidence.

  • Lessons expire silently

    A workaround from six months ago may now be harmful because the architecture changed. Memory that cannot be superseded becomes a source of confident bad advice.

How causal memory is used

The loop is always the same three fields — decision, context, outcome — plus one rule: record after the outcome, not before.

Record both directions of causality

During and after an incident, record two kinds of edge: what caused the failure, and what prevented it from being worse. The second one is the part most tools drop. A prevented edge carries negative activation, so the mitigation that worked ranks as a thing to repeat, while the one that was tried and did nothing does not get promoted.

  • relation: prevented for the rollback, the rate limit, the feature flag that contained the blast radius.
  • relation: caused for the change or condition that started it.
  • task_tag: the incident class (database, deploy, dependency), not the incident ID — recall works across incidents of the same class.

Trace cause before proposing a fix

Start from the symptom and walk backwards. trace_cause gives a single hop; trace_cause_chain follows multiple hops to the root. The point is to stop the agent from treating the loudest downstream error as the cause.

  • Feed the observed symptom, not your hypothesis — a hypothesis-shaped query returns evidence for the hypothesis.
  • Use max_depth 3 by default; deeper chains are usually a sign the graph needs better edges, not a deeper query.
  • Compare the returned chain with the incident timeline; disagreement is a signal that an edge is missing.

Check the mitigation against history

Before suggesting a mitigation, ask what happened last time an action like this was taken. If the answer includes a DANGER chain, the agent should say so explicitly and cite the incident, instead of presenting the action as routine.

  • This is a pre-action check, so it runs before the suggestion reaches a human.
  • A warning is evidence, not a veto: during an outage a known-risky action can still be correct.
  • The citation is what makes the warning reviewable after the fact.

Supersede workarounds when the system changes

When a workaround stops being safe, supersede it. The old edge remains for counterfactuals ('what would have happened if we had not failed over?'), but the answer model sees the correction. This is the difference between a memory that ages and one that rots.

  • Review superseded edges after every architecture change.
  • A superseded edge is not a wrong memory; it is a dated one, and the date is the point.

What the calls look like

The same JSON shape works over stdio MCP, the HTTP transport and the DSH plugin.

1 · Record the mitigation that actually prevented the worse outcomejson
{
  "name": "record_decision",
  "arguments": {
    "decision": "rolled back the checkout service to the previous image during the latency spike",
    "outcome": "error budget stopped draining; the database stayed below its connection ceiling",
    "relation": "prevented",
    "task_tag": "database",
    "context": "peak traffic, primary at connection limit, rollback available"
  }
}
2 · Trace the symptom back to a causejson
{
  "name": "trace_cause_chain",
  "arguments": {
    "outcome_description": "checkout p99 latency rose until the primary hit its connection ceiling",
    "max_depth": 3,
    "min_confidence": 0.5,
    "limit": 5
  }
}
3 · Check the obvious mitigation against historyjson
{
  "name": "intervention_query",
  "arguments": {
    "action": "fail over the primary database during peak traffic",
    "task_tag": "database",
    "max_depth": 3
  }
}

What to watch over three months

Track these on your own data. The published numbers are benchmark baselines, not a promise about your repository or your incidents.

Metrics to watch after adopting causal memory
MetricReferenceHow to read it
Repeat incident rateTrack per classShare of incidents whose task_tag matches an earlier incident in the same quarter. This is the number causal memory is supposed to move.
Inhibition accuracy80% vs 50%CausalEval C4: distinguishing a root-cause fix from a blast-radius limiter, against the mem0 baseline on the 70-question protocol.
Intervention accuracy75% vs 40%CausalEval C2: forward prediction of what a repeated action would do. This is the capability behind the pre-mitigation warning.
Postmortem completenessTrack per incidentWhether the postmortem records a prevented edge, not just a timeline. Incidents without one are the ones that will be re-learned.
MTTRTrack, no published numberWe do not publish an MTTR improvement. Measure first-response time and time-to-mitigation before and after adoption on your own incidents.

Benchmark figures come from the causal-memory README and CausalEval v13; see the CausalEval page for protocol and limitations.

On-call agent questions

Does this replace an incident timeline or a postmortem tool?
No. It stores the causal claims that a timeline leaves implicit: this caused that, this prevented worse, this did nothing. Keep the timeline; add edges for the parts a future agent needs to reason with.
How is a prevented edge different from a note saying 'this worked'?
It is typed and it spreads negative activation. At retrieval time, the prevented outcome ranks below neutral, which is what lets intervention_query return a warning instead of a neutral list. A prose note has no ranking effect.
Can the agent use this during an active incident?
Yes — recall and intervention queries are local SQLite reads by default, so they do not depend on an external service. Recording is safe to do during the incident; waiting until the postmortem loses the context.
What about incidents the agent did not handle?
Backfill the edges after the postmortem. The value is in the graph, not in whether the agent was present. A backfilled prevented edge warns exactly like a live one.
Is the incident data safe?
By default it stays in the local causal.db file, which means the same access controls as the machine running it. The hosted option isolates data per tenant; review what your incident data policy allows before sending it to any hosted service.

Run it on one real decision

Record a decision you already made, add the outcome when you know it, and ask for it back a week later. That single loop is the whole evaluation.