Preserve an AI Agent's Context

Build an agent that offloads large results and preserves its history on disk.

Introduction

30 Second Summary

Long AI conversations eventually run out of room. A quick summary can keep the work moving, but useful details may disappear with it.

In this project, you will build a Python agent with the deepagents summarization middleware that preserves its working history when its context fills up. You will watch the agent replace large results with short previews while the complete records stay available on disk.

What You'll Build

You will watch your agent shrink a large tool result into a short preview while the full result remains readable on disk.

By the end of this project, you'll have:

  • A working AI agent that prints a model response from your own Python script.
  • An offload record that lets you compare the short preview sent to the model with the complete result stored on disk.
  • A compacted conversation where the token count drops while the agent can still answer a question about earlier work.
  • Secret Mission: An optional challenge to push your context management skills further.

Are there any prerequisites?

You need Python, pip, and a model API key. The model calls run through an API, so no GPU is required.

Before We Start

A long-running agent needs a clean place for its packages before it can start managing its own context. Mixing those packages with unrelated Python projects makes installation problems harder to trace.

In this step, you'll prepare an isolated Python virtual environment. You'll install Deep Agents inside it. You'll also give the agent temporary access to a model provider.

In this step, get ready to:
  • Check Python and create a fresh project folder.
  • Create a virtual environment and install the deepagents package.
  • Set a model-provider API key for the current terminal session.
Check Python and create the workspace

Python runs the agent script you'll build later. Checking it first keeps the rest of the setup focused on your project.

  • Press Cmd+Space on macOS or the Windows key on Windows to open system search.
  • Type Terminal on macOS or PowerShell on Windows to find your terminal.
  • Press Enter to open the terminal.
  • Check whether Python is available by running the command for your platform:

macOS

python3 --version

What does this command do?

The --version option prints the installed Python version. A version number confirms that the terminal can find Python.

Windows

py --version

What does this command do?

The --version option prints the Python version selected by the Windows launcher. A version number confirms that Python is ready.

✔️ I see a Python version

Python is available. Keep this terminal open for the project setup.

ⓧ Command not found

Python needs to be installed before the project can continue.

  • Visit the official Python downloads page in your browser.
  • Download the current Python 3 installer for your operating system.
  • Run the installer using its recommended settings.
  • Return to your terminal after the installation finishes.
  • Run the version check above again to confirm that you see a Python version.

Still cannot run Python?

Close the terminal after installing Python. Open a fresh terminal so it loads the updated command path.

If the command still fails, ask for help checking your Python installation.

A named folder keeps the script and its offloaded context files together. You'll place it on your Desktop so it stays easy to find.

  • Create the deepagents-context-lab folder on your Desktop by running the commands for your platform:

macOS

cd ~/Desktop
mkdir deepagents-context-lab
cd deepagents-context-lab
pwd

What do these commands do?

  • The first command moves your terminal to the Desktop.
  • The second command creates the deepagents-context-lab folder.
  • The final commands enter the folder and print its full path.

Windows

Set-Location -Path ([Environment]::GetFolderPath('Desktop'))
New-Item -Path . -Name "deepagents-context-lab" -ItemType "Directory"
Set-Location -Path "deepagents-context-lab" -PassThru

What do these commands do?

  • The first command moves PowerShell to your Desktop.
  • The second command creates the deepagents-context-lab folder.
  • The final command enters the folder and prints its location.

You should see a path ending in deepagents-context-lab. Your terminal is now open inside the project folder.

Folder already exists?

Choose a different empty folder if you already used this name for another project. An empty workspace prevents old files from affecting your results.

If the terminal cannot create or enter the folder, ask for help with the folder path.

Create the environment and install Deep Agents

A virtual environment gives this project its own Python packages. Activating .venv keeps the Deep Agents installation separate from everything else on your computer.

  • Create and activate .venv by running the commands for your platform:

macOS

python3 -m venv .venv
source .venv/bin/activate

How does the environment work?

  • The first command creates an isolated Python environment inside .venv.
  • The second command activates that environment in your current terminal.
  • Your terminal prompt should now include (.venv).

Windows

py -m venv .venv
.\.venv\Scripts\Activate.ps1

How does the environment work?

  • The first command creates an isolated Python environment inside .venv.
  • The second command activates that environment in your current PowerShell session.
  • Your terminal prompt should now include (.venv).

