The scenario
You are adding memory to something and the API surface looks large. It is not. Three calls carry almost every integration, and a fourth exists only to save you writing a join.Step 1 — Record
Step 2 — Retrieve
Ranked rows, each with a score, when your code wants to do something with the results.Step 3 — Reason
One synthesised answer across everything the space holds, rather than rows you have to read yourself.reason runs a multi-step loop, so it costs more and answers vaguer questions.
Use retrieve when the caller can read rows; use reason when they need a
conclusion.
Step 4 — get_context, when you build the prompt yourself
retrieve, returned as one prompt-ready string with the
token budget enforced server-side. It saves a join and a truncation bug.
Evals
- Record three facts where the third only makes sense given the first two.
retrievea question answerable from one of them. Check it ranks first.reasona question that needs all three. Check the answer uses all three.- Ask something unrelated. Empty is the correct answer, and a system that invents one has its score floor set too low.
Guardrails
- Recording is asynchronous under the hood but
recordblocks while extraction runs. In a request path, use background writes instead. - A space is created on first write. A typo in
space_idsilently makes a new space rather than erroring — checklist_spacesif memories go missing. relevance_scorecan exceed 1.0. It is a ranking signal, not a probability.
The script
Complete and runnable:memory_basics.py.