# What Should an Agent Remember?

<details data-node-type="hn-details-summary">
<summary><strong>In this article · 6 min read</strong></summary>
<ol><li><p><a target="_self" rel="noopener noreferrer nofollow" class="cursor-pointer" href="#section-1" style="pointer-events: none;">Start with four responsibilities</a></p></li><li><p><a target="_self" rel="noopener noreferrer nofollow" class="cursor-pointer" href="#section-2" style="pointer-events: none;">Recover a crashed worker from revision 7</a></p></li><li><p><a target="_self" rel="noopener noreferrer nofollow" class="cursor-pointer" href="#section-3" style="pointer-events: none;">Treat summaries as views</a></p></li><li><p><a target="_self" rel="noopener noreferrer nofollow" class="cursor-pointer" href="#section-4" style="pointer-events: none;">Checkpointing does not make external effects atomic</a></p></li><li><p><a target="_self" rel="noopener noreferrer nofollow" class="cursor-pointer" href="#section-5" style="pointer-events: none;">Build the next context deliberately</a></p></li><li><p><a target="_self" rel="noopener noreferrer nofollow" class="cursor-pointer" href="#section-6" style="pointer-events: none;">Evaluate memory by what it preserves</a></p></li></ol>
</details>

A worker restarts halfway through a ticket update. Its conversation summary says the change is underway. Its last tool response is missing. Should it submit the update again?

More conversation history cannot resolve that question reliably. The runtime needs the original operation ID and a durable record of where execution stopped.

This article separates the information a model needs to reason from the state an application needs to recover. The running example resumes a fictional ticket task from checkpoint revision 7.

## Start with four responsibilities

For our illustrative ticket agent, I would separate memory into four stores:

| Store | Purpose | Example |
| --- | --- | --- |
| Conversation | Understand the current interaction | User clarified the target team |
| Durable task state | Resume and verify execution | Step 3 submitted; operation ID recorded |
| Retrieved evidence | Supply relevant external facts | Versioned support policy passage |
| Event history | Explain the execution | Tool request, result, verification event |

These are logical responsibilities. They do not require four database products. The important separation is their authority, retention, and update policy.

An operation ledger is authoritative about what the application attempted. A retrieved page is evidence about its subject. A generated summary is a lossy interpretation. They should not become interchangeable just because they all fit inside a prompt.

## Recover a crashed worker from revision 7

Consider a worker that has already submitted `op-82`. Its conversation summary says “moving the ticket to billing,” but its durable checkpoint says:

```json
{
  "task_id": "move-T-184",
  "revision": 7,
  "next_step": "verify_operation",
  "pending_operation_id": "op-82",
  "required_state": {"queue": "billing", "team_id": "team-billing"},
  "evidence_refs": ["ticket-read:v30"]
}
```

After a crash, the runtime reads this checkpoint first. It asks the operation service what happened to `op-82`, verifies the result, and attempts to advance revision 7 to revision 8. It does not ask the model to infer progress from the transcript.

The checkpoint update can use optimistic concurrency:

```sql
UPDATE task_checkpoints
SET revision = 8,
    next_step = 'report_result',
    pending_operation_id = NULL
WHERE task_id = 'move-T-184' AND revision = 7;
```

Check the affected-row count. Zero rows means no checkpoint matched that task and revision; reload to distinguish a concurrent update from a missing task. This compare-and-swap protects the local state transition. It does not prevent duplicate external actions by itself: operation identity and provider-side idempotency still own that problem.

The diagram separates three inputs to the next model call. Conversation contributes the user's intent. Evidence contributes facts with source versions. The checkpoint contributes the current execution position. The model context is a selected view of those stores, not the durable storage format.

For an illustrative 16,000-token input budget, reserve 2,000 for instructions and tool schemas, 3,000 for recent conversation, 1,000 for current state, and up to 10,000 for evidence. Count with the model's tokenizer and leave the required output allowance under its total context limit. These are allocation choices for this example, not universal ratios.

The serving cost behind this input budget is explained in [The Inference Wall: Where LLM Latency and Cost Go](https://sakshityagi.hashnode.dev/the-inference-wall-where-llm-latency-and-cost-go). A durable checkpoint and an inference KV cache have different jobs: the checkpoint preserves task state, while the KV cache supports model execution. Loading a checkpoint into a longer prompt still creates inference work.

If evidence exceeds its budget, prioritize passages required for the current decision and retain their identifiers. Do not truncate halfway through a qualification just to hit a token target. If the required evidence cannot fit, change the step decomposition or defer the action.

A recovery test can remove every old conversational turn and keep only the current request, checkpoint, and referenced evidence. The worker should still know to verify `op-82`, rather than submit the move again.

![Dataflow separates conversation, checkpoint revision, and evidence; the agent records outcomes in an operation ledger and advances the checkpoint with compare-and-swap.](https://cdn.hashnode.com/uploads/covers/6a42180870a681b0c318a004/75d13cc7-2054-42a6-9019-798c91e99b6a.png align="center")

*Figure 1. Conversation, evidence, and checkpoints have different responsibilities. Durable operation state determines what the worker should recover.*

## Treat summaries as views

A summary can omit a deadline, collapse an unresolved question into a conclusion, or describe a proposed action as completed. Keep important execution facts structured outside the summary.

Keep the checkpoint from the recovery example as the authority: `pending_operation_id=op-82` and `next_step=verify_operation`. A summary may describe those fields, but cannot change their meaning.

The summary helps the model orient itself. The structured fields control recovery. If they conflict, do not let polished prose silently overwrite the execution record.

Anthropic's [work on long-running agents](https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents) illustrates why explicit progress artifacts matter across sessions. The broader design lesson is to make continuation depend on inspectable state, not the model reconstructing an entire history correctly.

## Checkpointing does not make external effects atomic

Suppose the agent updates the ticket and crashes before saving its next checkpoint. On resume, the checkpoint still says the update is pending. Replaying that step can duplicate the action.

The remedy involves the operation identifiers and reconciliation policy from Part 2. A checkpoint is a recovery boundary; it does not automatically create a transaction across your database and someone else's API.

Choose persistence semantics deliberately. A synchronous checkpoint before the next step protects a different failure window from an asynchronous write or an exit-only save. LangGraph's documented [durability modes](https://reference.langchain.com/python/langgraph/types/Durability) make this tradeoff explicit. Your application still owns the semantics of side effects.

## Build the next context deliberately

At each step, assemble a context from the current goal, the minimal relevant task state, recent clarifications, and authorized evidence. Preserve source IDs so the model can distinguish quotations from instructions and refer back to the originals.

Retrieved content should not gain tool authority. A support document containing “close all tickets” is document content, not permission to mutate the application. Apply authorization in code and filter retrieval by the user's access before material enters the model context.

Freshness matters too. A stored policy excerpt should carry its version and retrieval time. A cached tool result may no longer describe the current ticket. Some facts are reusable; some must be read again before acting.

## Evaluate memory by what it preserves

Create controlled resume points and restart the worker at each one. Test whether it preserves the goal, honors corrections, avoids repeating committed effects, and notices stale evidence. Add a deliberately misleading summary to ensure structured state wins.

Measure unnecessary rework, missing constraints, duplicate actions, and recovery success. Token reduction is a useful cost metric, but it cannot tell you whether the right information survived.

Restart the worker immediately after a mutation, then deliberately give it an inaccurate summary. It should recover the original operation ID, reconcile the result, and advance the checkpoint once. That is a more useful memory test than how much history fits in the prompt.

*Next: One Agent or Five? Measure Before You Multiply.*
