拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

AI编码代理上下文工程实战:ChatMemory滑动窗口与Context-mode MCP优化

AI编码代理上下文工程实战:ChatMemory滑动窗口与Context-mode MCP优化

1. 为什么上下文工程成了 AI 编码代理的胜负手

1.1 从一次真实的翻车现场说起

去年冬天我接手了一个遗留的 Java 微服务项目,代码量大概在 12 万行左右,模块之间耦合严重,注释覆盖率不到 15%。当时我信心满满地把整个项目丢给一个主流的 AI 编码代理,想着让它帮我梳理一下订单模块的调用链路。结果呢?代理在第三轮对话之后就开始胡言乱语,把OrderService和PaymentService的方法签名混在一起,甚至凭空捏造了一个根本不存在的RefundHandler类。

我一开始以为是模型能力不行,换了个更强的模型,问题依旧。后来我把对话历史打印出来一看,傻眼了——上下文窗口里塞满了前几轮的文件内容、工具调用结果和我的追问,真正关键的当前任务描述被挤到了最边缘的位置,模型根本"看不见"。

这就是典型的上下文污染问题。AI 编码代理和普通聊天机器人最大的区别在于:它需要在一个持续的任务流中反复读写代码、调用工具、维护状态,上下文不是一次性的,而是像滚雪球一样越滚越大。如果不做工程化的管理,再强的模型也会被自己的历史拖垮。

上下文工程(Context Engineering)这个词这两年才逐渐被行业重视,但它的核心思想其实很朴素:在有限的上下文窗口里,动态地、有策略地放置"此刻最该被模型看到的信息"。它和提示词工程(Prompt Engineering)不是一回事——提示词工程关注的是"怎么问",上下文工程关注的是"给模型看什么、看多少、什么时候看、什么时候忘"。

这篇文章我会围绕两个具体的抓手展开:一个是ChatMemory 的滑动窗口机制,另一个是Context-mode MCP 的上下文优化策略。前者解决的是"对话历史怎么裁剪",后者解决的是"工具返回的内容怎么压缩和路由"。两者配合起来,基本能覆盖一个 AI 编码代理 80% 的上下文管理需求。

适合谁看?如果你正在做 AI 编码代理的开发、正在用 MCP 协议对接各种工具、或者单纯被"代理聊着聊着就失忆"的问题困扰过,这篇内容应该能给你一些可以直接抄作业的思路。

1.2 上下文窗口不是越大越好

很多人有个误区:既然模型支持 128K 甚至 200K 的上下文,那我全塞进去不就行了?

我实测过,在一个 128K 窗口的模型上,当上下文填充到 60% 以上时,模型对中间位置信息的召回率会明显下降。这个现象在业界被称为"迷失在中间"(Lost in the Middle)。也就是说,上下文长度和有效信息密度是两回事。你塞了 10 万 token 进去,模型真正能稳定利用的可能只有前 2 万和后 1 万。

更现实的问题是成本和延迟。每一次工具调用都要把完整上下文重新送进模型,token 消耗是线性增长的,而响应延迟会随着上下文变长而显著上升。在一个需要几十轮工具调用的编码任务里,不做上下文管理的代理,token 成本可能是优化后的 5 到 10 倍。

所以上下文工程的目标从来不是"塞满窗口",而是在正确的时间,把正确的信息,以正确的粒度,放到正确的位置。这句话听起来像废话,但真正落地的时候,每一个"正确"都需要具体的机制来支撑。

2. ChatMemory 滑动窗口:对话历史的裁剪艺术

2.1 ChatMemory 到底在管什么

ChatMemory 这个概念在不同的框架里叫法不太一样,有的叫 ConversationBuffer、有的叫 MessageHistory,但本质都是同一件事:维护一个有序的消息列表,并在每次调用模型前决定哪些消息进入上下文。

一个典型的 ChatMemory 里存的消息类型包括:

  • System Message:系统提示词,定义代理的角色、能力边界、输出格式要求
  • Human Message:用户的输入,包括原始任务描述和后续追问
  • AI Message:模型的回复,可能包含思考过程、工具调用请求
  • Tool Message:工具执行的结果,比如读文件返回的内容、命令执行的输出

这四类消息的"生命周期"是完全不同的。System Message 通常全程保留,Human Message 里的原始任务描述需要长期保留,而 Tool Message 里的文件内容往往只在当前这一步有用,用完就该丢。

