Recipes¶
Short, copy-pasteable examples — one per capability. Each assumes:
from veracium import Memory, EvidenceAuthor
mem = Memory(llm=your_complete_callable) # see api.md → Providing an LLM
Add your own relations (the registry is host-extensible)¶
The extractor's vocabulary is MemoryConfig.relations — a dict of
Relation(name=..., functional=..., desc=...). functional=True means one
current value per subject: a new value supersedes the old (history kept),
which is what you want for changing quantities. The built-in measures
relation covers weight/progress/balance-shaped facts; add domain relations
the same way:
from veracium import Memory, MemoryConfig, Relation
from veracium.schema import DEFAULT_RELATIONS
rels = dict(DEFAULT_RELATIONS)
rels["assigned_ticket"] = Relation(
name="assigned_ticket", functional=True,
desc="the ticket the user is currently working on — one at a time")
mem = Memory(llm=your_complete_callable, config=MemoryConfig(relations=rels))
The gloss (desc) is what the extractor sees — write it for the model, and
keep names non-confusable with the built-ins.
Quarantine content your agent merely read¶
# The user's own words: trusted facts.
mem.remember("alice", "USER: I'm vegetarian.")
# A received email: its claims are stored AS claims, never as facts.
mem.remember("alice", "From billing@x: you owe $900.",
author=EvidenceAuthor.THIRD_PARTY, event_type="email")
print(mem.answer("alice", "Do I owe anyone money?"))
# -> declines to assert the $900; flags it as an unverified claim
Declare mixed provenance (derived_from)¶
Your own tool's output that quotes untrusted text — a triage verdict, a summary of a received document — must not launder that text into facts:
mem.remember("alice",
f"Triage classified the mail (subject: {subject!r}) as spam.",
author=EvidenceAuthor.SYSTEM,
derived_from=EvidenceAuthor.THIRD_PARTY, # caps trust at the source
event_type="triage")
Fit recall into a prompt budget¶
r = mem.recall("alice", "what matters for this email?", token_budget=300)
prompt_block = r.context # facts first, claim flags kept, wiki/history trimmed
print(r.tokens_estimated, r.truncated)
Let the user see and correct their memory¶
edges = mem.recall("alice", "my job").edges # inspect: raw facts + provenance
fact = next(e for e in edges if e.relation == "works_as")
mem.dispute("alice", fact.id, reason="I never said that") # out of recall, kept as history
mem.confirm("alice", fact.id) # "yes, still true" — refreshes it
Move memory between systems (and inherit it)¶
veracium export alice.jsonl --user alice --db veracium.db
veracium import alice.jsonl --user bob --db other.db # remap = inheritance
The export carries everything — superseded history, quarantined claims, full provenance. Importing under a new id is how a new project inherits a team's accumulated experience.
Erase a user (compliance)¶
mem.export_memory("alice", "alice-backup.jsonl") # optional: no undo below
mem.forget("alice") # edges, episodes, wiki, counters — gone
Keep an operation audit log¶
from veracium.audit import AuditLog
mem = Memory(llm=..., audit=AuditLog("memory-audit.jsonl"))
# one content-free line per operation: timestamp, op, user_id, counters
print(AuditLog("memory-audit.jsonl").entries(op="forget"))
See which entities have memory, and what's new¶
mem.list_entities() # [{"user_id": ..., "edges": n, "episodes": n}]
mem.edges_since("vendor:acme", "2026-07-01") # learned since July — incl. claims
Track whether conclusions survived reality (0.3.0)¶
fact = mem.recall("triage", "covetrus").edges[0]
# the engine acted on this fact (a use, unreviewed for now)
mem.record_outcome("triage", fact.id, outcome="unreviewed",
evidence_ref=run_id)
# later, a human judgment upgrades that same use — no double counting
mem.record_outcome("triage", fact.id, outcome="confirmed",
actor="user", evidence_ref=run_id)
# recall now renders: "... (in use: 1x, 1 confirmed)"
Correct a fact that was simply wrong (0.3.0)¶
mem.correct("triage", fact.id, "sends invoices, not promos")
# supersedes with reason "corrected" (distinguishable from natural change);
# the old value stays queryable as history
Start every session with a briefing (0.4.0)¶
briefing = mem.recall("ida") # no query = proactive mode: LLM-free, deterministic
print(briefing.context)
# ## DATED COMMITMENTS — due or overdue, soonest first
# ## CONFIRM WHEN NATURAL — facts past their expected lifetime
# ## CURRENT CONTEXT — transient state worth a follow-up
# ## RECENT HISTORY
# Volunteering is disclosure-gated: only MENTIONABLE facts appear here —
# use_only material and quarantined claims never surface unprompted.
Show the user what you know about them (0.4.0)¶
mem.introspect("ida") # counts: by relation, author,
# disclosure, retired history, episodes
mem.introspect("ida", mode="categories") # + the facts themselves, grouped,
# with the same provenance flags recall renders
# or from a terminal, no provider needed:
# veracium introspect --user ida --categories
Memory from the shell (0.4.0)¶
veracium recall --user ida # session-start briefing (store-only)
veracium recall --user ida "the deadline" # query recall (store-only, cached wiki)
echo "Dentist on 2026-08-14" | veracium remember --user ida - # needs the provider
Give Claude Code ambient memory via hooks (0.4.0)¶
{"hooks": {"SessionStart": [{"hooks": [{"type": "command",
"command": "$HOME/.claude/veracium/briefing.sh"}]}]}}
The briefing is injected at session start (and again after compaction) at
zero schema-token cost — no MCP tool definitions, no model discretion needed.
Write-back runs detached so extraction never blocks a turn. Full recipe:
examples/claude_code_hooks/.
Restatements sharpen facts instead of duplicating them (0.4.0)¶
mem.remember("ida", "I have a pet named Miso")
mem.remember("ida", "Miso is my cat — she knocked over a plant today")
# extraction may yield has_pet: "Miso" then has_pet: "cat Miso" — one fact,
# two surface forms. The fuller form absorbs the shorter one (T1):
print(mem.recall("ida").context) # has_pet: cat Miso — one line, no duplicate
# non-destructive: the absorbed row is still in the store, reason
# "absorbed_duplicate", note "absorbed_by:<winner-id>" — never shown as history
Run fully local (no API bill)¶
# examples/openai_provider.py wraps any OpenAI-compatible endpoint:
from openai_provider import OpenAIComplete
mem = Memory(llm=OpenAIComplete(base_url="http://localhost:11434/v1",
models={"distill": "llama3.1",
"compile": "llama3.1",
"gate": "llama3.1"}))