Your prompt should now begin with (.venv). That prefix confirms that package installations belong to this project.

Virtual environment not activating?

  • Confirm that your terminal path ends in deepagents-context-lab.
  • Confirm that the environment folder is named exactly .venv.
  • On Windows, use the execution policy guidance in the official Python virtual environment documentation if PowerShell blocks the activation script.

If the prompt still does not change, ask for help activating the environment.

The deepagents package provides the agent harness and its context-management features. Installing it inside the active environment gives the project the dependency it needs.

  • Install the package into .venv by running this command:
python -m pip install deepagents

What does this command do?

Python runs pip from the active environment. Pip installs deepagents with the packages it depends on.

  • Review the final lines of the installation output.

You should see installation output ending with Successfully installed followed by package names. The download can take a moment while pip resolves the dependencies.

Package installation failed?

  • Confirm that (.venv) appears at the start of your terminal prompt.
  • Check that your internet connection can reach the Python package index.
  • Run the installation command again after correcting the environment or connection problem.

If pip still cannot install the package, ask for help with the installation output.

Set a model-provider API key

The agent uses an API key to authenticate with a model provider. Deep Agents supports providers including OpenAI, Google, and Anthropic.

Credentials deserve extra care. These commands keep the key in the current shell session. Your project files stay free of secrets.

OpenAI

  • Open the OpenAI API key page in your browser.
  • Create a new secret key for this project.
  • Copy the key when it appears.
  • Replace your-api-key with the key you copied.

Before you run the check, do you expect the terminal to confirm both the package and the environment variable?

macOS

  • Set the key for this shell and verify the setup by running these commands:
export OPENAI_API_KEY="your-api-key"
python -m pip show deepagents
test -n "$OPENAI_API_KEY" && echo "API key is set"
What should I see?
  • The package details should include Name: deepagents.
  • The final line should say API key is set without displaying the key.

Windows

  • Set the key for this PowerShell session and verify the setup by running these commands:
$env:OPENAI_API_KEY = "your-api-key"
python -m pip show deepagents
Test-Path Env:\OPENAI_API_KEY
What should I see?
  • The package details should include Name: deepagents.
  • The final check should return True without displaying the key.

Google

  • Open the Gemini API key guide in your browser.
  • Create an API key through the linked Google AI Studio flow.
  • Copy the key when it appears.
  • Replace your-api-key with the key you copied.

Before you run the check, do you expect the terminal to confirm both the package and the environment variable?

macOS

  • Set the key for this shell and verify the setup by running these commands:
export GOOGLE_API_KEY="your-api-key"
python -m pip show deepagents
test -n "$GOOGLE_API_KEY" && echo "API key is set"
What should I see?
  • The package details should include Name: deepagents.
  • The final line should say API key is set without displaying the key.

Windows

  • Set the key for this PowerShell session and verify the setup by running these commands:
$env:GOOGLE_API_KEY = "your-api-key"
python -m pip show deepagents
Test-Path Env:\GOOGLE_API_KEY
What should I see?
  • The package details should include Name: deepagents.
  • The final check should return True without displaying the key.

Anthropic

  • Open the Claude Console in your browser.
  • Create a new API key in the API keys area.
  • Copy the key when it appears.
  • Replace your-api-key with the key you copied.

Before you run the check, do you expect the terminal to confirm both the package and the environment variable?

macOS

  • Set the key for this shell and verify the setup by running these commands:
export ANTHROPIC_API_KEY="your-api-key"
python -m pip show deepagents
test -n "$ANTHROPIC_API_KEY" && echo "API key is set"
What should I see?
  • The package details should include Name: deepagents.
  • The final line should say API key is set without displaying the key.

Windows

  • Set the key for this PowerShell session and verify the setup by running these commands:
$env:ANTHROPIC_API_KEY = "your-api-key"
python -m pip show deepagents
Test-Path Env:\ANTHROPIC_API_KEY
What should I see?
  • The package details should include Name: deepagents.
  • The final check should return True without displaying the key.

Setup check did not pass?

  • Confirm that your terminal prompt still begins with (.venv).
  • Confirm that you replaced your-api-key with your actual key.
  • Keep the key-setting command in the same terminal that runs the checks.

If the check still fails, ask for help without sharing the key.

That's the setup locked in. Your isolated environment contains Deep Agents. Your current terminal can authenticate with your chosen model provider.