如果只是简单地按时间顺序保留最近 N 条消息,会出现一个很尴尬的情况:一次读大文件的操作可能产生一条 5000 token 的 Tool Message,它会把前面好几轮有价值的对话全部挤出窗口。这就是为什么朴素的滑动窗口不够用,需要更细粒度的策略。

2.2 滑动窗口的三种裁剪策略与取舍

我在实际项目里试过三种滑动窗口的实现方式,各有适用场景,下面这张表是我自己的对比总结:

策略核心逻辑优点缺点适用场景
固定条数窗口保留最近 N 条消息实现简单,行为可预测忽略消息长度差异,大消息会挤爆窗口短对话、工具返回内容稳定的场景
Token 预算窗口按 token 数从后往前填充精确控制上下文大小可能截断一条消息的中间部分需要严格控制成本的场景
分层保留窗口System + 首条 Human 永久保留,其余按 token 预算裁剪关键信息不丢失实现复杂度较高长任务、多轮工具调用的编码代理

我最终在编码代理里用的是分层保留窗口,因为它解决了一个核心痛点:原始任务描述不能丢。你想想,一个编码任务可能要进行 30 轮工具调用,如果第 25 轮的时候模型已经忘了用户最初要求"用 Python 3.11 的语法特性",那前面 24 轮的工作可能都要返工。

分层保留的具体做法是这样的:

class LayeredChatMemory: def __init__(self, max_tokens=8000, reserve_ratio=0.3): self.max_tokens = max_tokens self.reserve_ratio = reserve_ratio # 为最新消息预留的比例 self.system_message = None self.first_human_message = None self.recent_messages = [] def build_context(self): # 第一层:System Message 永远保留 context = [self.system_message] # 第二层:首条 Human Message 永远保留(原始任务) context.append(self.first_human_message) # 第三层:从最近的消息往前填充,直到用完预算 budget = self.max_tokens - self._count_tokens(context) recent = [] for msg in reversed(self.recent_messages): msg_tokens = self._count_tokens([msg]) if budget - msg_tokens < 0: break recent.insert(0, msg) budget -= msg_tokens return context + recent

这段代码里有个细节值得说:reserve_ratio这个参数我一般设成 0.3,意思是给最新消息预留 30% 的预算。为什么要预留?因为最新的工具返回结果往往是当前决策的直接依据,如果它被裁掉了,模型就会基于过时信息做判断。这个比例不是拍脑袋定的,我试过 0.2、0.3、0.4 三档,0.3 在大多数编码任务里表现最稳。

2.3 消息摘要:让被裁掉的历史"留个念想"

滑动窗口有个天然的缺陷:被裁掉的消息就彻底消失了。但有些信息虽然不需要原文,却需要"存在过的痕迹"。比如代理前面已经读过pom.xml,知道项目用的是 Spring Boot 3.2,这个结论比文件原文重要得多。

我的做法是在裁剪之前,先对即将被裁掉的消息做一次摘要压缩。具体来说,把连续的 Tool Message 和 AI Message 打包,让模型生成一段 100 到 200 字的摘要,然后作为一条特殊的 System Message 插回上下文。

def summarize_and_evict(self, messages_to_evict): summary_prompt = """请用不超过150字总结以下对话的关键信息, 重点保留:已确认的技术栈、已修改的文件、已发现的问题、待办事项。 不要保留具体的代码内容。""" summary = self.llm.invoke(summary_prompt + format_messages(messages_to_evict)) # 作为一条带标记的系统消息插回 self.recent_messages.insert(0, SystemMessage( content=f"[历史摘要] {summary}", metadata={"type": "summary", "evicted_count": len(messages_to_evict)} ))

这里有个坑我踩过:摘要本身也会消耗 token。如果每裁一次就生成一次摘要,摘要会越积越多,最后反而占满窗口。我的解决办法是给摘要也设一个上限,比如最多保留 3 条摘要,超出的旧摘要再合并成一条。这个"摘要的摘要"机制听起来有点绕,但实测下来能把长任务的上下文稳定控制在预算内。

提示:摘要生成最好用便宜的小模型来做,不要用主模型。摘要质量差一点没关系,它只是"记忆锚点",不是决策依据。

2.4 滑动窗口的触发时机:别等到满了才动手

很多人实现滑动窗口是"被动触发"的——每次调用模型前检查一下,超了就裁。这个思路能用,但不够好。

