← All guides

Claude API Loses Context After Compaction: Round-Trip the Block

Your agent works for many turns, crosses the compaction point, and suddenly acts as if the earlier task never happened. The API created the summary. Your message loop threw it away.

Bottom line

  • Claude returns compaction state as a content block.
  • Saving only block.text deletes that state.
  • Append the complete response.content array to your message history.
  • Test the boundary with a low development trigger and inspect block types.

Anthropic’s compaction documentation says clients must pass the compaction block back on later requests. It recommends appending the entire response content. The page was checked on August 20, 2026.

The symptom

The agent keeps its instructions and tool state for many turns. Then its behavior changes near the context limit:

  • It asks for information already supplied.
  • It repeats completed work.
  • It forgets the current acceptance criteria.
  • It stops referring to an earlier tool result that the summary should preserve.

The API call still succeeds. There is no context-window error.

The cause

Compaction replaces older history with a summary inside a compaction content block.

Many message loops keep only visible text:

# Wrong: discards compaction and other non-text blocks.
assistant_text = "".join(
    block.text for block in response.content
    if block.type == "text"
)
messages.append({"role": "assistant", "content": assistant_text})

That code works until the API returns a non-text block that carries state. The next request contains readable prose but no compaction summary.

The model did not forget the state. The client removed it.

The fix

Append the full content array:

messages.append({
    "role": "assistant",
    "content": response.content,
})

In TypeScript:

messages.push({
  role: 'assistant',
  content: response.content,
});

Do not serialize each block into a custom text format. Preserve the typed objects that the SDK returned.

Add a boundary test

Log only block types, not private content:

print([block.type for block in response.content])

When compaction occurs, the output includes compaction before later response blocks.

Add an assertion to your loop test:

returned_types = [block.type for block in response.content]

if "compaction" in returned_types:
    messages.append({"role": "assistant", "content": response.content})
    saved_types = [block.type for block in messages[-1]["content"]]
    assert "compaction" in saved_types

The test proves that your storage layer did not flatten the response.

Check every storage boundary

The in-memory append can be correct while persistence still breaks it.

Inspect these points:

  1. The SDK response object.
  2. The object written to your database or session file.
  3. The object loaded for the next request.
  4. The final messages payload.

At each point, the compaction block must remain typed and unchanged.

Do not patch the symptom with a larger context window

A larger window delays the boundary. It does not fix a message loop that deletes state.

Repair the round trip first. Then choose a compaction trigger that matches the workload.

Your agent survives short tests but loses the task overnight?

Book an agent rescue session. We inspect the stored message blocks at the failure boundary.

Need OpenClaw fixed live?

Remote rescue sessions for gateway, auth, tunnel, VPS, and model access problems.

See Rescue Session

Read next

Claude API Returns 400 on the Next Turn: Preserve Thinking Blocks
The first thinking request works, but the next returns 400. Pass thinking blocks back unchanged instead of trimming or rebuilding them.
Can You Use Your Claude or ChatGPT Subscription With OpenClaw and Hermes? What the Rules Actually Say (July 2026)
A video says you can't. A top comment says you can. Here is what is actually settled: API keys work everywhere, consumer subscription auth is the contested path Anthropic has enforced against, and local models have no rules at all.
Anthropic Banned OpenClaw Integrations: The Supply-Risk Case for Self-Hosting Your Agent Runtime
Anthropic just banned certain OpenClaw integrations. If your agent runtime sits on a single cloud provider, it can be yanked overnight. Here is the supply-risk case for self-hosting.
Your Prompt Cache Isn't Working and You're Paying Full Price
Cache hits stay at zero and every request bills full input cost. Usually the cached prefix is under ~1024 tokens, or you have more than 4 breakpoints.