Your workspace is ready. Next, you'll build the agent and watch it return its first response.

Create an Agent With a Large Tool

Your environment can already run a Deep Agents agent. A normal tool response may stay small enough to fit inside the context window.

This step gives the agent a deliberately large result. The summarization middleware can then move the full result to disk while the model receives a short preview.

In this step, get ready to:
  • Configure disk-backed artifact storage.
  • Create a tool that returns a large block of text.
  • Run the agent to generate an offloaded result.
Configure the offload backend

A filesystem backend gives the middleware somewhere persistent to write oversized results. The artifact root keeps those files together inside the project’s offload directory.

  • Use your editor’s New File control to create agent_offload_demo.py inside the open project folder.
  • Add the backend setup by pasting this code:
from pathlib import Path

from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, FilesystemBackend
from langchain.tools import tool

# Persist middleware artifacts inside this project's offload directory
backend = CompositeBackend(
    default=FilesystemBackend(root_dir=Path.cwd(), virtual_mode=True),
    routes={},
    artifacts_root="/offload",
)
print("Offload backend configured.")

What does this code do?

  • Path.cwd() points the backend at the project folder open in your terminal.
  • FilesystemBackend maps virtual agent paths into that folder.
  • CompositeBackend sets /offload as the root for middleware artifacts.
  • create_deep_agent() enables filesystem handling plus summarization when the agent is created later.
  • Save agent_offload_demo.py.
  • Return to the activated terminal from the previous step.
  • Check the backend setup by running this command:
python agent_offload_demo.py

What does this command do?

Python executes agent_offload_demo.py inside the active .venv. The print statement confirms that the imports loaded successfully.

You’ll see Offload backend configured. in the terminal.

Backend setup failed?

Confirm that .venv is still activated in this terminal. An inactive environment may use a Python installation without deepagents.

Check that the import lines match the code above. Help me diagnose the backend setup error.

Define the large-text tool

Tool results only move to disk after they grow beyond the middleware’s threshold. This tool creates thousands of numbered records so the offload path fires during the agent run.

  • Add the large-text tool below the final print line in agent_offload_demo.py by pasting this code:
@tool
def generate_large_report() -> str:
    """Return numbered records for context-offload testing."""
    # Cross the large-result threshold with repeatable test data
    return "\n".join(
        f"Record {index}: preserve this detail for later."
        for index in range(5000)
    )

print("Large tool prepared with 5000 records.")

How does the tool create pressure?

  • tool exposes generate_large_report() to the agent.
  • range(5000) produces enough records to cross the large-result threshold.
  • join() combines those records into one tool result.
  • Save agent_offload_demo.py.
  • Check that Python can load the new tool by running this command:
python agent_offload_demo.py

What does this check prove?

Python now loads the backend plus the decorated tool. The second status line proves that the complete tool definition executed.

You’ll see Offload backend configured. followed by Large tool prepared with 5000 records..

Tool definition failed?

Check that the tool code sits below the backend setup. Keep the function body indented exactly as shown.

Make sure the function keeps its docstring because the tool uses it as a description. Help me fix the large-text tool.

Invoke the tool through the agent

The agent call sends the tool result through the middleware stack. That route lets the filesystem middleware replace the oversized result with a preview.

  • Add the agent invocation below the tool status line in agent_offload_demo.py by pasting this code:
# Create an agent with the large tool and persistent artifact backend
agent = create_deep_agent(
    tools=[generate_large_report],
    backend=backend,
    system_prompt="Use generate_large_report for every large report request.",
)

# Route the large result through the agent's middleware stack
result = agent.invoke({
    "messages": [{
        "role": "user",
        "content": "Call generate_large_report once. Reply with a short confirmation.",
    }]
})
print(result["messages"][-1].content)

What happens during the run?

  • create_deep_agent() builds the agent with its filesystem middleware.
  • The same factory enables summarization middleware for later conversation compaction.
  • agent.invoke() sends the request into the agent loop.
  • result["messages"][-1].content selects the final response for printing.
  • Save agent_offload_demo.py.

Before you run this, do you expect the full report to stay in the model’s messages or move into the offload directory?

  • Run the completed agent script with this command:
python agent_offload_demo.py

What does the final run do?

The command starts one model request from the active environment. The agent calls generate_large_report() before printing its final response.

