Skip to main content

LangGraph Deep Agents Context: Summarize and Offload

· 9 min read
Vadim Nicolai
Senior Software Engineer

Long runs fail on context, not reasoning. A LangGraph deep agent that plans, reads files, calls tools and delegates work will, somewhere around step 200, be carrying more history than the model can hold. When that happens the agent does not get dumber. It gets blind: the original goal scrolls out of the window, a 40,000-token tool result crowds out the plan, and the next decision is made on the wrong evidence. LangGraph deep agents context engineering is the set of mechanisms that keep step 200 looking at the goal: compression of history, offloading of large results to files, isolation through subagents, long-term memory, and prompt caching for the parts that never change.

LangGraph Deep Agents, a 10-part series. ← Part 6 · Part 8 →

This part walks through each layer as the Deep Agents context engineering docs describe it, what the defaults are, and where you should and should not override them.

What is context engineering in LangGraph deep agents?​

The context engineering docs list five types of context: input context, runtime context, context compression (offloading and summarization), context isolation through subagents, and long-term memory in the virtual filesystem. Prompt caching, described in the overview, sits beside them as a cost and latency layer.

The mental model: the context window is a desk, not a filing cabinet. Only what you are working on right now belongs on the desk. Everything else should be one read_file away, summarized into a note, or handed to a colleague who returns a one-page report. Deep agents ship all three moves by default, which is a big part of what separates them from a plain tool-calling loop (see the harness).

Input context: what loads every turn​

Some context is always present, and it is worth keeping small:

  • AGENTS.md memory is loaded at startup through the memory parameter and is in every turn. Keep it minimal, because you pay for every line on every call.
  • Skills load on demand. Only their short descriptions are always visible; the full body arrives when the agent decides it needs it (skills and memory).
  • Runtime context, passed via context=, is not added to the prompt automatically. It is available to tools and middleware, not to the model, unless you put it there.
  • Tool schemas cost tokens too. Harness profiles can trim them, and excluded_tools removes tools the agent will never use.

How does automatic summarization work in deep agents?​

When the conversation grows, deep agents compress it. Per the context engineering docs, the defaults are:

  • Summarization triggers at 85% of the model's max_input_tokens, read from the model's profile, and only once nothing more is eligible for offloading. Offloading is tried first because it loses nothing.
  • It keeps the most recent 10% of tokens verbatim as working context and replaces the older history with a summary.
  • If the model has no profile, the fallback is a 170,000-token trigger with 6 messages kept.
  • If the provider still throws a ContextOverflowError, the agent summarizes immediately and retries rather than crashing the run.

Two details make this safer than a naive "summarize when full" loop. First, the summary is written into context, but a text record of the original messages is saved to the filesystem, so nothing is unrecoverable: the agent can go back and read what it compressed. Second, you can choose who writes the summary. Passing summarizer= when you override SummarizationMiddleware (requires deepagents>=0.7.26) hands summarization to a cheaper model or a custom callable, while the primary model still supplies the profile and token counting.

If you would rather let the agent decide when to compact, for example right after finishing a sub-task, the docs describe an optional compact_conversation tool added through create_summarization_tool_middleware.

How do deep agents offload large tool results to files?​

Summarization handles slow growth. Offloading handles the spike: one web fetch, one SQL dump or one log tail that alone would eat a quarter of the window.

The deep agent's rule, from the docs:

  • Large tool results over the default threshold of 20,000 tokens are written to the backend at a file path. The model receives a reference to that file plus the first 10 lines as a preview.
  • Large tool inputs, such as the content of a big write_file call, are truncated in history once context passes 85% of the window, leaving a pointer to the file on disk.
  • The agent recovers details with the ordinary filesystem tools, read_file with offsets and grep, pulling in only the slice it needs.

This is why the virtual filesystem is not a side feature. It is the overflow area that makes long runs possible. A 60,000-token API response becomes a 200-token pointer, and the agent can still find line 4,812 when it matters.

One limit worth knowing: compression does not resize or embed images. If your agent works with screenshots or PDFs, the multimodal page is the place to plan for that cost separately.