我现在的做法是主动预判:在每次工具调用返回之后,先估算一下这条 Tool Message 会占多少 token,如果加上它之后会超过预算的 80%,就提前触发一次裁剪和摘要。这样做的好处是避免"临时抱佛脚"式的裁剪——被动裁剪往往只能粗暴地砍掉最近的消息,而主动裁剪可以从容地做摘要、做分层。

估算 token 有个简单的经验公式:英文大约 4 个字符 1 个 token,中文大约 1.5 个字符 1 个 token,代码介于两者之间,大约 3 个字符 1 个 token。这个精度对于预算控制足够了,不需要上真正的 tokenizer,那样反而拖慢速度。

3. Context-mode MCP:工具返回内容的压缩与路由

3.1 MCP 协议为什么让上下文问题雪上加霜

MCP(Model Context Protocol)这两年在 AI 编码代理圈子里火得不行,它把各种工具(文件系统、浏览器、数据库、IDE)统一成一套标准接口,代理可以通过 MCP Server 调用它们。但便利的背后是新的上下文挑战:每个 MCP 工具返回的内容格式、粒度、大小都不可控。

我举个例子。用 Playwright MCP 让代理去抓一个网页,返回的可能是完整的 DOM 树,动辄几万 token;用文件系统 MCP 读一个日志文件,可能返回几千行;用数据库 MCP 查一次,可能返回一个几百行的结果集。这些内容如果原封不动塞进上下文,几轮下来窗口就爆了。

更麻烦的是,MCP 工具返回的内容里大量是噪音。DOM 树里 90% 是样式和布局信息,日志文件里大部分是重复的 INFO 级别记录,数据库结果集里可能只有几列是当前任务关心的。上下文工程在这里的核心任务就是:在工具返回结果进入上下文之前,先做一次"提纯"。

3.2 Context-mode 的三种压缩手段

我在自己的代理里实现了一套 Context-mode 处理层,夹在 MCP 工具和 ChatMemory 之间,专门负责对工具返回内容做压缩。核心手段有三种:

第一种是结构化裁剪。针对不同工具返回的格式,用不同的规则提取关键字段。比如 Playwright 返回的 DOM,我只保留可见元素的文本内容和交互属性,把 style、class 里的样式类名全部剥掉。数据库结果集只保留前 50 行和列名,超出部分用"还有 N 行未显示"代替。

第二种是语义摘要。对于非结构化的长文本(比如日志、报错堆栈),用一个小模型做摘要,只保留错误类型、关键行号、异常信息。这里的关键是摘要要保留可操作性——比如报错堆栈,行号和异常类名必须保留,因为代理后续可能要基于这些信息去定位代码。

第三种是引用替代。对于大文件,不把内容塞进上下文,而是把内容存到一个临时的"上下文存储"里,只在上下文里放一个引用 ID 和一段简短描述。代理需要看具体内容时,再通过一个专门的工具去取。这个思路有点像操作系统的虚拟内存——物理内存(上下文窗口)里只放当前活跃的页,其余的存在磁盘(外部存储)上。

class ContextModeProcessor: def __init__(self, storage, summarizer, max_inline_tokens=1500): self.storage = storage self.summarizer = summarizer self.max_inline_tokens = max_inline_tokens def process(self, tool_name, raw_result): tokens = estimate_tokens(raw_result) # 小结果直接内联 if tokens <= self.max_inline_tokens: return raw_result # 大结果走引用模式 ref_id = self.storage.put(raw_result) summary = self.summarizer.summarize(tool_name, raw_result) return f"""[工具 {tool_name} 返回内容已存储] 引用ID: {ref_id} 摘要: {summary} 如需查看完整内容,请调用 fetch_context(ref_id="{ref_id}")"""

这套机制实测下来,能把工具返回内容的平均 token 占用降低 70% 以上,而且代理的任务完成率没有明显下降——因为它需要细节的时候,知道去哪里取。

3.3 上下文路由:让不同的信息去不同的地方

Context-mode 的另一个核心能力是路由。不是所有信息都该进对话上下文,有些信息更适合放在别的地方。

我把代理运行时的信息分成了三个"存储层":

  • 对话上下文:当前任务相关的、需要模型直接看到的信息,容量最小,最宝贵
  • 工作记忆:任务执行过程中的中间状态,比如已修改的文件列表、已执行的命令历史,通过工具按需查询
  • 长期记忆:跨任务的知识,比如项目的技术栈约定、代码规范,通过检索注入

