cachly← All posts
Technical Deep Dive · May 9, 2026

The Causal Knowledge Graph: how cachly learns from cause-and-effect

Most AI memory systems store facts. cachly stores causation — what led to what, with confidence scores.

The difference between facts and causes

Fact

“Use 127.0.0.1 instead of localhost in the ClickHouse healthcheck.”

Tells you what to do. Not when, not why.

Cause (CKG)

Using localhost causes restart loops when IPv6 is disabled, because localhost resolves to ::1 which ClickHouse isn't bound to.

Tells you why — and exactly when this fix applies.

The distinction matters most at the moment you are least able to think clearly: something is broken, and a tool is offering you a suggestion. A fact gives you a thing to try. A cause gives you a condition to check first. If IPv6 is enabled on this host, the ClickHouse fix above is simply irrelevant, and applying it anyway costs you the next twenty minutes chasing a change that could never have helped.

What one causal edge actually contains

Every call to learn_from_attempts() creates or strengthens a causal edge:

learn_from_attempts(
  topic       = "fix:clickhouse-healthcheck",
  outcome     = "success",
  what_worked = "Use 127.0.0.1 not localhost",
  what_failed = "localhost → ::1 on IPv6-disabled servers",
  severity    = "critical",
  tags        = ["docker", "clickhouse", "ipv6"],
)
CONDITIONIPv6 disabledMECHANISMlocalhost → ::1SYMPTOMrestart loopACTIONuse 127.0.0.1viaproducesfixed_byOne edge, four parts — and a confidence score that moves with evidence.confidence 0.94 · n=7
The edge that call produces. The condition is the part a plain fact throws away — and it is the part that decides whether the fix applies to the machine in front of you.

Four parts, and none of them is optional.

Drop the condition and you have advice that fires everywhere, including on the machines where it cannot possibly apply. Drop the mechanism and nobody can tell whether a similar-looking failure is actually the same failure.

Drop the observation count and every claim carries the same weight, whether it was seen once or seven times. That last one is the quiet killer, because a store without counts still looks authoritative.

Bayesian confidence updates

Each edge has a confidence score that updates with each observation:

  • outcome: success → confidence increases toward 1.0
  • outcome: failure (same approach) → confidence decreases
  • outcome: partial → small upward adjustment
  • severity: critical → observations weighted more heavily
0.000.250.500.751.00one contradicting failuresilenceobservations over time →Evidence moves the score in both directions. Nothing pins it at 1.0.
A confidence score is a running argument, not a verdict. The dashed tail is the part most memory systems get wrong: a lesson nobody has needed in weeks is not thereby proven — it is unexamined.

A fix seen 10 times with outcome: success has near-certainty. A fix tried once with outcome: partial stays marked uncertain. The Brain gets better with use.

Reading a confidence score honestly

Two numbers travel together, and the smaller one is usually the more useful: the score, and the observation count it rests on. An edge at 0.95 built from a single success is a guess wearing a lab coat. An edge at 0.78 built from nine observations across four machines is worth acting on. When the two disagree, trust the count.

This is also why silence decays a score rather than preserving it.

A lesson that nothing has recalled in weeks has not been confirmed by that silence. It has simply gone unchecked while the world moved on. The package manager changed a default. The base image shipped a new kernel. Someone rotated a key.

Decay does not claim the lesson is wrong. It withdraws the claim that the lesson is still known to be right — which is a different and much more defensible statement.

Inspecting the graph yourself

None of this is meant to be taken on faith. Two tools open the graph up directly: ckg_inspect shows the edges around a concept, and trace_dependency walks the chain between two of them.

It is worth running these on your own instance early. A causal graph is only as good as what people wrote into it, and looking at the edges is the fastest way to find out whether your team records conditions or just records fixes.

When the ground moves, the lessons on it should move too

A lesson can declare what it stands on with depends_on — a runtime version, a service that must be up, a tunnel that must be active. When one of those prerequisites is marked stale, every lesson that named it is flagged for review rather than left quietly trusted.

