TAI BUI
Back to curriculum
BuildPython

Memory Blocks and Sleep-Time Compute (Letta)

MemGPT became Letta in 2024. The 2026 evolution adds two ideas: discrete functional memory blocks the model can edit directly, and a sleep-time agent that consolidates memory while the primary agent is idle. Together they let memory scale beyond a single conversation.

TIME: ~75 minutesPREREQUISITES: Phase 14 · 07 (MemGPT)

Learning Objectives

  • Name the three memory tiers Letta uses (core, recall, archival) and the role of each.
  • Explain the memory-block pattern: Human block, Persona block, and user-defined blocks as first-class typed objects.
  • Describe what sleep-time compute is, why it sits off the critical path, and why it can run a stronger model than the primary agent.
  • Implement a scripted two-agent loop where a primary agent serves responses and a sleep-time agent consolidates blocks between turns.

The Problem

MemGPT (Lesson 07) gave us the virtual-memory control flow. Running it in production surfaced three problems:

  1. Latency. Every memory operation sits on the critical path. If the agent has to prune, summarize, or reconcile while the user waits, tail latency blows up.
  2. Memory rot. Writes accumulate and nothing cleans up. Contradicted facts stay put, and retrieval drowns in stale content.
  3. Structure loss. A flat archival store can't express "the Human block is always in the prompt, the Persona block is always in the prompt, and the Task block swaps per session."

Letta (letta.com), the project MemGPT became in 2024, answers these. Memory blocks make the structure explicit. Sleep-time compute moves consolidation off the critical path.

Warm-up0/3
1. In a MemGPT-style agent, which part of memory sits inside the prompt on every turn?Warm-up
2. An agent must summarize and prune its memory before it can reply. What does the user notice?Warm-up
3. A web endpoint is slow because it runs a heavy cleanup job during every request. What is the usual fix?Warm-up
Check: The Problem0/1
1. Why does memory rot happen when writes accumulate and nothing cleans up?Explain

The Concept

A memory block is a typed, persistent, editable section of an agent's always-visible memory. Sleep-time compute is a second agent that rewrites that memory in the background while the primary agent is idle. The rest of this section covers both, starting with where blocks live.

Three tiers

TierScopeWhere it livesWritten by
CoreAlways visibleInside the main promptAgent tool call + sleep-time rewrites
RecallConversation historyRetrievableAutomatic turn logging
ArchivalArbitrary factsVector + KV + graphAgent tool call + sleep-time ingest

Core is the MemGPT core. Recall is the conversation buffer with its evicted tail. Archival is the external store. Splitting them out fixes the overloading MemGPT had with only two tiers.

Memory blocks

A block is a typed, persistent, editable section of the core tier. The original MemGPT paper defined two:

  • Human block: facts about the user (name, role, preferences, goals).
  • Persona block: the agent's self-concept (identity, tone, constraints).

Letta generalizes this to arbitrary user-defined blocks: a Task block for the current goal, a Project block for codebase facts, a Safety block for hard constraints. Each block has an id, a label, a value, a limit (character cap), and a description so the model knows when to edit it.

The model edits blocks through the tool surface:

  • block_append(label, text)
  • block_replace(label, old, new)
  • block_read(label)
  • block_summarize(label): condense a block that is near its limit.

Sleep-time compute

Sleep-time compute, a 2025 Letta addition, runs a second agent in the background, off the critical path. Sleep-time agents process conversation transcripts and codebase context, write learned_context into shared blocks, and consolidate or invalidate archival records.

Three properties fall out of that:

  • No latency cost. Primary responses never wait on memory operations.
  • Stronger model allowed. Nothing is waiting on the sleep-time agent, so it can be a slower, more expensive model.
  • A natural consolidation window. Dedup, summarize, and invalidate contradicted facts while the user isn't waiting.

It matches how people work: you do the task, you sleep on it, and long-term memory settles overnight.

Letta V1 and native reasoning

Letta V1 (letta_v1_agent, 2026) drops send_message/heartbeat and inline Thought: tokens in favor of native reasoning. The Responses API (OpenAI) and the Messages API with extended thinking (Anthropic) emit reasoning on a separate channel, passed through turns (encrypted across providers in production). The control loop is still ReAct. The thought trace is just structural now instead of prompt-shaped.

Where this pattern goes wrong

  • Block bloat. Unbounded block_append hits the limit fast. Wire in a block summarizer that runs before any write that would push the block over the cap.
  • Silent drift. The sleep-time agent rewrites a block and the primary agent never notices. Version your blocks and surface the diffs in the trace.
  • Poisoned consolidation. If the sleep-time agent processes attacker-reachable content into core, the attacker gets a persistent foothold. Lesson 27 applies to the sleep-time surface too.
