To keep recent messages intact during context compaction, exclude them from the text being summarized. Compact only the older completed conversation, then continue with the summary followed by the original recent message records and the current request.
This requires control over the application’s conversation history or a documented retention feature. A prompt asking a hosted chat to “remember everything exactly” cannot guarantee how that product manages its context internally.
Preserve the records, not a description of them
A summary can retain a decision while losing its exact wording, an identifier or the correction that followed it. If the next action depends on the precise recent exchange, preserving only its meaning is the wrong objective.
For an application you control, use two different operations: summarize the older portion and copy the retained portion without rewriting it. Keep roles, content blocks, ordering and tool identifiers attached to those records. Do not turn a structured exchange into an unlabeled paragraph and call that exact retention.
My recommendation is to keep the latest complete task exchange before deciding how many additional turns to retain. A count is useful as a budget control, but it should not cut through a correction, an unfinished tool cycle or an instruction that the next step needs.
Keep the full transcript separately when your application’s retention policy permits it. Compacted working context serves the next model request; an archival transcript serves recovery and exact lookup. One should not be mistaken for the other.
Choose a boundary where the conversation is complete
Do not split by an arbitrary number of messages alone. One user turn can involve several assistant tool calls and results before a final reply. Your application needs a boundary that respects the provider’s protocol and the workflow’s current state.
A safe design groups completed exchanges before choosing what to retain. Finish an active tool cycle before compacting it, or use a documented mechanism that supports pausing and resuming that cycle. If you cannot establish that the boundary is valid, postpone compaction rather than dropping a result to make the count fit.
For example, keeping an assistant request to fetch a file while summarizing away its matching result can leave the retained history structurally incomplete. Keeping the result without its call can be equally problematic. A generic “last five messages” slice does not understand that relationship.
Multimodal content needs the same care. Retaining a message that references an image is different from retaining the image block or a still-accessible attachment reference. Check whether the preserved record still carries everything the next request needs.
A minimal partition function for your own application
The example below partitions already grouped, completed turns. It makes a separate copy of the records and returns older messages for summarization plus recent messages to retain. It does not call an API, count tokens or validate tool protocols.
from copy import deepcopy
def split_completed_turns(turns, keep_turns=2):
"""Partition prevalidated, atomic completed-turn groups.
Each group is a list of original provider message records.
The caller must keep tool cycles together and exclude in-flight work.
"""
if type(keep_turns) is not int or keep_turns < 1:
raise ValueError("keep_turns must be a positive integer")
snapshot = deepcopy(turns)
cut = max(0, len(snapshot) - keep_turns)
older = [message for turn in snapshot[:cut] for message in turn]
recent = [message for turn in snapshot[cut:] for message in turn]
return older, recent
Supply each turn group as a list of original provider message records, with tool calls and results grouped correctly. The default of two groups is illustrative, not a universal retention recommendation. An application processing a large tool response may need a different budget than a short text conversation.
Send only the returned older portion to your chosen summarization mechanism. If that portion is empty, skip compaction. The recent portion is the protected tail; do not feed it through the summarizer and then expect to reconstruct it from the summary.
Before appending the current request, establish whether it is already included in your history snapshot. Add it exactly once. Duplicating the newest correction can be confusing, while omitting it can make the next reply continue an obsolete plan.
This helper is ordinary Python application logic, not a provider-specific request builder. Keep the original schema and follow your API’s documented rules when constructing the actual continuation.
Use the provider’s compaction format correctly
Claude’s documented recent-turn retention workflow uses on-demand compaction for the older portion, then places the returned compaction block before the retained turns. There is no single parameter on that workflow that selects the tail for you; the application chooses the cut.
The on-demand API returns a signed compaction block. Replay that block as returned rather than editing its text or manufacturing an equivalent-looking object. Check model support and the required beta header for the deployed API version before implementing the flow.
Retained thinking blocks can have additional validity conditions, including matching system instructions and tool definitions. Preserve supported blocks through the documented continuation path; copying visible assistant text alone is not equivalent to replaying the complete provider record.
Threshold-triggered compaction is a different control path. Its pause-and-resume options can support application-managed retention, but do not assume the default automatic flow leaves your preferred recent exchange untouched. Choose one documented approach and implement its continuation rules deliberately.
I would keep provider-specific handling behind a small adapter in the application. The general policy can stay the same—older summary plus exact recent records—while each adapter controls its own block placement, capabilities and validation.
Budget the retained tail before compaction starts
Exact retention saves no space for the retained portion itself. A very large recent attachment, log or tool output can still dominate the next request. Keeping more turns is therefore a trade-off, not an automatic improvement.
Budget for the summary, retained records, current request, system guidance, tool definitions and expected output or reasoning allowance. Use the provider’s supported token-counting method where available. A fixed message count cannot predict the size of arbitrary content.
Preserve the selected complete turns and summarize the older portion. Validate the resulting request size before sending it.
Choose an earlier safe compaction point, reduce the scope of future tool output or move bulky reference material to retrievable storage.
If the requirement is truly verbatim retention, silently shortening the protected messages is not a valid fallback. Return a clear budget problem to the workflow and choose a supported alternative instead.
My preference is to compact before the application reaches its absolute limit. That leaves room to write the summary and validate the continuation, rather than discovering that even the recovery request is too large.
Keep durable instructions outside a fragile summary
The retained tail protects recent conversation, not every long-term requirement. A rule supplied much earlier may still be important after the immediate exchange has moved outside the retention window.
Store durable guidance through the application’s supported instruction mechanism, and keep task state distinct from standing project conventions. The sister site’s project instruction checks explain how loading, scope and conflicting rules can look like a memory problem.
A useful summary should identify the current goal, accepted decisions, unresolved work and references needed for the next step. Keep superseded choices labeled as superseded. Otherwise, a summary can preserve both an old instruction and its correction without making their relationship clear.
Do not repeatedly summarize the previous summary when the original relevant records remain available and your architecture allows refreshing from them. Recheck important state against its authoritative source rather than allowing a shorthand note to become the only evidence.
Validate the candidate before replacing active history
Treat compaction as a transaction: build a candidate context, check it, and commit only when it passes. Keep the previous usable state available until then.
| Check | What it catches |
|---|---|
| Retained record equality | Changed text, missing blocks or reordered content. |
| Tool-cycle completeness | A call and result separated by the boundary. |
| Current request count | A duplicated or omitted new instruction. |
| Continuation validity | Incorrect provider block placement or unsupported schema. |
For structured records, compare the protected content and metadata with the snapshot. If byte-for-byte identity of a stored payload is required, retain and verify those original bytes as well; reserializing a dictionary can change representation even when its values are equal.
Add cases for an empty older portion, a large recent turn, a tool cycle near the boundary and a correction immediately before compaction. Test more than one successive compaction so that the second transition does not accidentally summarize or duplicate the protected tail.
A natural-language question such as “what was my last instruction?” can supplement these checks, but it cannot prove exact preservation. Compare the actual input assembled for the next request.
What to do when you only use a hosted chat
If you do not control the application’s message construction, the partition function is not a setting you can install into that chat. Look for documented export, handoff or retention features rather than assuming an API workflow is available in the user interface.
Before a long session becomes difficult to manage, save exact text that must remain unchanged and a short task handoff. Provide the relevant original material again when needed. This can improve continuity, but it does not guarantee that a hosted service will preserve a chosen context segment indefinitely.
Keep the handoff factual: current goal, latest accepted correction, completed work and next action. Avoid copying an entire stale conversation when only one precise instruction and a current artifact are needed.
Frequently asked questions
Does a “keep” setting always protect recent chat messages?
No. In Claude context editing, a keep option can refer to recent tool-use pairs rather than a verbatim conversational tail. Read the setting’s scope before relying on it.
Can summary instructions guarantee exact wording?
They can request preservation, but exactness is better established by excluding the protected records from summarization and comparing them afterward.
Should I retain every message forever?
Keep a suitable archive if permitted, but distinguish it from active model context. Replaying the entire archive defeats the purpose of compaction and may exceed the input budget.
What is the first practical change to make?
Identify the latest complete exchange that must remain exact. Snapshot it, choose a valid boundary before it, and verify that the next request contains those same records unchanged.