PREREQUISITEnode:>=20 · stalefix:pnpm-store-pathneeds reviewfix:corepack-shimneeds reviewdeploy:web-buildneeds reviewWithout this, a lesson stays trusted long after the ground it stood on moved.
One prerequisite goes stale and the flag spreads to everything that declared it. The alternative is worse than it sounds: not a wrong answer, but a confident answer nobody has any reason to doubt.

The failure this prevents is a quiet one. Nothing turns red.

The recall still returns a fix. It still carries a high score. It is still phrased with total confidence — and it has been wrong since the day the runtime was upgraded. Nobody finds out until the fix is applied to something that matters.

A flag that says “check this” is a small thing to build and an expensive thing to lack.

Contradictions are surfaced, not overwritten

When a new observation conflicts with what an edge already claims, the store does not silently take the newer one. It warns that the outcomes disagree and keeps the audit trail, because a contradiction is usually information rather than noise: the same command really does succeed on one host and fail on another, and the difference between those hosts is the condition nobody has written down yet.

The brain_predict tool

Before attempting a task, an agent can ask the Brain what's likely to go wrong:

brain_predict(
  context = "Deploying ClickHouse with Docker on a new Ubuntu server",
)

# Response:
{
  "predicted_failures": [
    {
      "description": "Healthcheck using localhost may fail if IPv6 is disabled",
      "probability": 0.91,
      "mitigation": "Use 127.0.0.1 + listen_host = 0.0.0.0",
      "severity": "critical",
      "based_on": 7
    },
    {
      "description": "ClickHouse OOM on low-memory hosts",
      "probability": 0.63,
      "mitigation": "Set max_server_memory_usage_to_ram_ratio = 0.8",
      "severity": "major",
      "based_on": 3
    }
  ]
}

Pre-load mitigations before the failure happens. That's the difference between reactive debugging and proactive deployment. Note that based_on ships with every prediction: seven observations and three observations are not the same kind of warning, and the response says so rather than flattening both into a percentage.

Why not just a vector database?

Vector DBs are great for “find things that look like X.” The CKG adds: “find things that cause X, or are caused by X, under what conditions.” A vector search for “healthcheck failure” returns text chunks. The CKG returns the condition, mechanism, fix, confidence, and observation count — together.

The two are not rivals. Similarity search is how you find the neighbourhood; causal edges are how you decide which house to knock on. cachly runs both, which is why a recall can answer “what looks like this” and “what does this lead to” in one round trip.

Edge types supported today: causes, fixes, requires, blocks, conflicts_with.

What a causal graph gets wrong

Worth saying plainly, because the phrase “causal graph” promises more than any such system can deliver. These edges are built from self-reports. When an engineer writes down what fixed a problem, they are recording what they changed last, which is not always what made the difference. A graph fed on that inherits every one of those mistakes, and a high confidence score means many people agreed — not that anyone verified.

Two habits keep this honest.

Record the condition even when it feels obvious. The condition is what stops a fix from being applied where it cannot help, and it is the first thing people leave out when they are tired.

Treat a contradiction as a finding rather than a merge conflict. When the same action succeeds here and fails there, the graph is telling you a condition is missing — and that missing condition is usually the most valuable thing in the whole entry.

Using it today

The CKG is live in all Brain instances. Every learn_from_attempts call contributes to it. Every recall_best_solution and smart_recall query benefits from it. No configuration needed.

npx @cachly-dev/mcp-server@latest autopilot

cachly is a persistent AI Brain for developers — memory shared across Claude Code, Cursor, GitHub Copilot & Windsurf simultaneously. Auto-detects every editor. Bootstraps from your git history. 122 MCP tools. Free tier, EU servers, no credit card.

Your AI is forgetting everything right now.

Every session starts blank. Every bug re-discovered. Every deploy procedure re-explained. cachly fixes that in 30 seconds — your AI remembers every lesson, every fix, every teammate's hard-won knowledge. Forever.

Four ways to install

Claude Code
/plugin marketplace add cachly-dev/cachly-mcp
/plugin install cachly-brain@cachly
Any MCP editor
npx @cachly-dev/mcp-server@latest autopilot
VS Code
JetBrains
🇪🇺 EU servers · GDPR-compliant🆓 Free tier — forever, no credit card⚡ 30-second setup via npx🔌 Claude Code · Cursor · Copilot · Windsurf