How do subagents isolate context?​

Some work is context-hungry by nature: researching ten sources, reading a whole directory, trying five fixes. Doing it in the main thread fills the window with intermediate noise the main agent never needs again.

Deep agents solve this with the task tool. The main agent delegates, the subagent runs in a fresh context, and only its final report returns to the parent. All the reading, retrying and dead ends stay in the subagent's window and are discarded. Runtime context still propagates from parent to subagents, and declarative subagents inherit the parent's state_schema (compiled and remote subagents do not).

research_subagent = {
"name": "researcher",
"description": "Conducts research on a topic",
"system_prompt": """You are a research assistant.
IMPORTANT: Return only the essential summary (under 500 words).
Do NOT include raw search results or detailed tool outputs.""",
"tools": [web_search],
}

That dict is the docs example verbatim; web_search stands for whatever search tool you define, and you pass the dict to create_deep_agent(subagents=[research_subagent]).

The design lever is the subagent's prompt: tell it to return a compact answer, as the example does. A subagent that pastes its whole transcript back defeats the isolation. Part 08 on subagents covers delegation patterns in depth.

How do you give a deep agent long-term memory?​

Everything above is thread-scoped: it lives as long as one conversation. Long-term memory is the file the agent can still read next week.

The docs pattern is a CompositeBackend that routes the /memories/ path to a StoreBackend backed by a LangGraph Store (here an InMemoryStore), while every other path stays in thread-scoped state, and the system_prompt tells the agent what to save:

from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend
from langgraph.store.memory import InMemoryStore

store = InMemoryStore()

agent = create_deep_agent(
model="anthropic:claude-sonnet-5",
store=store,
backend=CompositeBackend(
default=StateBackend(),
routes={
"/memories/": StoreBackend(namespace=lambda _rt: ("memories",)),
},
),
system_prompt="""When users tell you their preferences, save them to
/memories/user_preferences.txt so you remember them in future conversations.""",
)

/memories/ starts empty; the agent creates files as it learns. Scratch work under any other path vanishes with the thread, which is exactly what you want for offloaded tool results. Swap InMemoryStore for a persistent store before production (production); see the memory docs and backends docs for the options.

Does LangGraph deep agents context engineering include prompt caching?​

Yes, and for Anthropic it is free to adopt. The overview states that for Anthropic and Amazon Bedrock models, create_deep_agent automatically applies prompt caching to the static sections of the system prompt: the base instructions, memory and skill content that repeat every turn. It is on by default for Anthropic models and for Bedrock Claude or Nova models, with no configuration required. Other providers need their own caching through middleware integrations.

The practical consequence ties back to input context: caching rewards a stable prefix. Editing AGENTS.md mid-run, or injecting per-turn data at the top of the system prompt, breaks the cached prefix and you pay full price again. Put volatile data in messages or files, not in the static prompt.

A checklist for long runs​

  • Let offloading and summarization run with defaults first; measure before tuning (context engineering docs).
  • Point summarizer= at a cheaper model once runs regularly cross the 85% line.
  • Keep AGENTS.md short and stable so prompt caching keeps hitting.
  • Push context-heavy exploration into subagents that return short reports.
  • Route only durable facts to /memories/; leave scratch files thread-scoped.
  • Use excluded_tools to drop schemas the agent never calls.

FAQ​

When does a deep agent summarize its conversation? At 85% of the model's max_input_tokens, after offloading has been tried, keeping the most recent 10% of tokens. Without a model profile, it falls back to 170,000 tokens and keeps 6 messages.

What happens to a tool result larger than 20,000 tokens? It is written to a file in the agent's backend. The model sees a file reference and the first 10 lines, then uses read_file or grep to fetch details.

Do I need to configure prompt caching for Claude? No. For Anthropic and Bedrock Claude or Nova models, create_deep_agent caches the static system prompt sections by default.


Series: Harness · Quickstart · MCP tools · Virtual filesystem · Sandbox permissions · Skills and memory · Context engineering · Subagents · Human-in-the-loop · Production