Add thread state and long-term memory without confusing memory with facts.
The first memory feature should be small enough to review.
Learners scope a memory feature as a narrow product slice.
Why this matters: Narrow scope makes consent, tests, and correction tractable.
Problem anchor: a coding tutor should remember that a learner prefers TypeScript examples. It should not remember every emotional aside, every code snippet, or facts from retrieved docs.
The first slice accepts explicit preference statements, stores provenance, retrieves them for lesson/example tasks, and lets the learner correct them. That is enough to prove the architecture.
Accept: “Remember that I prefer TypeScript examples.” Reject: “I hate recursion today.” Reject: “The docs say pgvector uses HNSW.” The first is durable preference, the second transient mood, the third external knowledge for RAG.
The acceptance card becomes the regression suite seed.
The build needs boundaries before code.
Learners avoid mixing memory with documents or workflow progress.
Why this matters: Confusing memory with source-of-truth data creates stale and ungoverned behavior.
Thread state keeps the current run coherent. Long-term memory personalizes future runs. RAG supplies grounded external facts. The app database stores canonical records. Workflow engines store exact progress.
For the TypeScript preference slice, the memory store only holds user preference records. It does not store lesson content, billing status, or source documents.
| Option | Need | Store | Reason | When to choose | Cost | Complexity |
|---|---|---|---|---|---|---|
| Current plan/tool results | Run-local state. | Thread checkpoint or graph state. | Needed only to resume this run. | Use inside one conversation or workflow. | Low | Medium |
| User preference | Future personalization. | Long-term memory with provenance. | Changes later agent behavior. | Use with consent and correction. | Medium | Medium |
| Product documentation | Grounded external facts. | RAG/document index. | Source of truth lives outside user memory. | Use for citeable facts. | Medium | Medium |
The write path should make future correction possible.
Learners implement the memory write path.
Why this matters: Provenance and policy are easiest to add before data exists.
A minimal memory row can include namespace, type, value, source turn ID, created time, confidence, status, and optional expiration. This is enough to retrieve and correct later.
Avoid opaque transcript dumps. They are hard to inspect, hard to delete selectively, and likely to include sensitive or irrelevant content.
The user says, “Please remember: I prefer TypeScript examples.” The extractor proposes {type: preference, value: prefers TypeScript examples}. Policy accepts because it is explicit, future-useful, and low sensitivity.
The source turn ID is stored so the UI can later show where the memory came from.
Memory retrieval is part of prompt assembly.
Learners code the recall path and predict output.
Why this matters: Poor recall leaks data or clutters prompts with stale preferences.
When assembling the prompt, include relevant memories under a label such as “User preferences from memory.” Do not let memory masquerade as system policy or external evidence.
Spaced recall: from agent memory, current user instruction and safety policy outrank older memory. Retrieval should be narrow enough that this ordering remains readable.
store = [] def maybe_write(user_id, turn_id, text): lowered = text.lower() if "remember" in lowered and "prefer" in lowered: value = text.split("remember", 1)[1].strip(" :.") store.append({"ns": ("user", user_id), "type": "preference", "value": value, "source": turn_id, "status": "active"}) def recall(user_id, task): if "example" not in task.lower() and "lesson" not in task.lower(): return [] return [m for m in store if m["ns"] == ("user", user_id) and m["status"] == "active"] maybe_write("u1", "turn-7", "Please remember: I prefer TypeScript examples.") print(recall("u1", "write a lesson with examples")) print(recall("u1", "check my invoice"))
It does not. The preference is relevant to examples or lessons, not invoice checking.
A memory feature ships with lifecycle tests.
Learners complete the build with validation and tracing.
Why this matters: Memory regressions are sticky because wrong state affects future sessions.
Tests should cover explicit remember, transient no-write, sensitive no-write, user namespace isolation, task-relevant recall, correction, deletion, and current-instruction override.
Traces should show memory write candidates, acceptance policy result, stored memory ID, recall query, and prompt injection reason. This makes reviews and incidents diagnosable.
Review memory behavior across multiple turns.
Retrieval prompt: rebuild the implementation by naming memory class, extractor, acceptance policy, store, retrieval filter, prompt injection point, trace, correction path, and regression tests.
Implement a small preference-memory feature for an agent: accept explicit “remember my preference” statements, reject transient moods, store provenance, retrieve only for relevant tasks, expose correction, and run five tests. Next rung: add observability for memory writes and recalls.
Your agent remembers that a user prefers metric units. After three turns, the user says 'never mind, just use whatever.' Which memory action is most appropriate?
A user revocation is a correction event — the memory should be deleted or marked inactive so it no longer influences future answers.
In one or two sentences, explain the difference between a thread checkpoint and a long-term memory store, and give one example of information that belongs in each.
Thread checkpoints are session-scoped and transient; long-term memory is cross-session and intentionally persisted — conflating them leads to either data loss or privacy leaks.
When injecting a retrieved memory into an agent's prompt, which practice best supports traceability?
Labeling injected memories and logging their IDs lets you trace exactly which stored fact shaped a given answer — essential for debugging and correction.
A user mentions 'I'm stressed about my exam tomorrow.' Should the agent store this as a long-term memory? Why or why not?
Transient or time-bound statements (like stress about tomorrow's exam) are rejection candidates — they won't be accurate or useful after the moment passes.
You are writing tests for your memory system. Which pair of tests together gives you the strongest confidence that memory extraction is working correctly?
Pairing an acceptance test (valid preference gets stored) with a rejection test (transient or vague input is not stored) covers both sides of the extraction decision boundary.