路由的规则我总结成一句话:"决策依据进上下文,执行记录进工作记忆,背景知识进长期记忆"。

举个例子,代理在重构一个函数时,"这个函数当前的实现"是决策依据,要进上下文;"之前已经改过哪几个函数"是执行记录,进工作记忆;"这个项目的命名规范"是背景知识,进长期记忆。这样分层之后,上下文里永远只有当前这一步真正需要的东西。

注意:路由规则不要写得太复杂,我见过有人搞了七八层存储,结果代理自己都搞不清信息在哪。三层足够了,再多就是过度设计。

3.4 与 ChatMemory 的协同:谁先谁后

Context-mode 和 ChatMemory 的调用顺序很关键。我的实践是:MCP 工具返回 → Context-mode 压缩 → 写入 ChatMemory → ChatMemory 裁剪 → 送入模型。

这个顺序不能反。如果先写 ChatMemory 再压缩,那 ChatMemory 里存的就是原始大内容,裁剪的时候会误伤;如果先裁剪再压缩,那压缩的时候可能已经丢失了关键信息。先压缩后裁剪,能保证 ChatMemory 里存的都是"提纯过"的内容,裁剪的粒度也更可控。

还有一个细节:Context-mode 压缩后的引用 ID 要能被 ChatMemory 识别为"可回收"的消息。当引用对应的内容被取用之后,那条引用消息就可以标记为低优先级,在裁剪时优先淘汰。这个机制能让上下文始终保持"新鲜"。

4. 实操:从零搭一套上下文优化流水线

4.1 环境准备与依赖选型

先说技术栈。我用的是 Python 3.11,主要依赖这几个库:

pip install langchain-core langchain-openai mcp tiktoken
  • langchain-core提供消息类型和 ChatMemory 的基础抽象
  • langchain-openai用于调用模型(换成其他厂商的 SDK 也行)
  • mcp是 MCP 协议的官方 Python SDK
  • tiktoken用于精确的 token 计数(预算控制用,估算用经验公式)

模型方面,我建议主模型和辅助模型分开。主模型负责编码决策,用能力强的;辅助模型负责摘要、压缩、路由判断,用便宜快的小模型。这样成本能降下来一大截,而且辅助任务对模型能力要求不高。

4.2 核心模块的代码骨架

整个流水线分四个模块,我按数据流的方向依次说。

模块一:MCP 工具调用层。这一层负责和 MCP Server 通信,拿到原始返回结果。关键是给每个工具调用加上超时和大小限制,避免一个工具返回把整个流程卡死。

async def call_mcp_tool(server, tool_name, params, timeout=30, max_size=1_000_000): try: result = await asyncio.wait_for( server.call_tool(tool_name, params), timeout=timeout ) if len(str(result)) > max_size: result = str(result)[:max_size] + "\n[内容已截断]" return result except asyncio.TimeoutError: return f"[工具 {tool_name} 调用超时]"

模块二:Context-mode 处理器。前面已经给过骨架,这里补充一下摘要提示词的设计。摘要提示词要针对不同工具类型定制,不能一套提示词打天下。

SUMMARIZE_PROMPTS = { "read_file": "总结这个文件的内容,保留:文件用途、关键类/函数名、依赖关系。不要保留具体代码。", "run_command": "总结命令执行结果,保留:退出码、错误信息、关键输出行。", "query_db": "总结查询结果,保留:列名、数据规模、异常值。", "browse_page": "总结网页内容,保留:页面主题、主要交互元素、关键文本。" }

模块三:分层 ChatMemory。前面给过核心逻辑,这里补充消息优先级标记的实现。每条消息写入时打一个优先级标签,裁剪时按优先级从低到高淘汰。

