If you've ever crammed for an exam the night before, you know the feeling: the more you study, the more the early chapters start to slip.
如果你考前一夜突击过,就懂这种感觉:越往后学,越前面的章节越开始溜走。
Agents have the same problem. As they take on longer tasks, they take on more and more information (instructions, tool results, files etc.); eventually this becomes far too much context to comfortably fit in a model's context window. The more history, noise, and tool output a model carries, the worse its accuracy and reasoning tend to get.
Agent 有同样的问题。任务越长,装载的信息(指令、工具结果、文件等)越多;最终远超模型上下文窗口能从容容纳的量。模型携带的历史、噪声与工具输出越多,准确率与推理就越差。
In the world of agent engineering, we call this context rot. This blog covers techniques to manage your agent's context window and how the Deep Agents harness uses a concept called middleware to inject them into your agent's run.
在 agent 工程圈,这叫 context rot(上下文腐烂)。本文讲管理 agent 上下文窗口的技术,以及 Deep Agents harness 如何用一个叫 middleware(中间件)的概念把它们注入 agent 的运行。
Understanding context engineering techniques · 理解上下文工程技术
To simplify, an agent is just a model with a harness around it.
简化地说,agent 就是一个包着 harness 的模型。
The context engineering techniques at the agent's disposal to address context rot primarily fall into two categories: preventing unnecessary information from entering the context window, and managing and filtering what's already in the context window.
Agent 手上对抗 context rot 的上下文工程技术主要分两类:阻止不必要的信息进入上下文窗口;管理并过滤已经在窗口里的东西。
The harness applies these methods strategically to get the model the right context at the right time for the given task.
Harness 战略性地应用这些方法,让模型在给定任务的正确时刻拿到正确的上下文。
Now wiring up a harness that does this well is easier said than done, and requires a lot of work (maybe too much work if you are the kind of person who crams for exams the night before).
把一个 harness 接好说易行难,需要大量工作(如果你是考前突击型选手,那可能是太多工作)。
Deep Agents is LangChain's open source harness. It wraps the model of your choice with techniques that move context out of the active window (into files, summaries, or a separate agent), so that the main agent carries only what it needs (and can recover the raw data if needed later): Offloading, large tool results and user messages are saved to the filesystem, and the model sees a preview. Summarization, when the conversation nears the context limit, older messages are condensed into a summary. Skills, task know-how loads only when the model decides it's relevant. Subagents, noisy work runs in a separate context window, and only the result comes back. Long-term memory, what the agent learns is saved to a file that carries over to the next conversation.
Deep Agents 是 LangChain 的开源 harness。它用一系列技术包住你选的模型,把上下文移出活动窗口(放进文件、摘要或独立 agent),让主 agent 只携带所需(之后需要也能找回原始数据):**Offloading(卸载)**——大工具结果与用户消息存到文件系统,模型只看预览;**Summarization(摘要压缩)**——对话逼近上下文上限时,旧消息压缩成摘要;**Skills(技能)**——任务知识只在模型判定相关时才加载;**Subagents(子代理)**——噪声工作在独立上下文窗口里跑,只把结果带回来;**Long-term memory(长期记忆)**——agent 学到的东西存进文件,延续到下一次对话。
Applying context engineering to common use cases · 应用到常见用例
Let's see how the techniques above can be applied in a real-world use case: a competitive analysis agent. Every Monday, this agent researches five competitors and writes a report in the team's template. A single run looks something like this: pull a market data export for Company A (tens of thousands of rows); search the news, read a few articles, and take notes; repeat for Companies B through E; draft the report, revise it based on your feedback, and format it.
看看这些技术怎么落进真实用例:一个竞品分析 agent。每周一调研五家竞品、按团队模板写报告。单次运行长这样:拉 A 公司的市场数据导出(数万行);搜新闻、读几篇文章、记笔记;B 到 E 公司重复一遍;起草报告、按你的反馈修改、排版。
By step 4, the agent has carried five raw exports, dozens of search results, and two stale drafts through every model call. Most of it is irrelevant for formatting the final report.
到第 4 步时,agent 已经带着五份原始导出、几十条搜索结果和两版旧草稿穿越了每一次模型调用——其中大部分对排版最终报告毫无用处。
Retrieval methods (RAG, or filesystem search) help the agent pull in only what it needs, but that still only solves half the problem. Even a precise agent accumulates unnecessary messages, tool results, and intermediate work, so the harness also has to manage what's already in and around the context window.
检索方法(RAG 或文件系统搜索)帮 agent 只拉进所需,但这只解决一半问题:再精准的 agent 也会积累多余的消息、工具结果与中间产物——所以 harness 还必须管理上下文窗口之内与周围已有的东西。
How to implement these techniques: middleware · 怎么实现:中间件
An agent runs in a loop: the model decides what to do, calls a tool, reads the result, and repeats until the task is done. Middleware is code that plugs into specific points in that loop: such as before the agent starts, around each model call, or around each tool call. At each point it can read the context and change it before the next step runs. Every context engineering technique in this post is a piece of middleware hooked into one of those points. Most of this is built in, so you don't need to write any middleware to use these techniques (unless you want to customize something specific).
Agent 在循环里运行:模型决定做什么、调用工具、读结果、重复直到任务完成。Middleware(中间件)就是插进这个循环特定节点的代码:比如 agent 启动前、每次模型调用前后、每次工具调用前后。在每个节点它都能读取上下文、在下一步运行前修改它。本文的每项上下文工程技术都是挂在某个节点上的一块 middleware。这些大多内建好了——用这些技术不需要自己写 middleware(除非想定制什么特定的东西)。
Offloading: keeping it out the context window · 卸载:别让它进上下文窗口
Our agent doesn't always need to see all the data that's returned from every tool call or human message, especially if it's a large volume.
我们的 agent 并不总需要看到每次工具调用或人类消息返回的全部数据——量大的尤其如此。
For example, each pull_market_report tool call returns a full data export (thousands of rows); however, the agent only needs a few numbers from it, so the model can be restricted to only see those rows.
比如每次 pull_market_report 工具调用返回一整份数据导出(数千行),而 agent 只需要其中几个数字——可以限制模型只看到那几行。
FilesystemMiddleware runs every time a tool is called. When a tool result exceeds roughly 20,000 tokens, the full result is written to /large_tool_results/{tool_call_id} before it enters the conversation. The model sees only a short preview (the first and last few lines) plus the file path. When the agent later needs Company B's quarterly revenue, it pages through the file with read_file. Oversized user/human messages, like a pasted call transcript, get the same treatment at a higher threshold (50,000 tokens) and are saved to /conversation_history/.
FilesystemMiddleware 在每次工具调用时运行:工具结果超过约 20,000 token,完整结果在进入对话前就写到 /large_tool_results/{tool_call_id};模型只看到一段短预览(首尾几行)加文件路径。之后 agent 需要 B 公司季度营收时,用 read_file 翻那份文件。超大的用户/人类消息(比如粘贴的通话转录)同样处理、阈值更高(50,000 token),存到 /conversation_history/。
Summarization: compacting what's already there · 摘要压缩:压实已在窗口里的
Try as we may to offload verbose tool calls, context will gradually begin to pile up over a long run (e.g. five companies' worth of searches, notes, and drafts). Summarization can be used to condense our agent's entire context window into a summary of what has transpired so far, to allow it to continue on with its research tasks.
卸载再勤,长跑中上下文还是会渐渐堆积(比如五家公司的搜索、笔记与草稿)。Summarization 用来把 agent 的整个上下文窗口压成「到目前为止发生过什么」的摘要,让它继续研究任务。
The spikes are large tool results/human messages arriving; offloading swaps each one for a short preview before the model sees it, so context only grows by a little. Summarization handles the slow climb: once usage hits 85%, older messages are condensed into a summary and context drops back down.
(图示口径)尖峰=大工具结果/人类消息到达:卸载在模型看到之前就把每个尖峰换成短预览,上下文只涨一点点;摘要处理缓慢爬升——用量到 85% 时旧消息压成摘要、上下文回落。
SummarizationMiddleware checks token usage right before each model call. Once usage crosses a threshold (85% of the model's context window by default), a separate LLM call condenses older messages into a single summary. Older messages are removed from the context window while the most recent messages are kept verbatim. The model now sees the summary first, then the recent messages (so nothing recent gets paraphrased).
SummarizationMiddleware 在每次模型调用前检查 token 用量:一旦越过阈值(默认模型上下文窗口的 85%),一次独立的 LLM 调用把旧消息压成一条摘要。旧消息移出窗口,最近的消息逐字保留——模型先看到摘要、再看到近期消息(最近的内容不会被转述失真)。
Two important details: It's recoverable. The summarized messages are written to /conversation_history/{session_id}.md. If the agent needs a detail from Company A's research while drafting, it can read it back. It cycles. As the run continues, usage climbs again, and the next summary includes the previous one.
两个重要细节:**可恢复**——被摘要的消息写到 /conversation_history/{session_id}.md,起草时需要 A 公司调研的某个细节,能读回来;**可循环**——运行继续、用量再爬升,下一次摘要会包含上一次的摘要。
You can also summarize when the topic changes, not just at a certain token threshold. It can be helpful to customize the summarization prompt. Our post on context management for Deep Agents covers both in more detail.
也可以在话题切换时触发摘要,而非只按 token 阈值;自定义摘要提示词也有用。我们的 Deep Agents 上下文管理一文对两者有更细的展开。
Skills: load information only when it's needed · 技能:信息只在需要时加载
Say your sales team has a specific format for quarterly business reviews. The agent only needs those instructions once a quarter, so keeping them in the system prompt means paying for them (in tokens and response time) on every call. Instead, you can package this information as a skill.
假设销售团队对季度业务评审(QBR)有特定格式。agent 一个季度才需要一次这些说明,放进 system prompt 意味着每次调用都为它们付费(token 与响应时间)。更好的做法是打包成一个 skill。
A skill is a folder of instructions (with optional scripts and reference docs) that give an agent what it needs for a specialized task. The agent sees a short description up front and loads the full instructions for qbr-report only when a QBR comes up (other tasks never carry them).
Skill 是一个说明文件夹(可带脚本与参考文档),给 agent 完成专门任务所需的一切。agent 预先只看到一句简短描述,只在 QBR 真的到来时才加载 qbr-report 的完整说明(其他任务永远不带它们)。
Skills load context in layers, so the window stays small until something is actually relevant. This is called progressive disclosure: the model sees a "menu" up front and pulls in the full recipe when it needs it, so ten skills cost about as much context as ten one-liners.
Skill 分层加载上下文,窗口在真正相关之前保持小巧。这叫渐进披露(progressive disclosure):模型先看「菜单」,需要时才取完整菜谱——十个技能的上下文成本约等于十行简介。
You point the agent at your skills, and SkillsMiddleware uses two hooks: Before the agent starts, it scans the skills folder and reads only the header of each SKILL.md. On every model call, it adds those names and descriptions to the system prompt. The full instructions enter context only when the model decides a skill is relevant (and reads it with a read_file tool), so our agent researches without the template and only loads it once it's time to format a QBR.
把 agent 指向你的 skills,SkillsMiddleware 用两个钩子干活:agent 启动前,扫描 skills 文件夹、只读每个 SKILL.md 的头部;每次模型调用时,把这些名字与描述加进 system prompt。完整说明只在模型判定某个 skill 相关(并用 read_file 读它)时才进入上下文——所以我们的 agent 调研时不带模板、一身轻装,直到要排版 QBR 才加载它。
Subagents: isolate the noisy work · 子代理:隔离噪声工作
Offloading effectively combats oversized results, but subagents are a good design choice for work you already know will be noisy (like researching a company across dozens of searches and pages). The subagent does that work in its own context window and returns only the final result so that the main agent never sees the "noise".
卸载能有效对付超大结果,但对于**已知**会很吵的工作(比如横跨几十次搜索与页面的公司调研),subagent 是更好的设计选择:它在自己的上下文窗口里干完活、只返回最终结果——主 agent 从头到尾见不到那些「噪声」。
SubAgentMiddleware allows us to customize the system prompt and tools available to our subagents. market_researcher = { "name": "market-researcher", "description": "Researches a company and returns the 3 most notable developments.", "system_prompt": "Use pull_market_report, then return 3 short bullet points. Do not return the raw report.", "tools": [pull_market_report], } agent = create_deep_agent(model=model, subagents=[market_researcher]).
SubAgentMiddleware 让我们定制 subagent 的 system prompt 与可用工具:market_researcher 配置(name=market-researcher、描述=调研一家公司并返回 3 条最显著的动态、system_prompt=用 pull_market_report 然后返回 3 条短要点、不要返回原始报告、tools=[pull_market_report]),再经 create_deep_agent(model=model, subagents=[market_researcher]) 挂上。
In our case, the main agent hands each company to the market-researcher subagent. The researcher subagent reads the full report in its own context and returns just three bullets, so the main agent only sees these three bullets (not even a preview of the raw report). Additionally, since subagent tasks tend to be small and well scoped, they can often run on a cheaper model and in parallel.
我们的场景里,主 agent 把每家公司交给 market-researcher 子代理。研究员子代理在自己的上下文里读完整报告、只回三条要点——主 agent 只看到这三条(连原始报告的预览都没有)。另外,subagent 任务通常小而边界清晰,往往可以跑在更便宜的模型上、还可以并行。
Long-term memory: persist across conversations · 长期记忆:跨对话延续
By the end, your agent will have learned a lot. Some of it useful, some of it not.
到最后,你的 agent 会学到很多东西。有些有用,有些没用。
Say you tell your agent, "Use bullet points in the summary, not paragraphs." Without memory, you could be repeating that every week. In Deep Agents, long-term memory is a markdown file. You point the agent at it with one argument, and MemoryMiddleware handles the rest. Load: the file is read at the start of a run. Inject: its contents are added to the system prompt on every model call. Update: when the agent learns something worth keeping, like your formatting preference, it updates the file.
假设你告诉 agent「摘要用要点,别用段落」。没有记忆的话,这事你每周都得重说一遍。Deep Agents 里,长期记忆是一个 markdown 文件——一个参数把 agent 指向它,MemoryMiddleware 包办其余:**加载**(Load),运行开始时读入文件;**注入**(Inject),每次模型调用把内容加进 system prompt;**更新**(Update),agent 学到值得保留的东西(比如你的格式偏好)时更新文件。
Swap the model, keep the memory · 换模型,留记忆
Deep Agents is provider agnostic, and that carries through to memory. Because memory is a plain file in your own store (not something a provider holds onto), you can point the same backend at a different model: agent = create_deep_agent( model="openai:gpt-6", # different provider, same memory memory=["/memories/AGENTS.md"], backend=backend, store=store, ). Next week, a different model could read the same file and still write the summary in bullets.
Deep Agents 供应商中立,这一点贯穿到记忆:因为记忆是自有存储里的纯文件(不是供应商攥着的东西),你可以把同一后端指向不同的模型——create_deep_agent(model="openai:gpt-6"(换供应商,同一份记忆)、memory=["/memories/AGENTS.md"]、backend、store)。下周换个模型读同一个文件,摘要照样写成要点。
Context engineering strategies to keep in mind · 值得记住的上下文工程策略
Whether you build on Deep Agents, use another harness, or build one yourself, here are some things to look out for: Large inputs should be offloaded, not truncated—truncation is lossy, offloading keeps it retrievable. Compaction should be recoverable—after summarization, the agent can still get back the detail it needs. Know-how should load on demand—instructions for every task in the system prompt cost context on every call. Noisy work should be isolated—subagents with their own context keep the main agent focused. You should own the memory—memory in storage you control survives a model or provider switch. Defaults should be customizable—thresholds that suit one task rarely suit every task.
无论基于 Deep Agents、用别的 harness 还是自己造,几条原则值得记:**大输入应卸载不应截断**——截断有损,卸载保持可取回;**压缩必须可恢复**——摘要之后 agent 仍能找回所需细节;**知识应按需加载**——每个任务的说明常驻 system prompt,等于每次调用都付上下文成本;**噪声工作应隔离**——有独立上下文的 subagent 让主 agent 保持专注;**记忆应归你所有**——自有存储里的记忆在换模型换供应商后依然存活;**默认值应可调**——适合一个任务的阈值很少适合所有任务。
Try it · 试一试
uv add deepagents. Want to learn more from a live instructor? I'll be covering this on November 3rd: Register HERE! To go deeper on context engineering, check out our free, self-paced Deep Agents course on LangChain Academy.
uv add deepagents 即装。想跟直播讲师学?11 月 3 日我会讲这个主题(原文有注册链接)。想深入上下文工程,看 LangChain Academy 免费自步课程。