Skip to content

Evidence

Evidence is the raw record of engineering activity: what happened, when, and where. It is the input to everything else, and its quality sets the ceiling on the quality of every answer above it.

Evidence is never edited or deleted. This is a design commitment, not a storage detail, and it buys one specific thing: the audit trail means something. A record that can be rewritten after the fact cannot answer “what did the agent know at the time”, which is the only question that matters after an incident.

Correction works by adding:

supersedesstatus: deprecateddecision · March'use the legacy queue'correction · June'migrate off it'

Both records survive. The March decision stops being returned as current, and anyone auditing a February run still sees what was true then.

The most common mistake at rung 1 is remembering everything — dumping transcripts in and expecting search to sort it out. It does not. A corpus of transcripts is a corpus of noise, and noise costs you twice: once in retrieval quality, once in the tokens spent carrying it.

Write conclusions, not transcripts.

Write thisNot this
“The nightly reconcile job fails when billing/reconcile.py changes without regenerating fixtures.”The full CI log
“We migrated off the legacy queue in June; new services use the event bus.”The whole design-doc thread
payments/ledger.go has caused three rollbacks — change it with a migration plan.”Every PR touching that file

A good memory is one sentence that a future agent can act on, scoped to where it is true.

Every evidence record declares where it came from. The set you may send is SourceTypePublic: run, pr, ci, deploy, incident, doc, review, correction.

A hydrated record may carry a wider set — a record can report a source that the ingest verb does not accept directly. Use the public set when writing.

Every memory traces back to the evidence that produced it. This is what lets an agent cite its reasons and a human check them, and it is what makes a memory with five supporting records visibly stronger than one with none.

It is also what makes disagreement tractable. When two memories conflict, you can see what each is built on rather than guessing which to trust.

Evidence is not just what your agent reads — it is what your agent writes. Report what actually happened:

after the action:
evidence.ingest(
source_type = "pr",
summary = "Reconcile loop rewritten; fixtures regenerated",
scope_key = "repo:payments",
)

An agent that reads but never writes leaves the corpus exactly as good as the day you seeded it. See Write evidence back.

evidence.ingest takes a batch, and a batch can be partly accepted: outcomes come back in accepted[] and rejected[], and the call is a success with a mixed result.

The SDK does not retry a partial batch, and neither should you wholesale — replaying it re-sends records the server already committed. Resubmit the rejected subset as a new call.

One gap, stated rather than hidden: a rejected record carries index, code and message but no retryable flag, so automatic partial replay means interpreting the code yourself. That is a contract deficiency on our side, not something you are missing.