You’ll see both setup lines first. A short agent confirmation appears after the model call completes.

That is the key result working: the agent handles the oversized tool response without printing thousands of records into its final answer.

  • Inspect the persisted large tool result by running this command:
ls offload/large_tool_results

What does this listing prove?

The command lists files created under offload/large_tool_results. Each listed file preserves a full oversized tool result outside the model’s active messages.

The same artifact configuration reserves offload/conversation_history for conversation offloads when summarization compacts older turns.

You should see at least one generated file in the listing. Your first large tool result is now preserved on disk.

No offload file listed?

Confirm that the agent called generate_large_report() during the run. The final request must ask for the large report.

Check that artifacts_root remains set to /offload. Help me find the missing offload file.

✔️ Awesome, I've got everything!

Great. Double-check that agent_offload_demo.py is saved. Keep the generated offload directory for the next step.

ⓧ I'd like to double check the full code

Compare your saved agent_offload_demo.py with this complete checkpoint:

from pathlib import Path

from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, FilesystemBackend
from langchain.tools import tool

# Persist middleware artifacts inside this project's offload directory
backend = CompositeBackend(
    default=FilesystemBackend(root_dir=Path.cwd(), virtual_mode=True),
    routes={},
    artifacts_root="/offload",
)
print("Offload backend configured.")

@tool
def generate_large_report() -> str:
    """Return numbered records for context-offload testing."""
    # Cross the large-result threshold with repeatable test data
    return "\n".join(
        f"Record {index}: preserve this detail for later."
        for index in range(5000)
    )

print("Large tool prepared with 5000 records.")

# Create an agent with the large tool and persistent artifact backend
agent = create_deep_agent(
    tools=[generate_large_report],
    backend=backend,
    system_prompt="Use generate_large_report for every large report request.",
)

# Route the large result through the agent's middleware stack
result = agent.invoke({
    "messages": [{
        "role": "user",
        "content": "Call generate_large_report once. Reply with a short confirmation.",
    }]
})
print(result["messages"][-1].content)

This reference shows the complete file at this checkpoint.

Your agent now preserves oversized tool results outside its active messages. Next, you’ll inspect the preview that the model received beside the full result stored on disk.

Run the Large Tool and Inspect Its Offload

The prepared agent_offload_demo.py script gives your AI agent a deliberately oversized tool result. The open question is whether that result can leave the active context without disappearing.

The deepagents summarization middleware preserves oversized results on an attached filesystem. This step triggers that behavior and checks for the saved file.

In this step, get ready to:
  • Trigger the deliberately large tool result.
  • Confirm the agent prints its response.
  • Verify the complete result appears under offload/large_tool_results/.
Run the large-text tool

The configured threshold sits below the size of the tool result. Crossing that threshold sends the complete result to the attached filesystem.

Before you run the script, where do you expect the complete oversized result to appear?

  • In the activated virtual environment from earlier, execute agent_offload_demo.py by running this command:
python agent_offload_demo.py

What does this command prove?

  • The python command executes the prepared script in your active virtual environment.
  • The script invokes the configured large-text tool through the agent.
  • The middleware detects that the returned text exceeds its threshold. It persists the complete result under the configured offload directory.

The model call can take a moment, so a short pause is normal. You will then see an agent response printed in the terminal.

Good work. Your agent has completed the large tool call and returned a response.

Did the agent run fail?

  • Confirm the .venv from earlier is still active in this terminal session.
  • Confirm the model-provider API key is still available in the same shell session.
  • Confirm the terminal is still in the folder that contains agent_offload_demo.py.

Help me diagnose why the prepared agent script cannot complete its model call.

Inspect the offload directory

The printed response proves the run completed. A file under offload/large_tool_results/ proves the middleware preserved the oversized payload.

Before you inspect the directory, how many result files do you expect after one successful run?

macOS

  • List the files saved under offload/large_tool_results/ by running this command:
ls offload/large_tool_results/

What does this command show?

  • The ls command lists the visible files inside the specified directory.
  • Targeting the large tool results directory checks the exact location configured for oversized payloads.

Windows

  • List the files saved under offload/large_tool_results/ by running this command in PowerShell:
Get-ChildItem -Path offload/large_tool_results/

What does this command show?

  • The Get-ChildItem command lists the items inside the specified directory.
  • Targeting the large tool results directory checks the exact location configured for oversized payloads.