PRIORITY = { "system": 100, "first_human": 90, "summary": 70, "recent_human": 60, "recent_ai": 50, "tool_result": 30, "context_ref": 20 # 引用消息优先级最低,可随时淘汰 }

模块四:上下文组装与调用。最后一步把 ChatMemory 组装成模型能接受的格式,调用主模型。这里要注意消息顺序:System 在前,摘要其次,然后是保留的历史,最后是最近的消息。

4.3 参数调优:几个关键数字的来历

这套流水线里有几个参数直接决定效果,我把调优过程说一下。

max_tokens:这个取决于主模型的窗口大小。我的经验是只用窗口的 50% 到 60%。比如 128K 窗口的模型,我设成 64K 到 76K。留出的空间是给模型输出和突发的大工具返回用的。设太满会导致模型输出被截断,设太少又浪费能力。

max_inline_tokens:工具返回内容内联的阈值,我设的是 1500。这个数字是试出来的——低于 1500 的内容,做引用模式的收益(省下的 token)抵不上引用带来的额外工具调用开销;高于 1500,引用模式就开始划算了。

reserve_ratio:给最新消息预留的预算比例,0.3。前面说过,这个比例保证最新工具返回不会被裁掉。

摘要触发阈值:当被裁消息的总 token 超过 2000 时才触发摘要。太小的裁剪不值得摘要,直接丢就行。

这几个数字不是绝对的,不同模型、不同任务类型会有差异。但作为起点,它们能让你少走很多弯路。

4.4 一次完整的任务执行记录

我拿一个真实任务跑一遍,让你看看这套流水线在实际中怎么工作。任务是:"给这个 Spring Boot 项目加一个订单导出 Excel 的接口"。

第 1 轮:用户输入任务。ChatMemory 里只有 System Message 和这条 Human Message,上下文占用约 800 token。

第 2 轮:代理调用文件系统 MCP 读取项目结构。返回一个 3000 token 的目录树。Context-mode 判断超过 1500 阈值,做摘要压缩到 200 token,原文存入引用存储。上下文占用约 1100 token。

第 3 轮:代理调用 MCP 读取OrderController.java。返回 2500 token。同样压缩,摘要保留类名、方法列表、依赖注入的字段。上下文占用约 1400 token。

第 4 到 10 轮:代理陆续读取了 Service、Mapper、实体类,每轮都走压缩。到第 10 轮时,ChatMemory 里积累了 7 条摘要消息,加上原始任务和最近的对话,上下文占用约 5000 token。

第 11 轮:代理开始写代码,调用文件写入 MCP。返回结果很短("写入成功"),直接内联。此时 ChatMemory 触发了一次裁剪,把第 2 到 5 轮的摘要合并成一条"项目结构摘要",上下文占用回落到 4200 token。

第 12 到 20 轮:代理反复修改代码、运行测试。每次测试失败,返回的报错堆栈被压缩成"错误类型 + 关键行号 + 异常信息"。到第 20 轮,上下文占用稳定在 6000 token 左右。

任务结束:整个任务 20 轮工具调用,如果不用这套流水线,上下文峰值会超过 40000 token;用了之后,峰值控制在 6000 token 以内,token 成本降低约 85%,任务完成质量没有下降。

5. 常见问题与排查技巧实录

5.1 代理"失忆"了怎么办

这是最常见的问题。表现是代理突然问一个前面已经确认过的信息,或者重复执行已经做过的操作。

排查思路按这个顺序走:

  1. 先看 ChatMemory 的裁剪日志。是不是关键消息被裁掉了?如果是,检查优先级标记是否正确,原始任务描述有没有被标记为first_human。
  2. 再看摘要质量。如果关键信息被裁掉但摘要里应该有,那就是摘要生成出了问题。检查摘要提示词是否覆盖了这类信息。
  3. 最后看上下文组装顺序。有时候消息都在,但顺序不对,模型也会"看不见"。System 和摘要必须在前面,最近消息在后面。

我遇到过一次诡异的情况:代理反复忘记"项目用的是 Java 17"。查了半天发现是摘要提示词里写了"不要保留具体代码",结果小模型把"Java 17"也当成代码细节给删了。后来把提示词改成"保留技术栈版本信息",问题解决。

5.2 工具返回内容被压缩后代理无法操作

这个问题的表现是代理说"我需要查看完整内容"但不知道怎么取,或者取回来之后又不会用。

根因通常是引用消息的格式不清晰。代理不知道fetch_context这个工具的存在,或者不知道引用 ID 怎么用。解决办法是在 System Message 里明确说明引用机制:

当工具返回内容被压缩为引用时,你会看到 [工具 X 返回内容已存储] 的标记。 如需查看完整内容,调用 fetch_context 工具并传入引用 ID。

另外,fetch_context返回的内容也要走一遍 Context-mode 处理,避免取回来一个大内容又把上下文撑爆。这里可以设一个"取用后自动摘要"的规则。

5.3 摘要越积越多反而占满窗口

前面提过这个问题,这里给一个具体的解决参数。我设的规则是:

  • 摘要消息最多保留 5 条
  • 超过 5 条时,把最旧的 2 条合并成 1 条
  • 合并后的摘要标记为"二级摘要",优先级比普通摘要低
  • 二级摘要最多保留 2 条,超过就再合并

这样层层收敛,摘要的总量始终有上限。实测在 50 轮以上的长任务里,摘要占用的 token 稳定在 800 以内。

5.4 常见问题速查表

现象可能原因排查动作解决方向
代理重复问已确认信息关键消息被裁查裁剪日志和优先级标记提升关键消息优先级
代理说看不到完整内容引用机制未说明查 System Message补充引用工具说明
上下文占用居高不下摘要未收敛查摘要数量和大小启用摘要合并机制
工具调用超时MCP Server 响应慢查工具调用日志加超时和降级返回
代理输出被截断max_tokens 设太大查上下文占用比例降到窗口的 50%-60%
摘要丢失关键信息提示词覆盖不全查摘要提示词按工具类型定制提示词

5.5 几个我踩过的坑

坑一:用主模型做摘要。一开始图省事,摘要也用主模型,结果成本没降下来,延迟还上去了。后来换成小模型,摘要质量略降但完全够用。

坑二:裁剪粒度太粗。早期我是按"轮"裁剪的,一轮对话要么全留要么全丢。后来改成按消息裁剪,灵活多了。一条大 Tool Message 可以单独被压缩,不影响同一轮的其他消息。

坑三:忽略工具返回的元数据。MCP 工具返回的结果里往往带有元数据(比如文件大小、查询耗时),这些信息对代理决策有用,压缩时不能丢。我现在会在摘要里专门保留一段元数据。

坑四:上下文路由规则写太死。一开始我给每类信息都写死了去哪一层,结果遇到边界情况就卡住。后来改成"默认进工作记忆,显式标记才进上下文",灵活多了。

6. 上下文工程的边界与延伸

6.1 什么情况下这套方案不适用

说实话,这套流水线不是万能的。如果你的任务很短(少于 5 轮工具调用),上这套机制反而是过度设计,直接全量塞上下文更简单。如果任务对细节精度要求极高(比如逐行代码审查),压缩和摘要可能丢失关键信息,这时候宁可牺牲成本也要保留原文。

还有一种情况是工具返回内容本身就很小。如果你的 MCP 工具都是返回几十 token 的短结果,那 Context-mode 的压缩层基本是空转,可以关掉。

判断标准很简单:当上下文占用成为瓶颈时,才需要上下文工程。没到瓶颈就上,是给自己找麻烦。

6.2 可以继续深挖的方向

这套方案目前解决的是"单代理、单任务"的上下文管理。往深了走,还有几个方向值得探索。

多代理协作的上下文隔离。当多个代理协同工作时,每个代理的上下文应该独立管理,只通过明确的接口交换信息。这比共享一个大上下文要清晰得多,也更容易调试。

基于任务阶段的动态策略。编码任务的不同阶段(探索、设计、实现、测试)对上下文的需求是不一样的。探索阶段需要大量文件内容,实现阶段需要精确的接口定义,测试阶段需要报错信息。如果能根据阶段动态调整压缩策略,效果会更好。

上下文质量的度量。现在判断上下文管理好不好,主要靠"代理有没有出错"这种间接指标。如果能有一个直接的度量,比如"关键信息召回率",调优会更有方向。这个方向目前还没有成熟的方案,但值得关注。

6.3 我个人的一点体会

做上下文工程这两年,最大的感受是:它更像是一门"取舍"的手艺,而不是"堆料"的技术。很多人一上来就想把所有信息都留住,结果反而什么都留不住。真正有效的做法是承认上下文的稀缺性,然后逼着自己去判断"什么才是此刻真正重要的"。

这个判断能力,一部分靠机制(优先级、摘要、路由),一部分靠经验(知道什么信息在什么阶段有用)。机制可以抄,经验只能自己攒。我建议你在自己的项目里先把这套流水线跑起来,然后根据实际遇到的问题去调参数、改规则。跑上十几个真实任务之后,你对"什么该留什么该丢"的直觉就会建立起来。

最后分享一个小技巧:给代理加一个"上下文自省"的能力。让它在每次决策前,先输出一句"我当前基于哪些信息做判断"。这句话会逼着代理去检索上下文,也能让你直观地看到它到底"看见"了什么。这个技巧帮我定位过好几次上下文丢失的问题,成本几乎为零,但效果立竿见影。

返回列表