Reset Chat History
What Resetting Means
Resetting chat history means discarding some or all of the stored conversation so that the next request starts with less context, or none.
Because the Messages API is stateless (Lesson 21), Claude has no memory of its own to erase. The conversation exists only in the history your application sends. Resetting is therefore entirely under your control: you change the list, and the next request reflects that change.
history = [] # The simplest possible reset
After this, the next request contains only the new user message, so Claude begins a fresh conversation.
Why Reset a Conversation
| Reason | Explanation |
|---|---|
| New topic | Old context about a different subject can distract or confuse the answers to a new question. |
| Cost and speed | Every request resends the whole history. Shorter history means fewer input tokens, lower cost, and faster responses (Lesson 24). |
| Context window limits | Very long conversations approach the model's context window. |
| After a refusal | Anthropic's guidance on refusals recommends resetting the conversation context after a refusal, instead of continuing to build on it (Lesson 25). |
| A conversation that went wrong | If Claude misunderstood something early, the misunderstanding stays in the context. Starting fresh is often faster than correcting it. |
| Privacy | Users may want their conversation removed. A reset in memory is not enough; stored copies must be deleted too. |
Types of Reset
A reset does not have to be all or nothing.
| Type | What is kept | When to use |
|---|---|---|
| Full reset | Nothing from the conversation | A completely new topic, or a fresh start |
| Reset keeping configuration | System prompt and settings, without messages | A normal "New chat" button |
| Partial reset (trim) | Only the most recent turns | Long conversations that only need recent context |
| Reset with summary | A short summary of the old conversation | Long conversations where earlier facts still matter |
| Rollback | Everything except the last exchange or exchanges | Undoing a bad turn, or a refusal |
Full Reset vs. Configuration
The system prompt is not part of messages. It is sent separately with every request (Lesson 17). Clearing history therefore resets the conversation but keeps Claude's role and rules. That is usually what users expect from a "New chat" button.
SYSTEM = "You are a Python tutor."
history = [] # New chat; SYSTEM still applies
client.messages.create(model="claude-opus-5-5", max_tokens=2048,
system=SYSTEM, messages=[{"role": "user", "content": "Hi!"}])
Partial Reset (Trim)
Keep the most recent part of the conversation, making sure it still starts with a user message (Lesson 24):
def keep_recent(history: list[dict], max_messages: int) -> list[dict]:
recent = history[-max_messages:]
while recent and recent[0]["role"] != "user":
recent = recent[1:]
return recent
Rollback
Remove the last exchange, meaning the last user message and Claude's reply:
def rollback(history: list[dict]) -> list[dict]:
if len(history) >= 2 and history[-1]["role"] == "assistant":
return history[:-2]
return history
The len(history) >= 2 and role checks make sure only a complete user/assistant pair is removed.
Reset with a Summary
A full reset loses everything, including useful facts such as the user's name, goals, and decisions already made. A summary reset keeps the important information in a compact form:
- Ask Claude to summarize the conversation so far.
- Clear the history.
- Include the summary in the system prompt for the new conversation.
def summarize_history(client, history: list[dict]) -> str:
request_messages = history + [{
"role": "user",
"content": (
"Summarize our conversation so far in at most 5 bullet points. "
"Keep facts about me, decisions made, and open questions. "
"Reply with only the bullet points."
),
}]
reply = client.messages.create(model="claude-opus-5-5", max_tokens=2048, messages=request_messages)
return "".join(block.text for block in reply.content if block.type == "text").strip()
summary = summarize_history(client, history)
history = []
system = f"{BASE_SYSTEM}\n\n<previous_conversation_summary>\n{summary}\n</previous_conversation_summary>"
Why put the summary in the system prompt: the new conversation must still start with a user message, and the summary is background context, not something the user said. Wrapping it in tags marks it clearly as earlier context.
The trade-off: summarizing costs one extra request, and some detail is lost. In return, every later request is much smaller. Lesson 64 (Add Chat Memory) builds on this technique.
Automatic Resets
Applications can reset automatically when a condition is met:
| Trigger | Example rule |
|---|---|
| Size | The last request used more than 50,000 input tokens: summarize and reset |
| Refusal | A refusal occurred: roll back that turn, or reset completely |
| Inactivity | No message for 24 hours: start a new conversation next time |
| Topic change | The user selects a different course or document: start a new conversation |
Automatic resets keep costs predictable without requiring users to manage history themselves. Tell users when it happens, for example: "Starting a new conversation (summary of the previous one kept)."
Resetting in Web Applications
In web applications, history is stored outside the program, for example in a database (Lesson 25). A reset therefore has two design options:
| Option | How | Advantages |
|---|---|---|
| Start a new conversation record | Create a new row; keep or archive the old one | The user can return to old chats; nothing is lost |
| Clear the existing record | Set history = [] on the same row | Simple; the conversation ID stays the same |
# Django: start a new conversation (old one remains in the user's chat list)
new_conversation = Conversation.objects.create(owner=request.user, history=[])
# Django: clear the current conversation
conversation.history = []
conversation.save(update_fields=["history"])
Reset Is Not Deletion
Clearing the history in memory, or starting a new record, does not remove stored data. If a user asks to delete their conversations, delete them from every place they are stored, such as the database rows, cached copies, and logs that contain message text, according to your data-retention policy.
Conversation.objects.filter(owner=request.user).delete()
Prompt Caching After a Reset
Prompt caching (Lessons 121–130) reuses the unchanged beginning of earlier requests. After a reset, the conversation part of the cache no longer matches, but a cached system prompt still can, as long as it is unchanged. This is another reason to keep the system prompt stable and put changing information, such as a summary, at its end.
Practical Example: A Chat Session with Smart Resets
This class supports manual reset, rollback, summary reset, and an automatic summary reset when the conversation grows too large.
"""chat_session.py: a chat session with manual and automatic resets."""
import anthropic
from anthropic import Anthropic
from anthropic.types import Message
MODEL = "claude-opus-5-5"
BASE_SYSTEM = "You are a helpful Python tutor. Keep answers short."
AUTO_RESET_INPUT_TOKENS = 20_000
def get_text(message: Message) -> str:
return "".join(block.text for block in message.content if block.type == "text").strip()
class ChatSession:
def __init__(self, client: Anthropic):
self.client = client
self.history: list[dict] = []
self.summary = ""
@property
def system(self) -> str:
if not self.summary:
return BASE_SYSTEM
return f"{BASE_SYSTEM}\n\n<previous_conversation_summary>\n{self.summary}\n</previous_conversation_summary>"
def send(self, user_text: str) -> str:
pending = self.history + [{"role": "user", "content": user_text}]
try:
reply = self.client.messages.create(
model=MODEL, max_tokens=2048, system=self.system, messages=pending
)
except anthropic.APIError as error:
return f"[Request failed: {error}]"
if reply.stop_reason == "refusal":
return "[Claude declined this request. The turn was not saved.]"
self.history = pending + [{"role": "assistant", "content": reply.to_dict()["content"]}]
text = get_text(reply)
if reply.usage.input_tokens > AUTO_RESET_INPUT_TOKENS:
self.reset_with_summary()
text += "\n[Conversation was long, so it was summarized and restarted.]"
return text
def reset(self) -> None:
self.history = []
self.summary = ""
def rollback(self) -> None:
if len(self.history) >= 2 and self.history[-1]["role"] == "assistant":
self.history = self.history[:-2]
def reset_with_summary(self) -> None:
if not self.history:
return
request_messages = self.history + [{
"role": "user",
"content": "Summarize our conversation in at most 5 bullet points: facts about me, "
"decisions, and open questions. Reply with only the bullet points.",
}]
reply = self.client.messages.create(
model=MODEL, max_tokens=2048, system=self.system, messages=request_messages
)
self.summary = get_text(reply)
self.history = []
if __name__ == "__main__":
session = ChatSession(Anthropic())
print(session.send("Hi, I'm Arjun. I'm building a Flask app for a library."))
print(session.send("Which database should I start with?"))
session.reset_with_summary()
print("\n--- Summary carried forward ---")
print(session.summary)
print("\n--- New conversation ---")
print(session.send("Remind me what I'm building?"))
Example output (wording varies):
Hi Arjun! A library app is a great Flask project...
For a small library app, start with SQLite: it needs no server...
--- Summary carried forward ---
- The user is Arjun.
- Arjun is building a Flask app for a library.
- Recommended starting database: SQLite.
--- New conversation ---
You're building a Flask app for a library, Arjun, and we discussed starting with SQLite.
How It Works
systemis a property that combines the fixed instructions with the latest summary. Every request automatically includes the carried-forward context.send()commits a turn only after a usable reply, and leaves refusals out of the history.- Automatic reset:
reply.usage.input_tokensmeasures how large the conversation has become. When it passesAUTO_RESET_INPUT_TOKENS, the session summarizes and restarts, so later requests stay small. reset_with_summary()asks Claude for a short summary of the current conversation, stores it, and clears the messages. The new conversation is small but still knows the important facts.reset()clears everything, including the summary, for a completely fresh start.rollback()removes only the last exchange.
The final answer shows the effect: although the message history was cleared, Claude still knows the user's name, project, and database choice, because they survived in the summary.
Common Mistakes
Expecting a Reset to Need an API Call
What happens: developers look for an API endpoint to "clear Claude's memory".
Fix: there is none, and none is needed. The history you send is the only memory. Change the list.
Clearing the System Prompt by Accident
What happens: a reset also removes the role and rules, so the assistant suddenly behaves generically.
Fix: keep the system prompt separate from the message history, and reset only the messages unless a full reset is intended.
Resetting Without Telling the User
What happens: Claude "forgets" mid-conversation, which confuses users.
Fix: show a clear notice when an automatic reset happens.
Losing Important Facts on Reset
What happens: after a reset, users must repeat their name, goals, and constraints.
Fix: use a summary reset, or store key facts in a user profile that is added to the system prompt.
Treating Reset as Deletion
What happens: conversations a user wanted removed still exist in the database or logs.
Fix: implement real deletion separately, covering every place the data is stored.
Best Practices
- Offer a "New chat" action that clears messages but keeps the system prompt.
- Use rollback for single bad turns, and full resets after refusals or when a conversation has gone off track.
- Summarize before resetting when earlier context still matters.
- Automate resets based on token usage to control cost, and tell users when it happens.
- Keep the system prompt stable and append changing context at its end, which suits prompt caching.
- Distinguish reset from deletion and implement both deliberately.
Exercise
- Add a
/newcommand to the chat loop from Lesson 26 that callssession.reset(), and a/summarycommand that callssession.reset_with_summary()and prints the summary. - Lower
AUTO_RESET_INPUT_TOKENSto500, then chat until the automatic reset happens. What does Claude still remember afterward? - Add an
undofeature that usesrollback(), and test it by asking a question, undoing it, and then asking "What did I just ask?" - Explain why the summary is placed in the system prompt rather than as the first user message of the new conversation.
Step 3: after rollback(), the last question and its answer are no longer in the history. When you ask "What did I just ask?", Claude refers to the question before the one you undid, or says it does not see a previous question, because the undone exchange is not part of the request.
Step 4: the summary is background context provided by the application, not something the user said. Putting it in the system prompt keeps the conversation starting with the user's real first message, gives the summary operator-level framing, and keeps it separate from the user's own words. It also keeps the stable instruction part at the beginning of the system prompt, which benefits prompt caching.