You will see at least one middleware-created filename in the output. That file holds the complete oversized text returned by the tool.

That is the key result. Your agent returned a response while the full tool output stayed available on disk.

Don't see an offloaded file?

  • Check that the current terminal location still contains agent_offload_demo.py.
  • Check that offload/large_tool_results/ matches the persistence path configured by the script from earlier.
  • Confirm the script finished with an agent response before inspecting the directory again.

Help me find why the large tool result was not written to the configured offload directory.

Your oversized result now has a home outside the model's active context. Next, you will compare the shorter message the model received with the complete file.

Compare the Preview With the Full Result

Your deepagents agent has already moved an oversized tool result out of its context window. The complete result now lives under offload/large_tool_results/.

This step reveals what the model received in place of that result. You will compare the short preview with the complete text preserved on disk.

In this step, get ready to:
  • Expose the messages from the agent run.
  • Read the complete offloaded tool result.
  • Compare the preview with the preserved text.
Print the model-visible messages

The agent invocation returns a message history that includes the replacement tool message. Printing the complete return value exposes the preview that continued through the agent loop.

  • In agent_offload_demo.py, locate the assignment that stores the result of agent.invoke(...).
  • Locate the final print statement that currently displays the agent's answer.
  • Replace its current expression with the variable that stores the complete return value from agent.invoke(...).
  • Save agent_offload_demo.py.

Why print the whole result?

The final answer shows what the agent concluded. The complete invocation result also exposes the messages that carried the tool call through the agent loop.

The oversized result appears there as a short preview with a file reference. That replacement is the evidence you need for the comparison.

Before you rerun the script, do you expect the oversized tool result to appear in full inside the returned messages?

  • Rerun the same command you used in the previous step.

You should see the complete returned message collection. One tool message should contain a short preview plus a reference to a file under offload/large_tool_results/.

Cannot find the preview?

  • Confirm that the final print statement displays the complete invocation result instead of only the last message.
  • Confirm that the tool message includes wording about an oversized result plus a file reference.
  • Run the script again if the output only shows results from an earlier saved version.

Ask for help checking the returned message structure: Why can I see the final agent answer but not the offloaded tool-result preview?

Read the preserved result

The preview protects the model's context budget. The file under offload/large_tool_results/ preserves the complete text for later inspection.

Before you print the file, how much longer do you expect the stored result to be than the preview?

  • List the offloaded files and print their complete contents by running these commands:
