Reset Chat History

Su Suriya Ravichandran Updated 10 Nov 2026
10 min read ·Lesson 27 of 200

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

ReasonExplanation
New topicOld context about a different subject can distract or confuse the answers to a new question.
Cost and speedEvery request resends the whole history. Shorter history means fewer input tokens, lower cost, and faster responses (Lesson 24).
Context window limitsVery long conversations approach the model's context window.
After a refusalAnthropic'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 wrongIf Claude misunderstood something early, the misunderstanding stays in the context. Starting fresh is often faster than correcting it.
PrivacyUsers 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.

TypeWhat is keptWhen to use
Full resetNothing from the conversationA completely new topic, or a fresh start
Reset keeping configurationSystem prompt and settings, without messagesA normal "New chat" button
Partial reset (trim)Only the most recent turnsLong conversations that only need recent context
Reset with summaryA short summary of the old conversationLong conversations where earlier facts still matter
RollbackEverything except the last exchange or exchangesUndoing 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:

  1. Ask Claude to summarize the conversation so far.
  2. Clear the history.
  3. 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:

TriggerExample rule
SizeThe last request used more than 50,000 input tokens: summarize and reset
RefusalA refusal occurred: roll back that turn, or reset completely
InactivityNo message for 24 hours: start a new conversation next time
Topic changeThe 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:

OptionHowAdvantages
Start a new conversation recordCreate a new row; keep or archive the old oneThe user can return to old chats; nothing is lost
Clear the existing recordSet history = [] on the same rowSimple; 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

  1. system is a property that combines the fixed instructions with the latest summary. Every request automatically includes the carried-forward context.
  2. send() commits a turn only after a usable reply, and leaves refusals out of the history.
  3. Automatic reset: reply.usage.input_tokens measures how large the conversation has become. When it passes AUTO_RESET_INPUT_TOKENS, the session summarizes and restarts, so later requests stay small.
  4. 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.
  5. reset() clears everything, including the summary, for a completely fresh start.
  6. 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

  1. Add a /new command to the chat loop from Lesson 26 that calls session.reset(), and a /summary command that calls session.reset_with_summary() and prints the summary.
  2. Lower AUTO_RESET_INPUT_TOKENS to 500, then chat until the automatic reset happens. What does Claude still remember afterward?
  3. Add an undo feature that uses rollback(), and test it by asking a question, undoing it, and then asking "What did I just ask?"
  4. Explain why the summary is placed in the system prompt rather than as the first user message of the new conversation.
Show answers for steps 3 and 4

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.

0 Comments

Reviewed before they appear

No comments yet.

Anthropic SDK Using Python
Anthropic SDK Intro Claude API Intro SDK Requirements Install Anthropic SDK Upgrade the SDK Create an API Key Set API Keys Use Environment Variables Import Anthropic Create a Client Send Your First Message Choose a Claude Model Set Max Tokens Read a Response Print Response Text Understand Message Blocks Use System Prompts Send User Messages Set Temperature Handle Stop Reasons Messages API Intro Create Messages Use Message Roles Send Conversation History Continue a Conversation Build a Chat Loop Reset Chat History Use Multiple Turns Inspect Message IDs Read Usage Data Write Clear Prompts Set a System Prompt Add Context to Prompts Use Prompt Templates Add Examples to Prompts Request JSON Output Use XML Tags Control Response Length Improve Prompt Quality Avoid Prompt Injection Read Text Blocks Read Content Blocks Check Stop Reasons Count Input Tokens Count Output Tokens Count Tokens Before Sending Limit Output Tokens Use Stop Sequences Read Request IDs Parse API Responses Streaming Intro Stream Text Output Use Stream Events Use Stream Helpers Get Final Messages Stream Async Responses Handle Stream Errors Build a Live Chat Stream Long Responses Close Streams Safely Build a Chatbot Keep Chat History Manage Chat Sessions Add Chat Memory Build a CLI Chatbot Build a Web Chatbot Use Flask with Claude Use FastAPI with Claude Return JSON from an API Add Chat Error Messages Async SDK Intro Create an Async Client Send Async Messages Use asyncio Run Parallel Requests Stream Async Text Handle Async Errors Set Async Timeouts Close Async Clients Choose Sync or Async Tool Use Intro Define a Tool Create Tool Schemas Send Tools to Claude Read Tool Calls Run Python Tools Return Tool Results Continue After Tool Use Control Tool Choice Handle Tool Errors Use the beta_tool Decorator Create a Tool Runner Add Tool Docstrings Validate Tool Inputs Use Multiple Tools Limit Tool Calls Log Tool Activity Build a Weather Tool Build a Search Tool Build a Calculator Tool Structured Output Intro Request JSON Data Validate JSON Output Use Pydantic Models Handle Invalid JSON Extract Fields from Text Generate Typed Data Use Image URLs Send Base64 Images Read PDFs with Claude Use Output Schemas Build Data Extraction Test Structured Responses Send Image Inputs Upload Files Use File IDs Process Text Files Summarize Documents Extract Table Data Handle File Errors Read Cache Usage Reduce Repeated Input Costs Debug Cache Misses Prompt Caching Intro Enable Prompt Caching Cache System Prompts Cache Long Context Test Cache Performance Use Cache Breakpoints Cache Best Practices Message Batches Intro Create a Message Batch Set Batch IDs Check Batch Status List Message Batches Get Batch Results Process Batch Outputs Handle Failed Batch Items Use Batches for Bulk Tasks Compare Batches and Requests Handle API Errors Handle Rate Limits Retry Failed Requests Set Request Timeouts Handle Network Errors Use Exponential Backoff Build Reliable API Calls Use Extended Thinking Log API Errors Track Request IDs Paginate API Results Set Thinking Budgets Read Thinking Blocks Use Tool Search Use Web Search Tools Use Computer Tools Use Citations Use Token Counting Read Raw Responses Set Custom Headers Use Claude on AWS Bedrock Use Claude on Vertex AI Use Claude on Microsoft Foundry Configure Cloud Credentials Choose a Cloud Provider Compare API Integrations Configure Provider Clients Handle Cloud Errors Use Cloud SDK Extras Deploy Cloud Apps Protect API Keys Use a .env File Ignore Secrets in Git Validate User Input Reduce Prompt Injection Limit Tool Permissions Avoid Unsafe Tool Calls Sanitize Tool Results Set Usage Limits Review Security Logs Test SDK Functions Mock API Responses Test Error Handling Test Streaming Code Measure Token Usage Track API Costs Configure Logging Deploy with Docker Deploy a FastAPI App Monitor Production Apps Build a Claude Chatbot Build a Text Summarizer Build a Code Explainer Build a JSON Extractor Build a PDF Assistant Build a Streaming Chat App Build a Tool-Calling Agent Build a Batch Processor Build a Research Assistant Build a Claude API Dashboard
Ask about this post
AI Ask about this post

Ask questions about Reset Chat History and get answers drawn from it.

Signed-in readers only.