Corrective memory for AI agents
A user tells the agent where the team deploys. A month later they move. Retrieval hands the model both statements and the model guesses which one holds; Recall marks the first one replaced when the second is written, returns only what is true now, and keeps the old value where history and as_of reads can find it.
The code
Runs as written: pip install polign-recall brings the client, the recall
binary and a local polign_db. Swap local_dir for backend="polign" and a server
URL when the database should live in your bucket, or for PostgreSQL, MongoDB or Qdrant.
from polign_recall import Client with Client(local_dir="./recall-text", extract_model="openai:gpt-4.1-mini") as memory: memory.remember(text="We deploy to Fly.io. Alerts go to #ops-alerts.") memory.remember(text="We moved off Fly.io last week; everything deploys to GKE now.") for m in memory.ask("Where do we deploy?"): print(m.text, "| before:", [b.text for b in m.before]) for t in memory.history_text("where we deploy"): for step in t.changes: print(step.when[:10], step.change, step.ended, "->", step.began)
What it printed:
user deployment target: GKE | before: ['Fly.io']
2026-11-03 stated () -> ('user deployment target: Fly.io',)
2026-11-03 replaced ('user deployment target: Fly.io',) -> ('user deployment target: GKE',)
2026-11-03 stated () -> ('user detail: alerts go to #ops-alerts',)
What the record looks like
The extraction model turns each passage into typed statements, one record each. Every record is one vector in the collection with this metadata; the replacement is worked out when the record is read, from the predicate's rule (deployment_target holds one value), so nothing is updated in place and nothing is deleted. Two of the records above, as polign list shows them:
{"kind":"fact","subject":"user","predicate":"deployment_target","value":"Fly.io",
"source":"user_stated","confidence":"1","retraction":"false",
"observed_at":"2026-11-03T18:55:21.418Z","text":"user deployment target Fly.io"}
{"kind":"fact","subject":"user","predicate":"deployment_target","value":"GKE",
"source":"user_stated","confidence":"1","retraction":"false",
"observed_at":"2026-11-03T18:55:24.902Z","text":"user deployment target GKE"}
On polign_db the collection is a set of segment files in your bucket (segments/*.json.gz plus a write-ahead log), so the memory is a listable object prefix in your own account. On PostgreSQL, MongoDB or Qdrant it is a table or collection you already run. Forgetting writes a third record with retraction: true; it withdraws the belief and keeps the trail.
Evidence
Measured on Recall compared with mem0 and Zep: one user whose homes, jobs, emails and diet change over nine months, the same model extracting, answering and judging for all three. Recall answered 18 of 18 in every scenario, and when the user asked it to forget a shellfish allergy that had been stated in the same sentence as a new diet, Recall kept the diet in 3 of 3 runs; mem0 and Zep lost it in 3 of 3. See a correction walks through why plain retrieval answers from the old fact.
Where to go next
- Recall compared with mem0 and Zep
- See a correction
- How the fold turns records into beliefs
- Recall vs Mem0
Recall is typed, durable memory and state for AI agents. It stores corrections, decisions and task state as append-only records in your own object store (S3 or GCS), so an agent can be corrected without retraining and resumed after a crash, restart or pod replacement without snapshotting the process.
Try it
One pip install brings the client, the recall binary and the database. The snippet on
this page runs as written.