Session 4 of 11
Memory Across Turns and Sessions
Overview
Chapter 4 — Memory Across Turns and Sessions
Course: Building AI Agents
Prerequisites: You can read and run a short Python script. You know that a model reads a limited context window, and that an agent loop plans, acts, observes and repeats (the previous chapter). Everything else this chapter uses (stateless requests, compaction, tool-result clearing, notes, a memory store, supersession, expiry and scope) is defined in the notes before it is used.
What the reader can do after this chapter:
- Decide for a given fact whether an agent should keep it verbatim, summarize it or discard it, and name the place it should live: the context window, a persistent store or a notes file.
- Apply a fixed write rule, a compaction rule and an expiry rule to a stream of events and state exactly what the agent will recall afterwards.
- Diagnose a memory bug (a stale fact, a fact leaked between users, a fact lost to compaction or a sensitive value stored) and name the design change that removes it.
Core question this chapter answers: When an agent “remembers” something across turns or sessions, where is that memory actually kept, and which design decisions decide whether what it recalls is still true and belongs to the right person?
Connections:
- Builds on: Chapter 3, the single-agent loop, whose observations pile up in the context window turn after turn, and the context-window material in Getting Started with AI, which treats the window as a limited budget.
- Leads into: Chapter 6, which covers identity and access for agents. The memory policy you write in this chapter’s project decides which agent may read and write which entries once a store is shared.
Your answers are scored
This chapter is assessed. The quiz is marked against a key held separately from your materials. Questions 1–8 are multiple choice and are marked by comparing your letter with the key. Questions 9–10 ask for a short answer in an exact format, and each one is marked by a rule printed with the question, so you can check that your answer has the right shape before you submit it.
- Nothing is judged by reading it for style. An answer either matches the rule or it does not.
- All four project tasks are scored from an evidence file of
key: valuelines. Every line’s accepted value, or the rule that decides it, follows from what the task’s code prints, so you can check your own file before you submit it.
Notes
Building AI Agents — Chapter 4: Memory Across Turns and Sessions
Before you start
Nothing to install for the reading. For the project you need Python 3 and nothing beyond its standard library. No task needs an account with a model provider, an API key or any payment.
Keep one question in mind while you read: if the agent says it remembers this, where is the memory physically stored, and what would make it wrong? By the end of the chapter you should be able to answer it for any fact an agent keeps, from the store’s write rule, its expiry rule and its scope.
Summary
A language model has no memory of its own between requests: whatever an agent seems to remember was put into the request again, either from history your application sends, from storage your application reads, or from conversation state that a provider stores and replays for you. That makes memory a design problem with four decisions. Where a fact lives (in the window for this task, or in a store or notes file that outlives it). How the window is kept small (compaction summarizes it, and clearing old tool results trims it). How a fact stays true (a newer value replaces an older one, and an old one expires). And whose fact it is (each entry belongs to one user or scope). Memory bugs are quiet: the agent answers fluently from a fact that is stale, lost or somebody else’s. This chapter teaches you to make each of the four decisions in code, so that you can say what an agent will recall before it recalls it.
Key concepts
| Term | Definition |
|---|---|
| Stateless request | A model request that carries everything the model will see. A provider may store conversation state for you, but the earlier content still has to reach the model’s context for the model to use it. |
| Conversation history | The earlier messages your application sends again with each new request so that the model can use them. It grows with every turn. |
| Compaction | Summarizing a conversation that is nearing the context window limit, and starting a new context window with the summary in place of the full history. |
| Tool-result clearing | Removing the raw output of tool calls made earlier in a conversation, because the agent rarely needs the raw result again once it has used it. |
| Structured notes (agentic memory) | Notes the agent writes to storage outside the context window, and reads back into the window at later times. |
| Memory store | Storage your application controls (files or a database) that holds entries across requests and sessions. |
| Write rule | The rule that decides what happens when a new value arrives for a key that already has one. This chapter’s rule: the newest write wins, and the older entry stays in the log marked as superseded. |
| Supersession | A newer entry replacing an older one for the same key, so that the older one is no longer recalled. |
| Expiry (TTL) | A limit, in turns, on how long an entry may be recalled after it was written. An entry past its limit is not returned. |
| Scope | The owner of an entry (a user, a team or everyone). A recall asks for a scope and gets only entries that belong to it. |
| Stale memory | An entry that was true when written and is no longer true, but is still recalled. |
| Pinned message | A message the compaction rule is told to keep verbatim, such as an order number the rest of the conversation depends on. |
Explanations
The failure, before the explanation
Here is an illustrative support incident, of the kind this chapter is designed to prevent. A team
builds a support agent that writes down facts about each customer so that it need not ask twice. In
turn 2 a customer says they are on the Basic plan, and the agent stores plan = basic. In turn 9
the same customer says they upgraded yesterday to Pro, and the agent stores plan = pro as a second
entry beside the first. Then a customer asks about their monthly export limit. The agent looks up
plan, its lookup returns the first match, basic, and it quotes the Basic limit.
Nothing malfunctioned in the model. It answered correctly from what it was given. The memory design had no rule for what a second write to the same key means, so the old entry was still there. A second incident from the same agent: two customers share one store, the lookup is by key alone, and it returns another customer’s address. Each of these is a decision the team made, and each is one this chapter gives you a way to make differently.
Where “memory” physically lives
Start with a chat in which the agent appears to remember. The assistant answers a follow-up that depends on turn 3. In every case the detail reached the model because it was in this request: sent again by your application, read from storage by your application, or replayed from conversation state that a provider keeps.
One provider’s documentation says it plainly: “each text generation request is independent and
stateless”, and a multi-turn conversation is built by providing earlier messages as parameters of
the next request (OpenAI, Conversation state). The same page describes a stateful option, the
previous_response_id parameter, which chains responses into a threaded conversation, and it adds
that “all previous input tokens for responses in the chain are billed as input tokens” (OpenAI,
Conversation state). So even a provider that keeps the thread for you still puts the earlier
content back into what the model reads, and you pay for it.
A first way to picture it: the model is a consultant who arrives each morning with no recollection of yesterday. Whatever they appear to remember is in the folder you hand them. A second way: a web server with no session state. It “remembers” a user only because each request carries a cookie or the server reads a row from a database. Memory for an agent is the folder, the cookie or the row.
This gives three places a fact can live, and the rest of the chapter is about choosing between them:
- The context window, for this task only. It is rebuilt from the history each request, and it is limited.
- A memory store, such as a database table or a directory of files, which outlives the window and which your application owns.
- Notes the agent writes itself into that store and reads back later.
The window fills, so something must shrink it
Take an agent that investigates an outage. By turn 30 its context holds forty log-search results, each hundreds of lines, and the answer it needs from them is one sentence it wrote down at turn 6. The window is a limited budget. One provider’s engineering write-up describes context rot: “as the number of tokens in the context window increases, the model’s ability to accurately recall information from that context decreases” (Anthropic, Effective context engineering for AI agents). More history is not free even before the limit is reached.
Two techniques from that write-up shrink the window.
Compaction “is the practice of taking a conversation nearing the context window limit, summarizing its contents, and reinitiating a new context window with the summary.” The same page is direct about the risk: “The art of compaction lies in the selection of what to keep versus what to discard, as overly aggressive compaction can result in the loss of subtle but critical context whose importance only becomes apparent later” (Anthropic, Effective context engineering for AI agents). Picture a support thread compacted to “customer asked about a refund”: the order number from the first message is gone, and nobody notices until the agent has to look the order up.
Tool-result clearing is the lighter touch. The write-up asks: “once a tool has been called deep in the message history, why would the agent need to see the raw result again?” and calls clearing old tool calls and results “one of the safest lightest touch forms of compaction” (Anthropic, Effective context engineering for AI agents). In the outage example, the forty raw search results can go once the agent’s notes hold what it concluded from them.
A second way to see the difference: compaction is writing minutes of a meeting and throwing away the recording; clearing a tool result is throwing away the attachment after you have read it. Minutes can leave out the line that later mattered. An attachment you have already used rarely can.
This chapter’s project uses a fixed rule so that you can see exactly what compaction loses: keep the last messages verbatim, keep any message marked as pinned, and drop the rest, leaving a one-line marker. The provider’s write-up says its coding tool does this by “passing the message history to the model to summarize and compress the most critical details” (Anthropic, Effective context engineering for AI agents); the fixed rule is the same idea made deterministic, so that “what survived” can be tested.
Notes the agent writes for later
Return to the outage agent. Before it clears the search results it writes: “Root cause is the expired certificate on host db-3; checked hosts a, b, c, all fine.” That sentence is a note, and it is small. The write-up names the technique: “Structured note-taking, or agentic memory, is a technique where the agent regularly writes notes persisted to memory outside of the context window. These notes get pulled back into the context window at later times.” It gives two everyday examples of the pattern: “Claude Code creating a to-do list, or your custom agent maintaining a NOTES.md file” (Anthropic, Effective context engineering for AI agents).
The same provider offers a memory tool built on this idea, and its documentation is explicit about
where the data lives. “Because the memory tool is client-side, Claude only requests memory
operations. Your application executes each request against storage you control and returns the
result in a tool_result block.” It adds that “Memory lives entirely in your application”, with the
/memories path being “a prefix that your handler maps onto real storage, such as a per-user
directory or keys in a database” (Anthropic, Memory tool). This is the same split as in Chapter 1:
the model asks, your code acts. Everything the agent “remembers” is something your handler wrote
and your handler returns.
For long tasks the documentation gives a prompt pattern: before starting, view the memory directory for earlier progress; while working, record progress in memory; and it includes the line “ASSUME INTERRUPTION: Your context window might be reset at any moment, so you risk losing any progress that is not recorded in your memory directory” (Anthropic, Memory tool). A second picture: a lab notebook. A researcher who expects to be interrupted writes down where they are before each step, because their head is the part that gets cleared.
Notes have a cost the window does not: they persist, so a wrong note persists too. That leads to the part of memory that goes quietly wrong.
Keeping a fact true: supersession and expiry
Look again at the plan incident. The store held plan = basic from turn 2 and plan = pro from
turn 9. A lookup that returns the first match gave the wrong answer; a lookup that returns the
newest one gives the right answer. That is a write rule, and this chapter uses the simplest one:
for a key, the newest write wins, and the older entry stays in the log, marked as superseded, so that
you can still ask what was true at an earlier turn. A delete is a write too: after a delete, the key
recalls nothing.
Here is a stream of events and what the rule recalls afterwards:
| Turn | Event | recall("theme") right after |
|---|---|---|
| 1 | write theme = light |
light |
| 4 | write theme = dark |
dark |
| 7 | delete theme |
none |
The older entries are still in the log. recall_as_of("theme", 5) asks what was true at turn 5 and
answers dark, because the newest write at or before turn 5 is the one from turn 4. Keeping the log
rather than overwriting is a design choice: it costs storage, and it lets you explain a past answer.
Expiry covers the facts nobody rewrites. A customer’s stated preference may stop being true
without anyone saying so. Give each entry a limit in turns, called a TTL: an entry written at turn
w with limit t is recalled at turn n only if n - w <= t. At exactly the limit it is still
recalled; one turn later it is not. When the newest entry for a key has expired, the key recalls
nothing; it does not fall back to an older entry, because an older entry is older still. The
provider’s memory documentation gives the operational form of the same idea: “Periodically delete
memory files that haven’t been accessed in a long time” (Anthropic, Memory tool).
The two rules in this section are this chapter’s design rules, not statements from a provider. They are chosen because they are simple and testable. A real system may weigh other factors, and the project lets you check your own against exact expected values.
Whose fact is it: scope
Return to the second incident: two customers, one store, a lookup by key alone. Customer Ana’s
address is stored under address, Ben’s is stored under address as well, and the second write
supersedes the first. Ana’s next recall returns Ben’s address, and the agent writes it into her
reply. This is a leak, and a worse one than staleness, because the information is accurate and
belongs to someone else.
The fix is to make the scope part of the key. An entry is stored under (user, key), and a recall
supplies both. The provider’s memory documentation describes the handler’s mapping in the same
terms: the /memories prefix maps to real storage “such as a per-user directory or keys in a
database” (Anthropic, Memory tool). A per-user directory is scope as a folder; a database key is
scope as a column. A second way to see it: a shared office filing cabinet where every drawer is
labelled with a person. Without labels the filing still works; the retrieval does not.
Scope is also what the identity and access chapter (Chapter 6) depends on. When more than one agent shares a store, “which agent may read or write which scope” is the access question, and it is much easier to answer if the entries were scoped from the start.
What must not be written, and what the handler must refuse
The agent decides what to write, but your handler does the writing, so your handler is the place for rules. The memory tool’s documentation lists safeguards that are the application’s responsibility. Sensitive information: “Claude usually refuses to write sensitive information to memory files. For stronger guarantees, add validation that strips sensitive data before your handler writes the file.” File size: “Track memory file sizes and cap how large a file can grow.” And paths: “A malicious path such as /memories/../../secrets.env can reach files outside the /memories directory. Your implementation must validate every path in every command to prevent directory traversal attacks” (Anthropic, Memory tool).
Notice the wording “usually refuses”. A rule that holds most of the time is a behavior; a rule that the handler enforces on every write is a guarantee. Put the rule where it is enforced in code.
Choosing where a fact goes
| The fact is… | Example | Put it in | Why |
|---|---|---|---|
| Needed for this task only, short | The error line just returned by a tool | The window | It is cheap now and useless later |
| Needed later in this task, but its raw form is bulky | Forty raw log results | A note, then clear the raw results | The conclusion is small; the raw output is the cost |
| Needed in a later session | The customer’s current plan | The store, with a scope and an expiry | The window will not exist next session |
| An exact identifier the thread depends on | An order number | Pinned verbatim, or in the store | A summary can drop it |
| Sensitive | A card number | Not stored, or stripped by the handler | Storage keeps it as long as the store lives |
Three situations you will meet, and what they mean for your design
Before the table, three situations:
- A QA engineer notices that after a long chat the agent asks the user for the order number they gave at the start. The conversation was compacted at turn 40.
- A backend engineer ships a notes file for the agent. Two weeks later the agent keeps proposing a deprecated endpoint that was in a note it wrote on the first day.
- A DevOps engineer lets two tenants use one memory directory. A tenant reports seeing another tenant’s hostname in an answer.
| What you see | What the design allowed | What to do instead |
|---|---|---|
| The agent asks again for a fact it was told (situation 1) | Compaction dropped an exact identifier | Pin identifiers, or store them as entries, and test what survives compaction |
| An old fact keeps being used (situation 2) | No supersession or expiry rule | Newest write wins, give entries an expiry, and delete what is retired |
| One tenant sees another’s data (situation 3) | Entries not scoped by owner | Key every entry by scope and require the scope on every recall |
Flashcards
Say the answer aloud before revealing it. Speaking it is what exposes the gaps that reading past a written answer hides.
Where does an agent's "memory" physically live?
In what reaches the model in the current request: history your application sends again, entries your application reads from its own storage, or state a provider replays. The model keeps nothing between requests on its own.
What does compaction do, and what is its main risk?
It summarizes a conversation that is nearing the window limit and starts a new window with the summary. The risk the provider names is that overly aggressive compaction can lose subtle but critical context whose importance appears only later.
What is tool-result clearing, and why is it a light touch?
It removes the raw output of tool calls made deep in the history. The provider calls it one of the safest lightest touch forms of compaction, because once the agent has used a result it rarely needs the raw text again.
What are structured notes?
Notes the agent writes to storage outside the context window and pulls back into the window at later times. A to-do list or a NOTES.md file are the examples the provider gives.
With the memory tool, who actually reads and writes the files?
Your application. The tool is client-side: the model requests an operation and your handler runs it against storage you control and returns the result.
A store has plan=basic at turn 2 and plan=pro at turn 9. Under this chapter's write rule, what does recall return?
pro. The newest write wins. The turn-2 entry stays in the log as superseded, and asking what was true as of turn 5 would still return basic.
An entry written at turn 6 has a limit of 10 turns. Is it recalled at turn 16? At turn 17?
At turn 16 yes: 16 - 6 = 10, which is not more than 10. At turn 17 no: 17 - 6 = 11.
Why must an entry's scope be part of its key?
With a lookup by key alone, one user’s write can supersede or be returned for another user. Keying by scope means a recall for one owner cannot return another owner’s entry.
Why put sensitive-data stripping in the handler instead of trusting the model to refuse?
The documentation says the model usually refuses to write sensitive information; “usually” is not a guarantee. Code in the handler runs on every write, so the rule holds each time.
What must a memory handler do with a path such as /memories/../../secrets.env?
Validate every path in every command, so that anything resolving outside the /memories directory is rejected. The documentation names this as directory traversal.
Model answer
The question: “Our support agent quoted a customer’s old plan after they upgraded. Walk me through how agent memory works and how you stop that class of bug.” This is the question a lead engineer asks after an incident like this one. A strong answer hits five beats, in this order:
- Place — the model keeps nothing between requests; memory is the window, a store or notes, and with a client-side memory tool the store is your application’s.
- Shrink — the window is limited, so compaction and clearing reduce it, and each can lose something that mattered.
- Freshness — a newer write supersedes an older one, and entries expire.
- Scope — every entry belongs to an owner and every recall names one.
- Guard — the handler enforces what may be written, on every write.
“The model keeps nothing between requests. What looks like memory is either history we send again, entries our application reads from a store and puts in the request, or state a provider replays, and with a client-side memory tool the store and its rules are ours. Because the window is limited, we shrink it: compaction summarizes, and clearing drops old tool results. Both can lose a detail that matters later, so identifiers are pinned or stored as entries. In the plan incident, the store had two plan entries and the lookup returned the first. The fix is a write rule: the newest write wins, the older entry is kept as superseded, and entries carry an expiry so that facts nobody rewrites do not live forever. Each entry is scoped to a user and a recall names the user, so one customer’s data cannot answer for another. And the handler, not the model, enforces what may be stored: it strips sensitive data and rejects paths outside the memory directory, on every write.”
Missing a beat is a failure state. Without place, “memory” is magic and nobody owns it. Without shrink, a long task fails at the window or the answer degrades before it. Without freshness, the agent confidently answers from a stale fact. Without scope, one user’s data answers for another. Without guard, a rule that the model follows most of the time is treated as one that always holds.
Why this matters
- Correctness. A stale or lost fact produces a fluent wrong answer, which is harder to notice than an error.
- Privacy. A store with no scope on its entries is a data leak waiting for the second user.
- Cost and quality. A window that fills with raw tool output costs more to send and, per the provider’s write-up, is harder for the model to recall from.
- Talking to customers. When a customer asks “what does the assistant remember about me, and for how long?”, the answer is in your store, scope and expiry rules, and you can show it.
After this chapter
The project for this chapter is Give the Agent a Memory You Can Test (project.md). You will write
a memory store with a write rule, a compaction function with a fixed rule, a scoped recall with
expiry, and a memory policy for one agent of your own.
Chapter 5 starts from the memory policy you write in the last task. It turns to workflows that run for a long time, and the policy’s scopes decide which entries each step may read and write.
Project
Hands-on Project — Give the Agent a Memory You Can Test
Objective
Build a small memory store, a compaction function, a scoped recall with expiry, and a memory policy for one agent of your own, so that for each of them you can say exactly what the agent will recall and check it against a stated value.
What this project needs: Python 3 and nothing beyond its standard library. No task needs an account with a model provider, an API key or any payment, and no task calls a model: the conversations and events are fixed data given below. All four tasks are required.
Your evidence file. Keep one plain-text file, chapter4-evidence.txt. Each task tells you which
lines to add. Every line has the form key: value, one per line, with the key in lower case exactly
as printed. Write what your code printed, not what you expected it to print. Where a value is
missing, write the word none.
Task 1 — A memory store with a write rule
Write a small class, Memory, that keeps an append-only log. Each log entry is a turn number, an
operation (write or delete), a key and a value. It needs three methods:
write(turn, key, value)anddelete(turn, key), which append to the log and never change an earlier entry.recall(key), which returns the value from the newest log entry for that key if that entry is a write, andNoneif the newest entry is a delete or the key has no entries.recall_as_of(key, turn), which does the same but considers only entries whose turn is at mostturn.
Replay these events, in order, into a fresh Memory:
EVENTS = [
(1, "write", "plan", "basic"),
(2, "write", "region", "eu"),
(3, "write", "contact", "email"),
(5, "write", "plan", "pro"),
(6, "write", "region", "us"),
(8, "write", "contact", "phone"),
(9, "delete", "region", None),
]
A live key is a key whose recall is not None once all events are replayed. A write entry is
superseded if any later log entry (a write or a delete) exists for the same key.
Add to your evidence file, writing the word none where the code returns None:
t1_log_entries: <number of entries in the log>
t1_live_keys: <the live keys, alphabetical, comma-separated>
t1_superseded_count: <number of superseded write entries>
t1_recall_plan: <recall("plan")>
t1_recall_region: <recall("region")>
t1_asof_plan_4: <recall_as_of("plan", 4)>
t1_asof_region_7: <recall_as_of("region", 7)>
t1_asof_region_1: <recall_as_of("region", 1)>
Output: one class with three methods, and eight evidence lines.
Task 2 — Compaction with a fixed rule
One provider’s write-up says that in its coding tool compaction works by “passing the message
history to the model to summarize and compress the most critical details” (Anthropic, Effective
context engineering for AI agents). Here you use a fixed rule instead, so that what survives can be tested. Write compact(messages, budget), where each message is (id, text, pinned) and a message’s
word count is len(text.split()). If the total word count is at most budget, return the messages
unchanged. Otherwise return a new list in this order: first one marker line, then the messages that
are kept, in their original order. A message is kept if it is pinned or if it is one of the last
two messages; all other messages are dropped. The marker line is exactly
[summary: N earlier messages dropped], where N is the number of dropped messages, and it counts
as one message with 5 words for the purpose of the word total.
Run it on this conversation with a budget of 40:
MESSAGES = [
(1, "User says the order number is A-1041 and the parcel is late.", True),
(2, "Agent greets the user and asks how it can help today.", False),
(3, "Agent looks up A-1041 and finds it shipped on the third.", False),
(4, "User says thanks and asks about the refund policy for late parcels.", False),
(5, "Agent states the refund policy applies after seven days.", False),
(6, "User asks to refund order A-1041 now.", False),
]
Add to your evidence file:
t2_words_before: <total words before compaction>
t2_dropped_count: <number of dropped messages>
t2_kept_ids: <ids of the kept messages, ascending, comma-separated>
t2_words_after: <total words after, counting the marker line as 5>
t2_summary_line: <the marker line, exactly>
t2_order_number_survives: <yes if the text A-1041 appears in any kept message, else no>
t2_shipped_survives: <yes if the word shipped appears in any kept message, else no>
Stop at the fixed rule: no model call, no second pass.
Output: one function, and seven evidence lines.
Task 3 — Scoped recall with expiry
Write recall(user, key, now) over this list of entries, each (user, key, value, turn_written, ttl):
ENTRIES = [
("ana", "address", "12 Oak St", 1, 50),
("ben", "address", "9 Elm Rd", 2, 10),
("ana", "address", "40 Pine Ave", 6, 10),
("ana", "pref", "dark", 3, 5),
("ben", "pref", "light", 4, 3),
]
The rules, in order: consider only entries for that user and key that were written at or before
now. If there are none, return None. Take the one with the newest turn_written. Return its
value if now - turn_written <= ttl; otherwise return None. The rule never falls back to an older
entry.
Evaluate these six queries, numbered 1 to 6, as (user, key, now):
QUERIES = [
("ana", "address", 7), # 1
("ben", "address", 7), # 2
("ana", "pref", 8), # 3
("ben", "pref", 8), # 4
("ana", "address", 17), # 5
("carol", "address", 7), # 6
]
Add to your evidence file, writing none where the code returns None:
t3_q1: <result of query 1>
t3_q2: <result of query 2>
t3_q3: <result of query 3>
t3_q4: <result of query 4>
t3_q5: <result of query 5>
t3_q6: <result of query 6>
Output: one function, and six evidence lines.
Task 4 — A memory policy for your own agent
Pick one agent you would really build (a support agent, an on-call helper, a code-review bot).
Write a file, memory-policy.json, with a list of exactly five facts the agent could learn while
working. Each fact is an object with four keys:
fact: a sentence describing the fact.class: one ofpersist(keep in a store across sessions),summarize(keep only inside a compacted summary) ordiscard(do not keep).ttl_turns: for apersistfact, a whole number of turns of at least 1; for the other two classes,null.scope: one ofuser,teamorglobal.
Use at least one fact of each class and at least one with scope user. Check your own file against
those rules before you record it.
Add to your evidence file one line per fact, in the order they appear in your file, with the three
fields joined by a vertical bar and no spaces: class, ttl_turns (the number, or the word null)
and scope. For example, a line for a fact kept across sessions for one user looks like
persist|30|user; a discarded team fact looks like discard|null|team. The sentences themselves
are not recorded.
t4_fact_1: <class|ttl_turns|scope>
t4_fact_2: <class|ttl_turns|scope>
t4_fact_3: <class|ttl_turns|scope>
t4_fact_4: <class|ttl_turns|scope>
t4_fact_5: <class|ttl_turns|scope>
Output: memory-policy.json and five evidence lines.
What carries forward
Keep memory-policy.json, your Memory class and chapter4-evidence.txt. The next chapter opens with
the memory policy from Task 4: it gives work to more than one agent, and the scopes in your policy
decide which agent may read and write which entries.
TechEazy Consulting training material — not affiliated with or endorsed by OpenAI, Anthropic or any other company named in this course.