Try this first
Look at a long transcript. Find the read_file from turn two.
The model has since edited that file twice. That result is now wrong, and it is still there,
still being resent, still competing for attention with the current state.
Stale results are worse than large ones
Two separate problems, and the second is underrated.
Cost. You pay for it every turn.
Contradiction. The transcript now contains two versions of the same file. The model has to
work out which is current, and sometimes gets it wrong — reporting a function that was
deleted, or re-fixing something already fixed.
Clearing them yourself
The transcript is your list, so this is a function you write. Twelve lines:
def clear_old_tool_results(messages, keep_last=6):
"""Blank out tool results older than the last `keep_last` messages."""
cutoff = max(0, len(messages) - keep_last)
for m in messages[:cutoff]:
if m["role"] == "tool_results":
for r in m["results"]:
r["content"] = "[older result removed to save context]"
return messages
Note what it does not do. It does not delete the message. The turn is still there, the
tool call still happened, only the stale contents are gone.
That distinction matters. The model still knows it read agent.py at turn two. It just no
longer has the old text in front of it, so it re-reads when it needs to — which is exactly the
behaviour you want, because the file has changed since.
Some providers will do it for you
Anthropic has a context-editing feature that clears old tool results server-side:
# Anthropic-specific. Same idea as the function above, done for you.
response = client.beta.messages.create(
model="claude-opus-5",
max_tokens=16000,
betas=["context-management-2025-06-27"],
context_management={"edits": [{"type": "clear_tool_uses_20250919"}]},
tools=TOOLS,
messages=messages,
)
Use it if you are on that provider and it fits. The reason we wrote the function first is that
now you know precisely what such a feature does, and you can decide whether its policy — which
results, how old — is the one you want.
Clearing versus summarising
This is the distinction to keep straight:
| Context editing | Compaction (next lesson) | |
|---|---|---|
| Does what | Deletes old tool results | Replaces old turns with a summary |
| Keeps structure | Yes | No — turns are collapsed |
| Costs | Nothing | A model call to write the summary |
| Loses | The content of old results | Detail, and possibly something important |
| Reach for it | Tool output is your bulk (usually) | The conversation itself is long |
Reach for clearing first. It is cheaper, it is lossless in the sense that matters (the model
can re-read anything it needs), and per Lesson 6.1 tool results are most of your transcript
anyway.
One caution, whichever way you do it
Clearing rewrites part of the transcript, which means it changes the prefix — and Lesson
6.2 just taught you what that does to your cache. Everything after the edit point has to be
processed fresh.
So clear in occasional large batches rather than every turn. Clearing one result per turn is
the worst of both worlds: you save a little context and pay a cache miss every single time,
which usually costs more than you saved.
Clearing removes stale tool output while keeping the shape of the conversation. It is the
first thing to reach for, and it is the cheapest.
Try this before the next lesson
Run a fifteen-turn task, then again with clearing on.
Compare total input tokens and check the answer is still correct. Then look for the moment the
model re-reads a file it had already read — that is the mechanism working, not failing.