我做的 AI Agent 跑长任务时跑着跑着就开始报上下文超长、回答还越来越糊涂,我对着疯狂飙升的 token 账单排查了大半天才搞懂上下文得管理的复盘
这是一个让我对"AI Agent 的上下文"彻底重视起来的故事。我做了一个能自己调用工具、多步推理的 AI Agent,让它去完成一些需要好多轮"思考→调用工具→看结果→再思考"的复杂任务。短任务里它表现很好。可一旦任务变长、需要十几二十轮交互,怪事就来了:它跑着跑着,就开始报错:context length exceeded(上下文超长),直接中断;就算没报错,它的回答也越到后面越糊涂——忘了前面说过的关键信息、重复做已经做过的事、答非所问;与此同时,我的 API token 账单,以肉眼可见的速度疯狂飙升,长任务的成本高得吓人。
我一开始以为是模型能力不行,换了更大上下文的模型,只是把问题推迟了,治标不治本。直到我把每一轮真正发给模型的 prompt 打印出来,才终于揭开真相,补上了我对 Agent 工程一个最致命的认知漏洞:问题的核心,是我从来没有"管理"过 Agent 的上下文——我的做法,是把从任务开始到现在的所有历史,一字不漏地全部塞进每一次的 prompt 里:第一轮的思考、第一次工具调用的完整返回结果、第二轮的思考、第二次工具调用的完整返回结果……全都累积着,一轮都不删。这就导致了一个致命的恶性循环:因为 LLM 是无状态的,它不"记得"之前的对话,你每一轮,都必须把"全部历史"重新发给它,它才"知道"之前发生了什么;而随着任务进行,这个"历史",只增不减、单调地、线性地膨胀;尤其是,某些工具的返回结果非常大(比如一次读取了整个文件、或查询返回了几百条数据),它们原封不动地、永久地占据着上下文。于是:token 数,随着轮次越滚越大——这第一,让成本线性甚至超线性飙升(因为每轮都为全部历史付费);第二,迟早会撑爆模型的上下文窗口上限,报 context length exceeded;第三,即使没撑爆,过长的、塞满了无关信息的上下文,也会让模型"注意力"涣散、抓不住重点("lost in the middle",中间的信息容易被忽略),从而变笨、变糊涂。我这才痛彻地明白:Agent 的"上下文(context)",是它极其宝贵、且容量有限的"工作记忆";它不是一个可以无限堆放历史的垃圾桶。一个能跑长任务的 Agent,其核心能力之一,根本不是"推理"本身,而是"上下文管理(context management)"——即在有限的上下文窗口里,精心地、动态地,只保留对当前决策最有用的信息。不做上下文管理,任何 Agent,都跑不远。
故障现场:无脑累积全部历史,token 单调膨胀
我把这个"上下文爆炸"的现场,用伪代码摊开给你看:
# ✗ 灾难: 每轮把"全部历史"无脑塞进 prompt, token 只增不减
messages = [{"role": "system", "content": SYSTEM_PROMPT}]
def agent_loop(task):
messages.append({"role": "user", "content": task})
while not done:
# ✗ 每轮都把"从头到现在的所有 messages"发给模型
resp = llm.chat(messages=messages) # ✗ messages 越来越长!
messages.append({"role": "assistant", "content": resp.thought_and_action})
if resp.tool_call:
result = call_tool(resp.tool_call) # ✗ 工具结果可能巨大(读了整个文件)
# ✗ 把完整的、巨大的工具结果, 原封不动追加进上下文, 永不清理
messages.append({"role": "tool", "content": result}) # 可能几万 token!
# 为什么会爆炸?
# - LLM 无状态: 它不记得之前的对话, 每轮必须把"全部历史"重发它才"知道"。
# - 所以 messages 只增不减, 随轮次单调、线性膨胀。
# - 大的工具返回(整个文件/几百条数据)原封不动永久占着上下文。
# 三个后果:
# 1. 成本飙升: 每轮都为"全部历史"付费 → token 费用随轮次超线性增长。
# 2. 撑爆窗口: 迟早超过模型上下文上限 → context length exceeded → 中断。
# 3. 变笨: 过长上下文 → 注意力涣散, "lost in the middle", 抓不住重点 → 答糊涂。
# 现象: 长任务跑到中后段报上下文超长 / 回答越来越糊涂 / 账单飙升。
# 根因: 没做上下文管理, 无脑累积全部历史(尤其大工具结果), token 单调膨胀。
看着这段伪代码,我才算彻底想明白了这场"上下文爆炸"的根源。问题的核心,是我每一轮,都把"从头到现在的所有 messages",无脑地全部发给模型,而 messages 只增不减。为什么会这样?因为 LLM 是无状态的——它不记得之前的对话,你每一轮都必须把"全部历史"重发给它,它才"知道"发生过什么;于是 messages 随轮次单调、线性地膨胀;而某些大的工具返回(读了整个文件、查了几百条数据)还会原封不动地、永久地占着上下文。这带来三个后果:第一,成本飙升——每轮都为"全部历史"付费,token 费用随轮次超线性增长;第二,撑爆窗口——迟早超过模型上下文上限,报 context length exceeded 中断;第三,变笨——过长的上下文让模型注意力涣散、"lost in the middle"(中间信息被忽略),抓不住重点、回答糊涂。归根结底:没做上下文管理,无脑累积全部历史(尤其是大的工具结果),token 单调膨胀——这,就是上下文爆炸、成本飙升、回答变糊涂的根源。
第一件事:搞懂上下文是有限的"工作记忆"
定位到根源,我必须把"Agent 的上下文"这件事,从根上彻底搞清楚:
上下文是 Agent 有限的"工作记忆", 必须主动管理
# 为什么必须每轮重发全部历史?
# - LLM 是"无状态"的: 它不记得上一次调用, 每次都是"全新的"。
# - 它对"过去"的全部认知, 仅来自你这次 prompt 里塞进去的内容。
# - 所以多轮 Agent = 每轮把"它需要知道的历史"重新喂给它。
# 上下文窗口: 有硬上限
# - 每个模型有最大 token 数(如 8k/32k/128k/200k...)。
# - 输入(全部历史) + 输出, 都算在内 → 历史越长, 留给思考/输出的越少。
# - 超过上限 → 直接报错, 无法继续。
# 成本: 按 token 计费
# - 每轮都把全部历史发一遍 → N 轮任务的总 token ≈ 历史长度的累加 → 超线性。
# - 大工具结果若每轮都带着 → 成本雪上加霜。
# 质量: 上下文不是越长越好
# - "lost in the middle": 信息在长上下文中间位置容易被模型忽略。
# - 塞满无关信息 → 信噪比下降 → 模型抓不住当前该关注的重点 → 变笨。
# 关键认知: 上下文是稀缺资源, 要"经营", 不能"堆放"。
# - 把它当成一块容量有限的白板: 只写"现在最该看的", 旧的没用的要擦掉。
# - Agent 的核心能力之一 = 在有限上下文里维持"有效的工作记忆"。
# 核心: LLM 无状态 → 每轮重发历史; 上下文窗口有硬上限、按 token 计费、
# 且过长会变笨; 上下文是稀缺的工作记忆, 必须主动管理而非无脑堆积。
原理终于清晰了。为什么每轮都要重发全部历史?——因为 LLM 是"无状态"的:它不记得上一次调用,每次都是"全新的";它对"过去"的全部认知,仅来自你这次 prompt 里塞进去的内容;所以多轮 Agent,就是每轮把"它需要知道的历史"重新喂给它。而上下文窗口有硬上限:每个模型有最大 token 数(8k/32k/128k……),输入(全部历史)+ 输出都算在内,历史越长、留给思考和输出的就越少,超过上限就直接报错。成本上,每轮都发全部历史,N 轮任务的总 token 是历史长度的累加,超线性增长;大工具结果若每轮都带,雪上加霜。质量上,上下文不是越长越好——"lost in the middle"(信息在长上下文中间位置容易被忽略)、塞满无关信息会让信噪比下降,模型抓不住当前重点、变笨。由此,我刻下一个关键认知:上下文是稀缺资源,要"经营",不能"堆放"——把它当成一块容量有限的白板:只写"现在最该看的",旧的没用的要擦掉;Agent 的核心能力之一,就是在有限上下文里维持"有效的工作记忆"。归根结底:LLM 无状态故每轮重发历史;上下文窗口有硬上限、按 token 计费、且过长会变笨;上下文是稀缺的工作记忆,必须主动管理,而非无脑堆积。
第二件事:正解——上下文工程,只保留有用的
搞懂了原理,正解就清晰了:做"上下文工程"——主动地压缩、裁剪、外置历史,让每轮的上下文,只装"对当前决策最有用的信息"。
# ✓ 正解: 主动管理上下文 —— 摘要压缩 + 裁剪 + 工具结果外置
def build_context(history, task):
msgs = [{"role": "system", "content": SYSTEM_PROMPT}]
msgs.append({"role": "user", "content": task})
# ✓ 1. 摘要压缩: 把"久远的历史"浓缩成一段摘要, 而不是全文带着
if len(history) > KEEP_RECENT:
old = history[:-KEEP_RECENT]
summary = summarize(old) # 用 LLM 把旧历史压成几句话
msgs.append({"role": "assistant", "content": f"[此前进展摘要] {summary}"})
# ✓ 2. 滑动窗口: 只保留最近 N 轮的完整细节
for h in history[-KEEP_RECENT:]:
msgs.append(h)
return msgs
# ✓ 3. 工具结果外置: 大结果存外部, 上下文里只放"引用/摘要"
def call_tool_managed(tool_call):
result = call_tool(tool_call)
if len(result) > MAX_TOOL_TOKENS:
ref = store_externally(result) # 存到文件/向量库/KV, 返回一个 id
# ✓ 上下文里只放摘要 + 取回方式, 而不是几万 token 的全文
return f"[结果较大已存储, id={ref}] 摘要: {summarize(result)}"
return result
# ✓ 4. 按需取回: 需要细节时, 用一个工具按 id/查询取回相关片段(类似 RAG)
# —— 把"全量历史"从"上下文"转移到"可检索的外部记忆"。
# 几条上下文管理策略:
# - 摘要(summarize): 旧历史压缩成要点。
# - 裁剪/滑窗(truncate): 只留最近 N 轮 + 关键信息。
# - 外置(offload): 大数据存外部, 上下文只放引用, 按需取回。
# - 结构化记忆: 把"已确定的事实/结论"单独存, 避免淹没在对话流里。
# 核心: 做上下文工程 —— 摘要压缩旧历史 + 滑动窗口留最近 + 大工具结果外置只放引用,
# 让每轮上下文只装"对当前决策最有用的信息", token 不再单调膨胀。
修复的核心,是从"堆放"转向"经营"。策略一,摘要压缩:把"久远的历史",用 LLM 浓缩成一段摘要(几句话的要点),而不是全文带着——既保留了"之前干了啥"的关键信息,又大幅压缩了 token。策略二,滑动窗口:只保留最近 N 轮的完整细节,更早的就交给摘要。策略三,工具结果外置(最关键的一招):当工具返回结果很大时,把全文存到外部(文件/向量库/KV),上下文里只放"摘要 + 一个取回 id",而不是几万 token 的全文。策略四,按需取回:当后续真的需要某个细节时,再用一个工具按 id 或查询,把相关片段取回来(这其实就是 RAG 的思想)——把"全量历史"从"上下文"里,转移到"可检索的外部记忆"中。此外,还可以用结构化记忆:把"已经确定的事实/结论"单独存放,避免它们淹没在冗长的对话流里。归根结底:做上下文工程——摘要压缩旧历史 + 滑动窗口留最近 + 大工具结果外置只放引用,让每轮上下文只装"对当前决策最有用的信息",token 就不再单调膨胀。
第三件事:工具返回结果,要在源头就控制大小
这次事故里,"大工具结果撑爆上下文"是重灾区。我意识到,最好的办法是在工具源头就控制输出大小:
工具输出治理: 在源头控制大小, 别把原始大数据灌进上下文
# 为什么工具结果是上下文爆炸的"重灾区"?
# - 一次"读文件"可能返回几万字; "查数据库"可能返回几百条。
# - 这些原始结果若直接进上下文, 单次就能吃掉大半个窗口。
# - 而且它们往往"大部分无关", 真正有用的只是其中一小部分。
# 在工具源头控制输出(设计工具时就考虑):
# 1. 分页/限量: 查询工具默认 LIMIT, 别一次返回全部("只返回前 20 条")。
# 2. 字段裁剪: 只返回需要的字段, 别 SELECT *。
# 3. 摘要化返回: 工具内部先把结果总结成要点再返回(如"共找到 N 条, 关键的是...")。
# 4. 返回引用而非内容: 返回文件路径/记录id, 让 Agent 需要时再精确取。
# Agent 侧的配合:
# - 给工具传"精确的查询条件", 而不是"把所有数据捞回来自己筛"。
# - 拿到大结果先判断: 真的需要全部吗? 还是只要其中一部分?
# 经验法则:
# - 让"筛选/聚合"发生在数据源头(工具内/数据库), 而不是在上下文里。
# - 上下文里流动的, 应该是"提炼过的信息", 不是"原始的海量数据"。
# - 把上下文当"决策依据", 不是"数据仓库"。
# 核心: 工具输出要在源头控制大小(分页/裁剪字段/摘要/返回引用),
# 让筛选聚合发生在数据源, 上下文只承载提炼过的信息。
这套"工具输出治理",是釜底抽薪的一招。为什么工具结果是重灾区?——一次"读文件"可能返回几万字、"查数据库"可能返回几百条,这些原始结果直接进上下文,单次就能吃掉大半个窗口;而且它们往往"大部分无关",真正有用的只是一小部分。所以,最好的办法,是在工具的源头就控制输出(设计工具时就考虑):分页/限量(查询默认 LIMIT,别一次返回全部)、字段裁剪(只返回需要的字段,别 SELECT *)、摘要化返回(工具内部先把结果总结成要点)、返回引用而非内容(返回文件路径/记录 id,让 Agent 需要时再精确取)。Agent 侧也要配合:给工具传精确的查询条件(而不是"把所有数据捞回来自己筛"),拿到大结果先判断"真的需要全部吗"。我总结的经验法则是:让"筛选/聚合"发生在数据源头(工具内/数据库),而不是在上下文里;上下文里流动的,应该是"提炼过的信息",不是"原始的海量数据";把上下文当"决策依据",不是"数据仓库"。归根结底:工具输出要在源头控制大小(分页/裁剪/摘要/返回引用),让筛选聚合发生在数据源,上下文只承载提炼过的信息。
下面这张图,是这次"上下文爆炸"的成因与治理:
第四件事:几种上下文管理策略的对比
这次踩坑后,我把常见的上下文管理策略,按"省 token、保信息、复杂度"几个维度横向比了一遍。
| 策略 | 做法 | 优点 | 代价/注意 |
|---|---|---|---|
| 滑动窗口 | 只留最近 N 轮 | 简单、稳定省 token | 会丢早期信息, N 太小会失忆 |
| 摘要压缩 | 旧历史 LLM 压成要点 | 保留关键信息又省 token | 摘要本身要花一次调用, 可能丢细节 |
| 工具结果外置 | 大结果存外部, 只留引用 | 从源头消除最大占用 | 需要外部存储 + 取回工具 |
| 结构化记忆 | 事实/结论单独存取 | 关键信息不被对话流淹没 | 要设计记忆的读写结构 |
| RAG 按需检索 | 外部记忆里检索相关片段 | 历史再多也只取相关 | 引入检索, 相关性依赖 embedding |
把它们排在一起,选择就清楚了:这些策略不是互斥的,而是该组合使用。一套实用的组合拳是:滑动窗口保最近几轮的完整细节(简单稳定)、摘要压缩把更早的历史浓缩成要点(保信息又省 token)、工具结果外置从源头消除最大的占用(大结果只留引用)、再用 RAG 按需检索在需要时从外部记忆精确取回相关片段。它们各有取舍:滑动窗口简单但会失忆(N 太小)、摘要本身要花一次调用且可能丢细节、外置需要外部存储和取回工具、RAG 相关性依赖 embedding 质量。这张表给我的最大启发是:"上下文管理"本身,已经是一个独立的、值得精心设计的工程子系统了——它决定了你的 Agent,究竟是只能跑几轮的"玩具",还是能持续作业的"生产力工具"。Agent 的能力上限,很大程度上,不取决于模型多聪明,而取决于你把它有限的"注意力",经营得有多好。
第五件事:Agent 长任务里其他几个高频坑
顺着上下文这条主线,我把 Agent 跑长任务时其他几个高频踩的坑,一并梳理排查了。
| 坑 | 后果 | 对策 |
|---|---|---|
| 上下文无脑累积 | 超窗/成本飙升/变笨 | 摘要+滑窗+外置(本文) |
| 大工具结果直接进上下文 | 单次吃掉大半窗口 | 源头分页/裁剪/摘要/返回引用 |
| 没有步数/成本上限 | 死循环烧光预算(见护栏篇) | 设最大步数 + 成本预算熔断 |
| 不校验工具输出就用 | 错误累积、跑偏越来越远 | 每步校验工具结果再决策 |
| 所有信息平铺进 prompt | 关键指令被淹没 | 分层: 系统指令/任务/记忆/当前 分区放 |
| 关键事实只存对话流 | 被滑窗/摘要冲掉就丢了 | 关键结论写进结构化记忆持久保留 |
这张表,几乎是一份"Agent 长任务避坑总纲"。上下文无脑累积(本文)和大工具结果直接进上下文,是两大头号杀手,治法就是摘要+滑窗+外置和源头控制输出。其余的坑也都很真实:没有步数/成本上限,会让 Agent 一旦跑偏就烧光预算(要设最大步数 + 成本预算熔断);不校验工具输出就用,会让错误一步步累积、越跑越偏(要每步校验再决策);所有信息平铺进 prompt,会让关键指令被淹没(要分层、分区放置:系统指令/任务/记忆/当前状态);关键事实只存在对话流里,会被滑窗或摘要冲掉而丢失(要写进结构化记忆持久保留)。它们共同指向一个认知:做一个能跑长任务的 Agent,真正的难点,从来不在"让它思考一步",而在于"如何让它在几十、上百步的长跑中,始终保持清醒、聚焦、不偏航、不失忆、不破产"——而这,几乎全是"上下文与状态的工程",而非"模型本身"的事。
第六件事:设计一个 Agent 时,我现在会怎么决策
现在,每当我设计一个要跑长任务的 Agent,脑子里都会过一遍这张决策图——核心就一句:把上下文当成一个要主动经营的有限资源。
这张图的灵魂,是把"上下文经营"提升为 Agent 设计的第一等公民。第一问:任务会有很多轮交互吗?——几轮就完的,简单累积无妨(但仍要设上限);十几轮以上的长任务,就必须做上下文管理。然后多管齐下:滑动窗口保最近 N 轮细节、摘要压缩把更早历史压成要点、工具结果源头限量 + 大结果外置只放引用、关键事实写进结构化记忆(别只存易被冲掉的对话流)。再加上护栏与校验:最大步数 + 成本预算熔断(防失控)、每步校验工具输出再决策(防跑偏)。最后,贯穿始终:监控每一轮的 token 消耗,真正把上下文当成一个有限的、需要主动经营的资源来对待。
我立下的几条规矩
这场"上下文爆炸、成本飙升、越答越糊涂"的事故,换来了我做 AI Agent 时,刻进骨子里的几条铁律:
- 上下文是有限的工作记忆,要经营不要堆放。LLM 无状态、每轮重发历史、窗口有硬上限——长任务必须主动管理上下文。
- 用摘要+滑动窗口控制历史长度。最近 N 轮留细节,更早的压成摘要,token 不再单调膨胀。
- 大工具结果一律外置,只放引用。这是上下文爆炸的最大来源;全文存外部,需要时按 id/检索取回。
- 工具输出在源头就控制大小。分页、裁剪字段、摘要化返回、返回引用——让筛选发生在数据源,不在上下文。
- 关键事实写进结构化记忆。别让重要结论只存在对话流里,被滑窗/摘要冲掉就丢了。
- 长任务必加护栏。最大步数、成本预算熔断,防止失控烧光预算(配合死循环护栏)。
- 监控每轮 token。token 单调上涨就是没管好上下文的信号,用数据盯住它。
附:一个带上下文管理的 Agent 循环骨架
把前面讲的策略落到一起,这是我现在写 Agent 循环的"带上下文管理"骨架,可以直接参照:
# ✓ 带上下文管理 + 护栏的 Agent 循环骨架
MAX_STEPS = 30
TOKEN_BUDGET = 200_000
KEEP_RECENT = 6
MAX_TOOL_TOKENS = 2_000
def run_agent(task):
history = [] # 完整历史(留存, 但不全发给模型)
facts = [] # ✓ 结构化记忆: 已确定的关键事实/结论
spent = 0
for step in range(MAX_STEPS): # ✓ 护栏1: 最大步数
if spent > TOKEN_BUDGET: # ✓ 护栏2: 成本熔断
return finalize(facts, "预算用尽")
# ✓ 每轮"构建"上下文(而不是无脑累积)
ctx = [{"role": "system", "content": SYSTEM_PROMPT}]
ctx.append({"role": "user", "content": task})
if facts: # ✓ 关键事实始终带上(不会被冲掉)
ctx.append({"role": "assistant", "content": "[已知事实] " + "; ".join(facts)})
if len(history) > KEEP_RECENT: # ✓ 旧历史摘要化
ctx.append({"role": "assistant",
"content": "[此前进展摘要] " + summarize(history[:-KEEP_RECENT])})
ctx += history[-KEEP_RECENT:] # ✓ 最近 N 轮留完整细节(滑动窗口)
resp = llm.chat(messages=ctx)
spent += resp.usage.total_tokens # ✓ 监控 token
history.append({"role": "assistant", "content": resp.content})
if resp.is_final:
return resp.answer
# ✓ 工具调用: 结果校验 + 大结果外置 + 关键事实抽取
result = call_tool(resp.tool_call)
if not validate(result): # ✓ 校验工具输出再用
history.append({"role": "tool", "content": f"[工具出错] {result.error}"})
continue
if len(result) > MAX_TOOL_TOKENS: # ✓ 大结果外置, 只放引用+摘要
ref = store_externally(result)
history.append({"role": "tool", "content": f"[大结果已存 id={ref}] {summarize(result)}"})
else:
history.append({"role": "tool", "content": result})
if key_fact := extract_fact(result): # ✓ 把关键结论沉淀进结构化记忆
facts.append(key_fact)
return finalize(facts, "达到最大步数")
# 核心: 每轮"构建"上下文(系统+任务+事实记忆+旧摘要+最近N轮), 而非无脑累积;
# 叠加步数/预算护栏、工具结果校验与外置、关键事实沉淀, 才能稳定跑长任务。
这个骨架,把前面所有的策略,拧成了一股绳。它最核心的转变,是每一轮都"构建(build)"一个上下文,而不是"累积(append)"一个上下文:每轮的 ctx,都是当场拼装出来的——系统提示 + 任务 + 结构化的"已知事实" + 旧历史的摘要 + 最近 N 轮的完整细节;它始终维持在一个可控的大小,绝不随轮次膨胀。而它还叠加了这一系列的工程保障:最大步数和成本预算两道护栏(防失控)、每轮监控 token(用数据盯住)、工具结果先校验再用(防跑偏)、大结果外置只放引用(防爆炸)、以及把关键结论沉淀进 facts 结构化记忆(防遗忘)。把这些放在一起,你会发现:一个能稳定跑长任务的 Agent,其"循环"里,真正"调用模型"的代码只有一行;而围绕着它的、那些关于"该给它看什么、记住什么、何时停下"的工程代码,才是让它从"能跑两步的 demo"蜕变为"能干活的系统"的关键所在。这,正是我想用这段骨架,留给每一个 Agent 开发者的最后一句话:模型只是引擎,而你为它构建的"上下文与记忆系统",才是真正决定这辆车能开多远的底盘和方向。
写在最后
回头看,这场由"上下文无脑累积"引发的、Agent 越跑越贵又越糊涂的事故,真正教给我的,是一个关于 AI Agent 工程的、颇为反直觉的洞见:决定一个 Agent"能力上限"的,往往不是它背后那个模型有多聪明,而是你为它设计的"上下文管理"有多精巧。我一开始,把所有希望都寄托在"换个更聪明、上下文更长的模型"上,可那只是把崩溃的时间点,往后推了推而已;真正的破局,发生在我不再把模型当成一个"无限记忆的大脑",而是把它看作一个"极其聪明、却患有严重健忘症、且每一秒注意力都很昂贵"的天才之后——我的工作,从"喂给它越多越好",彻底转变为了"在每一个决策时刻,精心地为它准备好、且仅准备那些它此刻最该看的信息"。这其实是一种深刻的视角转换:从"追求模型的能力",转向"经营模型的注意力";从"给它更多",转向"给它恰好"。在这个意义上,做一个优秀的 AI Agent,更像是在做一名出色的"幕僚长"或"信息策展人":你伺候的那位"决策者"(模型)绝顶聪明,但精力有限、记性极差,你的全部价值,就在于替他过滤掉海量的噪音,在每个关键节点,把最精炼、最相关的简报,递到他面前。经营好那块有限的注意力——这,是我用一次"上下文爆炸"的崩溃,换来的、关于 AI Agent 工程最朴素、也最深刻的领悟。如果这篇复盘,能让你在下一次设计 Agent 时,不再只盯着"用哪个模型",而是多想一句"它的上下文,我该怎么经营",那我对着那份飙升的账单熬的这大半天,就值了。
—— 别看了 · 2026