ergo
Sign inGet started

Concepts

The mental model behind Ergo.

One store, two behaviors

Everything Ergo remembers is a claim — a statement scoped to an (org_id, project). But claims come in two flavors, and the difference is the whole point.

KindBehaviorReasonChanged by
factupsert freelyoptionaloverwrite / ingest
decision · constraint · rejection · conventionappend-onlyrequiredsupersede

Facts are cheap, high-churn context — paths, versions, who-owns-what. They upsert without ceremony and skip the contradiction gate.

Decisions, constraints, rejections, and conventions are the durable choices you don't want a future session to reverse by accident. They are append-only, they must carry a reason, and the only way to change one is to supersede it — which keeps the old version linked in history.

Why reasons are mandatory

A decision without a reason can't defend itself. When a later session asks "why do we deploy only on green CI?", Ergo's why query returns the best reasoned belief plus its rationale and full supersede history. A reason-less claim can never win that query — so decisions require one at write time.

The contradiction guard

A guarded write (remember, learn, supersede) doesn't just append. It runs the candidate claim through a pipeline before it's allowed to land:

  1. Normalize — an LLM normalizer parses the statement into a structured form (subject, stance, scope, and an atomic value where one exists — a color, port, version, hostname, or number).
  2. Structural — compares the normalized claim against active claims in the same scope: same subject, same-direction stance, overlapping scope, but a disagreeing atomic value flags a conflict.
  3. NLI — natural-language inference checks for entailment/contradiction that the structural pass can't see from values alone.
  4. Judge — decides the outcome: a HIGH-confidence contradiction blocks the write; softer signals surface as an advisory warning.

A blocked write returns HTTP 409 (the MCP tools surface this as a structured conflict, not an error). That 409 is the product working — it's Ergo refusing to let the agent quietly contradict itself.

The gate is deliberately selective. It runs on decisions/constraints, where a stale claim is costly. Bulk reference content goes through ingest, which skips the gate entirely (see below).

Here's that same pipeline alongside the other four ways a claim moves through Ergo, so the shape of the whole system is in one place:

Stored
0
Warn
0
409
0

remember and supersede are the two gated lanes — both run normalize → structural → NLI → judge, and both can be turned away with a 409. ingest is drawn passing underneath the four gate rings, because it genuinely skips them — it's the fact fast-path described above. recall and why are drawn arcing backwards, out of the store rather than into it, because they're reads: nothing they do can ever 409. A blocked claim on a gated lane travels only as far as the judge ring before reversing and returning red, which is the 409 from the paragraph above, drawn as a path rather than a status code. The five plates at the far end are the physical store — claims, vec_claims, writes, conflict_events, and projects — all in the one SQLite file described in One SQLite file below. Drag to orbit, and use the lane buttons or "force a contradiction" to see a 409 on demand.

Resolving a conflict: supersede vs. retract

When you hit a 409 — or when a decision simply changes — you have two distinct tools, and the difference matters:

  • supersede"I changed my mind, and here's why." The decision genuinely changed. Ergo writes a new row, flips the old one to superseded, and links them so the why-chain survives. Use this to preserve history.
  • retract"this was wrong at birth." A typo, test junk, or a mis-scoped write that never should have existed. It flips to retracted (reason required) and leaves the active set, but stays visible in history. Retract runs no contradiction gate — it's pure removal.

Rule of thumb: if the world changed, supersede. If the claim was a mistake, retract.

Provenance

Beliefs formed from a source keep that source attached. learn takes a required source and folds it into the reason, so a later why/recall can tell you not just what is believed and why, but where it came from — a file and line, a doc, a URL. This is the bridge between raw ingested reference (no gate) and a contradiction-checked claim.

Audit trail

Every guarded write and every conflict it triggers is logged — not just the current belief. If you need to answer who wrote what, and when for a compliance or security review, /audit (or the ergo_audit tool) is a self-serve, read-only trail of your own org's writes and conflict events — see HTTP API → GET /audit. On the hosted app this is also a browsable page — see The app → Audit — with a project selector and paginated tables, not just the raw API response.

Scope

Every read and write is scoped to an (org_id, project) pair. Claims in one scope are never contradiction-checked against another — no cross-contamination between repos or teams. The MCP adapter defaults the scope to org_id="claude-code" and project = the git-repo basename of the working directory, both overridable per call.

org_id is also the tenant — the isolation unit in a multi-tenant deployment, where each tenant gets its own database file and its own token. project is a namespace inside a tenant, not a security boundary. See Multi-tenancy for the full model.

One SQLite file

The entire store — claims, reasons, history, and the sqlite-vec embedding index — is a single SQLite file. One file, one embedding space, one backup. That makes Ergo trivially air-gappable and portable: copy the file and you've copied the memory. The embedding dimension is locked at the first write, so pick your embedding provider before you start writing.