ls offload/large_tool_results/
cat offload/large_tool_results/*

What do these commands show?

  • The first command lists the files created for oversized tool results.
  • The second command prints the complete text stored across those files.
  • The wildcard selects every current file inside offload/large_tool_results/.

You should see at least one file name followed by the complete oversized text. The stored output should be much longer than the preview from the agent messages.

Cannot read the full result?

  • Confirm that your terminal is still inside the project folder containing agent_offload_demo.py.
  • Check that offload/large_tool_results/ contains a file before running the second command.
  • Rerun the agent script if the directory is empty.

Ask for help tracing the missing file: Why is my offloaded large tool result missing or unreadable?

Compare the preview with the full text

The two outputs represent the same tool result at different sizes. Only the short preview continues through the model conversation. The complete payload remains recoverable from disk.

Before you compare them, do you expect the preview's file reference to identify the same file you listed in the terminal?

  • Scroll back to the returned messages from the script.
  • Locate the tool message that describes the oversized result.
  • Find the file reference inside that message.
  • Match its file name with the output from offload/large_tool_results/.
  • Compare the preview's opening text with the start of the stored result.
  • Compare the preview's closing text with the end of the stored result.

The preview should contain a small sample plus the matching file reference. The file should contain the complete tool result, including the text omitted from the model-visible message.

What does this comparison prove?

The model can continue with a compact message while the filesystem preserves the original result. The file reference gives the agent a route back to the missing detail when it becomes useful.

This separation keeps the active conversation smaller without discarding the tool's work.

You have confirmed the full offload path from end to end. The model receives a compact preview while your project retains the complete result.

Your offload is now visible from both sides. Next, you will keep the conversation running and inspect how older turns move into conversation history.

Offload Earlier Conversation Turns

Your agent already proves that Deep Agents can preserve an oversized tool result on disk. Its model-visible message now carries a short preview.

Long conversations create a second pressure point. Older turns eventually crowd the model's context window.

In this step, you'll continue one conversation until the summarization middleware moves earlier turns into conversation history. You will then compare the complete stored turns with the compact summary sent to the model.

In this step, get ready to:
  • Continue one agent conversation past the summarization threshold.
  • Inspect the conversation-history file that preserves earlier turns.
  • Compare the complete stored turns with the compact model-visible summary.
Continue the Conversation

Conversation offloading depends on continuity. Each follow-up must inherit the messages returned by the previous invocation.

Each follow-up makes another API request. The configured threshold gives this test a clear stopping point.

  • Edit agent_offload_demo.py with the same editor you used earlier.
  • Find the existing invocation that sends the prompt which calls the large-text tool.
  • Extend that invocation into a bounded follow-up sequence that asks about the earlier result while reusing returned messages until the configured conversation-history threshold is crossed.
  • Save agent_offload_demo.py.

Before you rerun the script, consider which earlier turns the middleware will remove from the model-visible context.

  • Run the updated script with the same terminal command you used earlier.

When the threshold fires, you'll see a compact summary in the model-visible messages. The printed agent response still completes.

Good work. Your agent has now crossed the threshold that protects a long-running conversation from filling its working context.

No Conversation Summary Yet?

  • Confirm that every invocation receives the messages returned by the previous invocation.
  • Check that the follow-up count reaches the conversation-history threshold configured in your middleware.
  • Keep every follow-up inside the same script run so the conversation state remains continuous.

Help me work out why my earlier conversation turns were not offloaded.

Read the Stored History

The middleware writes evicted messages to its filesystem backend before summarizing them. That order preserves the original conversation before the model receives a shorter version.

  • Return to agent_offload_demo.py in your editor.
  • Reuse the file-reading approach from your earlier large-result comparison to print the first file under offload/conversation_history/.
  • Save agent_offload_demo.py.

Before you rerun it, consider whether the stored history or the model-visible message will contain more detail.

  • Run the updated script with the same terminal command you used earlier.

You'll see at least one history file under offload/conversation_history/. Its printed contents include the complete earlier turns.

What Was Preserved?

The conversation-history file is the canonical record of the evicted messages. It keeps the detail that no longer fits comfortably in the model's working context.

The model keeps a shorter summary with a reference to that file. The reference gives the agent a route back to the complete record.

History Directory Still Empty?

  • Confirm that the script completed enough follow-ups to cross the configured threshold.
  • Check that the middleware still writes internal files beneath the existing offload/ directory.
  • Confirm that the history-reading section runs after the final agent invocation.

Help me diagnose why offload/conversation_history/ is empty after my agent crosses its summarization threshold.

Compare Both Views

A direct comparison shows whether the agent preserved earlier detail while reducing the context sent to the model.

Before you compare the views, consider whether an original sentence from an early turn will remain visible to the model.

  • Choose a distinctive sentence from one early follow-up in the printed history file.
  • Find that exact sentence in the complete history output.
  • Review the final model-visible messages for a compact summary.
  • Locate the conversation-history file reference inside the model-visible output.
  • Keep your API key outside the area you capture for the checkpoint.

You'll find the distinctive sentence in the stored history. The model-visible context contains a compact summary with a file reference instead.

That is the hard part done. Your agent can reduce its working context without discarding the complete earlier turns.

Your conversation can now grow while its earlier work remains recoverable on disk. Next up, you'll compact the conversation on demand and measure how the token count changes.

Compact the Conversation Manually

Your Deep Agents run already preserves older turns before they leave the model's context window. Automatic summarization protects the conversation when it crosses the configured threshold.

Manual compaction gives you control over that timing. In this step, you will trigger the compaction tool yourself. Then you will measure the reduction and test whether the agent still remembers earlier work.

In this step, get ready to:
  • Expose the manual conversation compaction tool.
  • Print the token count before and after compaction.
  • Ask about earlier work after the context becomes smaller.
Enable manual compaction

The existing summarization middleware handles automatic compaction. A separate tool middleware exposes compact_conversation so the agent can compact the same conversation on demand.

  • Inside agent_offload_demo.py, place this beside the existing model and backend setup:
# Add an on-demand compaction tool to the existing setup
from deepagents.middleware.summarization import create_summarization_tool_middleware

# Reuse the backend that already stores offloaded conversation history
compact_middleware = create_summarization_tool_middleware(model, backend)
print("Manual compaction tool:", compact_middleware.tools[0].name)

What does this code do?

  • The factory uses the same model that summarizes the existing conversation.
  • The factory points at the same backend that stores your offloaded files.
  • The print statement exposes the registered tool name before the agent starts its work.
  • In the existing create_deep_agent() call, add the following entry to its middleware argument:
  • Keep every middleware entry that is already present.
# Register the on-demand middleware with the agent
compact_middleware,

Why register the middleware?

Registration makes compact_conversation available during the agent loop. The tool updates the same summarization state used by automatic compaction.

Older messages remain recoverable through the conversation-history files. The active model context receives their condensed summary.

  • Save agent_offload_demo.py.
  • Rerun the script with the same terminal command you used earlier.

You should see Manual compaction tool: compact_conversation before the existing agent output. This confirms that manual compaction is available to the agent.

Manual tool missing?

  • Check that compact_middleware appears inside the middleware argument passed to create_deep_agent().
  • Check that the factory receives the existing model variable.
  • Check that the factory receives the existing backend variable.

Help me find why the manual compaction tool is missing from my Deep Agents setup.

Measure the compaction

Provider usage metadata records how many input tokens reached each model call. Comparing the newest reported count on each side of compaction gives you a visible measurement of the reclaimed space.

  • At the end of the existing conversation flow in agent_offload_demo.py, add this measurement and compaction code:
def latest_input_tokens(messages):
    # Find the newest model response that reports input usage
    for message in reversed(messages):
        usage = getattr(message, "usage_metadata", None)
        if usage and usage.get("input_tokens") is not None:
            return usage["input_tokens"]
    raise RuntimeError("No provider-reported input token count was found.")

# Measure the final model call before requesting compaction
before_tokens = latest_input_tokens(result["messages"])

# Ask the agent to invoke the registered tool in the same thread
result = agent.invoke(
    {
        "messages": [
            {
                "role": "user",
                "content": "Call compact_conversation now. Confirm when it finishes.",
            }
        ]
    },
    config=config,
)

# Confirm that the model receives a smaller context after compaction
after_tokens = latest_input_tokens(result["messages"])
print(f"Tokens before compaction: {before_tokens}")
print(f"Tokens after compaction: {after_tokens}")
assert after_tokens < before_tokens

How does the measurement work?

  • The latest_input_tokens() helper searches backward for the newest model response with usage data.
  • The first measurement captures the context size before the manual request.
  • The next invocation asks the agent to call compact_conversation inside the existing thread.
  • The assertion confirms that the model's later input contains fewer tokens.
  • Save agent_offload_demo.py.

Before you rerun the script, do you expect the second token count to be higher or lower?

  • Rerun the script with the same terminal command you used earlier.

You should see values after Tokens before compaction: and Tokens after compaction:. The second value should be lower.

You have just reclaimed model context on demand. The full offloaded history still remains under offload/conversation_history/.

Token count did not drop?

  • Confirm that the manual request appears in the same thread represented by config.
  • Inspect the returned messages for a call to compact_conversation.
  • Confirm that the conversation contains enough reported usage for manual compaction to run.

Help me diagnose why manual compaction did not lower the reported token count.

Test retained knowledge

A smaller context is only useful when the summary still carries the details needed for later work. Your final request checks whether the agent can connect the compact summary to the earlier large result.

  • Add this final follow-up below the token count check in agent_offload_demo.py:
# Ask about details that appeared before manual compaction
result = agent.invoke(
    {
        "messages": [
            {
                "role": "user",
                "content": "What did the large-text tool return earlier? Where was the complete result saved?",
            }
        ]
    },
    config=config,
)
print("Answer after compaction:", result["messages"][-1].content)

What does this check prove?

The question depends on work completed before manual compaction. A relevant answer proves that the summary preserved the important thread.

The stored file provides the complete source when the summary alone is too short. Compaction reduces active context without deleting the underlying record.

  • Save agent_offload_demo.py.

Before you rerun the script, do you think the agent can still identify the earlier result after its token count drops?

  • Rerun the script with the same terminal command you used earlier.

You should see an answer that describes the earlier large-text result. You should also see a reference to the preserved result under offload/large_tool_results/.

Earlier work missing from the answer?

  • Confirm that every invocation reuses the same config value.
  • Confirm that the earlier conversation-history file still exists under offload/conversation_history/.
  • Confirm that the complete tool result still exists under offload/large_tool_results/.

Help me trace why the agent lost earlier details after manual compaction.

Strong finish. Your agent can now compact its active conversation on demand while keeping detailed work recoverable on disk.

Secret mission

Audit the Agent's Context Trail

Your agent already left a trail through its model-visible messages. Matching files preserve the full details on disk. In this mission, you will connect both views into an audit of context preservation.

Clean Up Your Resources

Clean Up Your Resources

Idle local deepagents files have no ongoing cost. Choose Keep, Pause, or Delete based on whether you plan to spend model API capacity on another run.

Resources you used:

  • The agent_offload_demo.py demonstration script.
  • The .venv virtual environment with deepagents installed.
  • The offload/ directory containing persisted middleware output.
  • The current shell session containing your model-provider API key.

Where does the API key live?

The key value exists only in your current shell environment. Closing that terminal removes the environment variable from the session.

The provider-side credential remains active until you revoke it through your provider.

Keep everything running

No action is needed. Choose this option if you want to continue experimenting with context offloading.

  • Keep agent_offload_demo.py for future agent runs.
  • Keep offload/ to compare model-visible previews with complete stored records.
  • Keep .venv so the installed package remains available.
  • Leave the terminal open only if another agent run is imminent.

Pause - I'll come back to this later

Pausing closes the credential-bearing shell session while preserving your script and offloaded evidence.

  • Close the project terminal window.
  • Keep agent_offload_demo.py for your next session.
  • Keep offload/ as evidence of what the middleware preserved.
  • Keep .venv for the installed project dependencies.
  • Set your model-provider API key in a new shell session when you return.

Delete - I don't want to use this again

This option permanently removes the local demonstration artifacts. Your provider-side API key requires separate revocation.

  • Remove the API-key setup entry from your shell history with the built-in controls for your shell.
  • Revoke the key through your provider's key-management page if you created it only for this project.

macOS

This command permanently removes the script and its stored offloads. The surrounding project folder remains in place.

  • Remove the local project artifacts by running this command in the current project terminal:
rm -rf .venv offload agent_offload_demo.py
What does this remove?

The command removes .venv plus offload/ from the current folder. It also removes agent_offload_demo.py.

  • Verify that the artifacts are gone by running:
ls -a
What should I see?

You should not see .venv, offload, or agent_offload_demo.py in the output. Your local demonstration artifacts are now cleared.

  • Close the project terminal window to clear the API key from the current shell session.

Windows

These commands permanently remove the script and its stored offloads. The surrounding project folder remains in place.

  • Remove the local project artifacts by running these commands in the current project terminal:
cmd /c rmdir /s /q .venv
cmd /c rmdir /s /q offload
cmd /c del /q agent_offload_demo.py
What do these commands remove?

The first two commands remove .venv plus offload/. The final command removes agent_offload_demo.py.

  • Verify that the artifacts are gone by running:
dir
What should I see?

You should not see .venv, offload, or agent_offload_demo.py in the output. The Windows cleanup is complete.

  • Close the project terminal window to clear the API key from the current shell session.

Linux

This command permanently removes the script and its stored offloads. The surrounding project folder remains in place.

  • Remove the local project artifacts by running this command in the current project terminal:
rm -rf .venv offload agent_offload_demo.py
What does this remove?

The command removes .venv plus offload/ from the current folder. It also removes agent_offload_demo.py.

  • Verify that the artifacts are gone by running:
ls -a
What should I see?

You should not see .venv, offload, or agent_offload_demo.py in the output. The Linux cleanup is complete.

  • Close the project terminal window to clear the API key from the current shell session.

Nice Work!

Nice Work!

You did it! You built a Python AI agent with deepagents that preserves detailed work on disk while keeping its model context compact.

You've learned how to:

  • Trigger large tool result offloading through the summarization middleware. You inspected the complete result inside offload/large_tool_results/.
  • Compare a model-visible preview with the complete text stored on disk. You also confirmed that offload/conversation_history/ preserves earlier turns after the model receives a summary.
  • Run manual conversation compaction to reduce the model-visible token count. You confirmed that the agent still answers questions about earlier work afterward.
  • Secret Mission: Completed an optional project extension to push your context-management skills further.

Ready to quiz yourself?