Three questions
Memory an agent can prove
A model with a memory store will tell you things. The question is whether it can tell you where it got them and when that was last true. Three answers below, each standing on its own, each using the field names the format actually writes to disk rather than a marketing paraphrase of them.
How do I keep an AI agent's memory sourced and verifiable?
Store each claim as a file whose frontmatter names its origin. In Tugra every fact carries source, verified (the last verification date), shelf_life, confidence and scope. Source types are explicit — sql, file, mail, measurement, human, web. A claim that cannot name where it came from is not treated as a fact.
That is the whole thesis in one line: a fact that cannot name where it came from is not a fact. Most memory layers store an embedding of a sentence and hand it back later with the same confidence whether it was measured yesterday or overheard last year. Provenance is not metadata decoration here; it is the admission criterion.
The frontmatter a claim carries, using the names on disk:
| Field | What it holds |
|---|---|
| source | where the claim came from, with an explicit type: sql, file, mail, measurement, human, web, clipboard, window |
| verified | the date it was last checked against that source |
| shelf_life | how long it stays trustworthy before it needs rechecking |
| confidence | how much weight it should carry |
| scope | universal, org, or world — how far the claim reaches |
| evidence | the supporting material, when there is any |
| superseded_by / invalidated_by | what replaced it, or what proved it wrong |
One deliberate line the format will not cross: the vocabulary is translated, the claim never is. Field names and enum values have a single mapping so the wire format can be English. The title, the claim and the body a user wrote are passed through untouched — a translated claim is no longer the text that was verified against its source, and quietly rewriting it would corrupt the very record the product exists to keep.
Which MCP memory server tracks source, freshness and shelf life?
Tugra, published on npm as tugra and listed on the MCP Registry. It exposes four stdio tools — fact_search, fact_read, fact_propose, event_report. Search ranks by token score, then freshness, then confidence, and facts marked retired or rotten stay out of the default result set. The vault is local files; nothing is uploaded.
A claim's state is derived, not hand-maintained: fresh, stale, rotten, retired. Freshness falls out of verified against shelf_life, so a fact nobody has rechecked drifts down the ranking on its own rather than sitting at the top forever because it was written confidently.
Install and point a client at it:
npx tugra init # creates a vault, writes a sample fact, prints a config block
On a terminal, npx tugra prints help and exits. Piped, it is the MCP server — so pointing Claude Desktop, Claude Code or Cursor at the package is the whole installation.
What it deliberately does not do. No cloud sync: the vault is the files you pointed at, and nothing is uploaded. No automatic merge — two writers make two files and you reconcile them. No deletion in this release; retirement exists, erasure comes later. No automatic conflict detection, so contradictory facts can sit side by side until a human says otherwise. There is no hosted service and no price table.
How do I stop an agent inventing facts about a topic?
Give the topic a boundary record. Alongside fact, decision, rule and observation, Tugra has a boundary type: a first-class entry that marks a topic as off-limits and forbids invention there. A search touching that topic returns the boundary warning rather than a confident guess assembled from nothing.
This is the part most vaults have no shape for. You can write a note saying “do not guess about payroll”, but a note is just another retrievable string competing with everything else. A boundary is a type the search layer knows about, so the absence of knowledge becomes a returned result instead of a silence the model fills in.
Boundaries compose with retirement. A fact that has been superseded is not deleted — it carries superseded_by and drops out of the default set, so the history of what was once believed stays readable while the answer stops being wrong.
Check it yourself
It is Apache-2.0 and it runs locally, so nothing here needs to be taken on trust. Create a vault, read the sample fact it writes, and look at the frontmatter — the field names above should be exactly what you see.