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.
Immutable and append-only
Section titled “Immutable and append-only”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:
Both records survive. The March decision stops being returned as current, and anyone auditing a February run still sees what was true then.
What to write
Section titled “What to write”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 this | Not 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.
Source types
Section titled “Source types”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.
Provenance is the product
Section titled “Provenance is the product”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.
Closing the loop
Section titled “Closing the loop”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.
Batches partly succeed
Section titled “Batches partly succeed”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.
- The memory graph — what evidence becomes
- Write evidence back — the practical version