Check: The Concept0/25
1. What is a memory block?Define
2. What does the Human block hold?Define
3. What is the Persona block for?Define
4. What is sleep-time compute?Define
5. What does a block's limit control?Define
6. What is learned context?Define
7. What are Letta's three memory tiers?Define
8. Which property is NOT a memory block field in Letta?Define
9. What replaced inline `Thought:` tokens and the send_message/heartbeat pattern in Letta V1?Define
10. What does block_summarize do in Letta's memory-block tool surface, per the lesson?Define
11. Which tier is filled by automatic turn logging rather than by an agent tool call?Define
12. What is the description field on a block for?Define
13. What pattern do the Human and Persona blocks generalize to?Define
14. What does the lesson's poisoned consolidation pitfall describe?Define
15. Why does Letta split memory into core, recall and archival instead of keeping MemGPT's two tiers?Explain
16. What does the consolidation window let the system do that is awkward during a live turn?Explain
17. Why can the sleep-time agent run a stronger model than the primary?Explain
18. What is silent drift in this pattern?Explain
19. What is block bloat, and how does the lesson say to prevent it?Explain
20. In Letta V1, what stays the same after native reasoning replaces inline Thought tokens?Explain
21. Users report slow replies after long chats because the agent summarizes blocks inline. Which change fits this lesson?Analyze
22. An operator asks why the agent no longer knows the user's city, and nobody can say which write removed it. What was missing?Analyze
23. A support agent's sleep-time pass reads inbound customer emails and writes learned_context into the core Safety block. Soon the primary agent follows odd rules no operator wrote. Which failure fits?Analyze
24. You must reconcile thousands of contradictory archival notes each night with an expensive model, without raising reply latency. Which design fits?Design
25. A sleep-time agent will now read untrusted web content. Which rule should govern its edits to the Persona and Safety blocks?Design

Build It

code/main.py implements:

  • Block: id, label, value, limit, description, plus a near_limit() check.
  • BlockStore: creates blocks and looks them up by label.
  • Two scripted agents: PrimaryAgent serves a turn, SleepTimeAgent consolidates between turns.
  • A trace of a four-turn conversation with block writes, followed by a sleep-time pass that invalidates a stale fact. The pass also summarizes any block at 80 percent of its limit, but no block gets that full in this trace.

Run it:

python3 code/main.py

The example does not expose block_summarize as a tool. Summarization runs inside the sleep pass, and Exercise 1 asks you to add it as a tool the primary agent can call.

The transcript shows the split. Primary turns are fast and leave raw writes behind. The sleep pass cleans up after them.

Check: Build It0/6
1. In main.py the human block (limit 180) gets 'name=ava role=ships_agents city=Berlin' (38 characters) on turn 1 and 'city=Lisbon (updated from Berlin)' (33 characters) on turn 3. What does the second append return?Apply
2. The task block in main.py has limit 220 and holds 119 characters when the sleep pass runs. near_limit uses its default threshold of 0.8. What happens to the block?Apply
3. In main.py the sleep pass runs with the claim 'ava lives in Berlin'. Archival holds a001 'ava prefers concise, citation-heavy writing over tutorial-style' and a002 'ava lives in Berlin - old address, outdated'. Which records end up invalid?Apply
4. A Block in main.py has limit 160 and a value of exactly 128 characters. What does near_limit() return with the default threshold?Apply
5. A persona block in main.py is empty. What happens when block.replace('formal', 'casual') is called on it?Apply
6. After the sleep pass in main.py the human block still reads 'city=Berlin city=Lisbon (updated from Berlin)'. Which explanation fits the code?Analyze

Use It

  • Letta (letta.com) is the reference implementation. Self-host it or use the managed cloud.
  • Claude Agent SDK skills work as block-shaped knowledge. A skill is a named, versioned, retrievable block of instructions the agent loads on demand.
  • Custom builds make sense when you need control over the storage backend. Follow the Letta API contract so you can migrate later.
Check: Use It0/1
1. How does the Use It section frame Claude Agent SDK skills relative to Letta's memory blocks?Define

Ship It

outputs/skill-memory-blocks.md generates a Letta-shaped block system with sleep-time hooks for any runtime, including safety rules and citation wiring.

Author's Note

The design choice I'd defend hardest is that the sleep-time agent is a separate writer, and you should treat it like one. Consolidation feels like housekeeping, harmless because nobody is waiting on it. But it's the only process that rewrites core memory while nobody is watching, which makes a bad rewrite the hardest kind to catch. Version your blocks from day one and put the diffs in the trace. When an agent "forgets" something, the first question is always which write removed it, and without history you're guessing.

Exercises

  1. Add the block_summarize tool from the Letta surface (the example only summarizes in the sleep pass). It replaces the block value with a model-generated summary when near_limit returns true. Which trigger threshold minimizes both summarization calls and block overflow?
  2. Implement sleep-time dedup over archival: two records whose text has >90% token overlap collapse to one. Do it only in the sleep pass, never on the critical path.
  3. Version blocks. On every write, record the old value and a diff. Expose block_history(label) so operators can debug "why did the agent forget X."
  4. Treat sleep-time agents as untrusted writers. When one touches the Persona or Safety block, require a second-agent review before committing.
  5. Port the example to the Letta API (letta_v1_agent). What changes in the block schema, and how does native reasoning alter the trace shape?

Key Terms

TermWhat people sayWhat it actually means
Memory block"Editable prompt section"Typed, persistent, LLM-editable segment of core memory
Human block"User memory"Facts about the user, pinned in core
Persona block"Agent identity"Self-concept, tone, constraints, pinned in core
Sleep-time compute"Async memory work"Second agent doing consolidation off the critical path
Core / Recall / Archival"Tiers"Three-layer memory split: always-visible / conversation / external
Block limit"Cap"Character limit per block; forces summarization
Native reasoning"Thinking channel"Provider-level reasoning output, not prompt-level Thought:
Learned context"Sleep output"Facts the sleep-time agent writes into shared blocks

Further Reading

Code

Ships With