Agent 小知识|上下文预算:让 Agent 知道该看什么

发布时间:2026/7/16 15:51:51
Agent 小知识|上下文预算:让 Agent 知道该看什么 上一期我们聊到Agent 和 Chatbot 最大的差别是工作方式变了Agent 是“你定目标我推进”Chatbot 是“你问我答”。虽然 Agent 看起来很强但它也给我们带来了一个问题如何解决 Agent 每往前走一步产生的新信息。无论是调用工具返回的结果还是需要的资料文件、代码报错信息历史决策记录……这些东西到最后都会以某种形式进入模型的上下文。但模型的上下文窗口再大也有上限。所以Agent 系统里有一个很重要的工程概念上下文预算。先说清楚上下文是什么我们平时和 ChatGPT、DeepSeek、Claude 等 AI 对话时会有一个印象是它“记得”前面我们和它聊过什么。举个例子你让 ChatGPT 解释下什么是 KV Cache。等它解释完之后你继续说“用更适合新手的方式再讲一遍”。这时候你不用重新说明“讲一遍什么”ChatGPT 就知道指的是 KV Cache。模型之所以能接上是因为前面的对话内容一起被放进了当前这次生成的输入。这些被模型“看见”的信息就是上下文。而模型能“看见”的信息包括但不限于用户刚刚输入的话、前面的聊天记录、系统规则、工具说明、检索到的资料、文件内容、代码片段、工具返回结果等等。这里有个知识点模型在生成输出之前只能根据当前上下文窗口被塞进来的内容做判断。那些没有被放进来的信息对模型来说就像不存在——感知不到即为不存在。上下文预算的分配逻辑假设上下文窗口是一张工作台每次模型思考前系统都要把相关材料摆到这张工作台上。但既然上下文是个工作台那它的摆放空间就有限。放得太少模型缺少信息容易给出错误判断放得太多模型不仅会被噪音淹没成本和延迟也会跟着上涨。上下文预算讲的就是在一次模型调用中有限的上下文窗口应该分给谁要分多少给这个信息什么时候要收拾工作台对信息进行压缩和丢弃。上下文预算并不是单纯的 token 上限问题它其实是 Agent 系统的信息调度问题。一个 Agent 能不能长期稳定地跑长任务很大程度上取决于它能不能把每一步需要的“刚好有用的信息”放到模型面前。上下文窗口里有什么上面有简单提过上下文窗口有哪些信息这里我们具体展开看看System Prompt。它定义了 Agent 的身份、规则、边界和任务风格。比如一个代码修复 Agent就不要执行危险命令。修改代码前先要读取文件改完后必须再运行测试。如果遇到删除、提交、发送等动作要请求人类进行确认。这类内容一般比较固定而且优先级高。工具定义。Agent 要调用工具就得知道工具叫什么、能做什么、怎么用参数怎么写、返回结果的格式是什么。像是read_file(path)、write_file(path, content)、run_shell(command)、search_web(query)等调用函数都是 Agent 需要知道的。而 Agent 挂载的工具越多工具定义占用的上下文也就越多。工具太多的话模型每次都要在一堆工具说明里做选择。不仅上下文会被挤占选错工具的概率也会上升。外部知识和记忆。这里主要是 RAG 检索回来的文档片段、项目规范、用户偏好、历史任务经验、代码库结构说明。这些信息是重要但不能无脑全塞进来。同一个任务当前步骤往往只需要一小部分的相关资料。如果把不相关的文档也塞进去只会让模型更难抓住重点。历史记录。Agent 做过什么、调用过什么工具、在哪里失败过、上一步输出了什么结果这些都属于历史。历史最大的问题就是它在不断增长。一次简单问答历史记录可能就几句话。但一个 Agent 跑完十几轮之后工具调用、日志、报错、重试、解释和中间计划就能堆满历史记录。如果每一轮都把完整的历史原样带上上下文窗口很快会爆。输出预留空间。上下文窗口不只给输入用模型还要留出空间来生成回答、计划、工具调用参数或最终报告。如果输入塞得太满输出空间就会被挤压轻则回答变短重则直接截断。所以一个健康的上下文预算既要看“输入还能放多少”还要看“下一步要留多少输出空间”。Agent 的上下文消耗Chatbot 的上下文增长相对可控。你问一句它答一句。大多数时候上下文就是聊天记录。Agent 的情况要复杂得多毕竟它的每一步都生成中间信息。举个例子你让 Agent 修一个 CI 报错。它会先读取测试日志这个日志有几百行报错信息它再查看个配置文件又是几十行数据接着它再运行 shell 命令输出一堆环境信息然后它又修改文件生成 diff再跑测试测试失败的话还会出现新的报错信息。上面这些可能对模型都有用但并不是每一轮都要完整保留。真正要保留的信息只有当前目标、已经排除的原因、最近一次失败、刚刚修改过的文件、下一步需要验证的假设。如果系统没有预算意识Agent 很快就会变成一个“背着所有历史往前跑”的人。跑得越久包就越重包越重走得就越慢要命的是最后还会忘记真正要找的是什么。上下文过载的连锁问题第一个问题是成本变高。每一轮都要带上大量历史、工具定义和文档片段意味着每次调用模型都要处理更多 token。Agent 又是多轮循环系统一次任务可能多次调用模型。单轮多一点整条任务链路就会贵很多。第二个问题是延迟变高。上下文越长模型处理输入越慢。如果每一步都带上大量重复内容用户就会感觉 Agent 一直在“thinking”。第三个问题是注意力变散。长上下文不等于有效上下文。模型看到的信息越多就越不容易找到被淹没的关键线索。真正有用的一行报错可能夹在几千行日志中真正关键的一条用户要求可能被多轮中间对话冲淡。第四个问题是历史污染。Agent 早期做过的错误判断如果一直留在上下文里可能会影响后面的推理。如果一开始它误判是网络问题但后来确认是配置问题。这时候如果旧判断还反复出现在历史记录中可能就会带偏模型。第五个问题是输出空间不够。输入塞得太满时模型留给输出的空间会变小这会影响最终报告、代码修改说明甚至工具调用参数的完整性。所以上下文预算不只是“省 token”还影响了 Agent 的稳定性、成本、速度和任务完成率。上下文管理的四种方式一个成熟的 Agent 系统每一轮调用模型前都应该先做一次“上下文装包”。去判断哪些信息必须带哪些只带摘要哪些要按需检索哪些可以丢弃哪些要给下一步输出预留空间。相对应的上下文信息管理可以分成这四种处理方式固定保留这类信息有系统规则、安全边界、当前任务目标、关键约束。它们决定了 Agent 的行为边界所以每轮都要保留。最近保留这类信息有最近一次工具调用结果、最近一次报错、上一步推理结论。下一步决策强依赖这些信息所以优先保留原文。压缩保留这类信息有更早的执行历史、看过的文件、已排除的原因。我们不一定要原样保留这些信息可以压缩成摘要。比如“已检查 docker-compose.yml发现 DB_HOST 配置错误已修改为 test-db首次 make test 失败原因是数据库容器未启动第二次测试通过。” 这种摘要要比完整保留几百行日志更适合放进上下文。按需加载这类信息有大型文档、完整源码、历史任务记录。这些内容不用常驻上下文。系统可以先把它们放在外部存储等模型真的用到时再检索回来。这也是为什么 Agent 系统经常会同时出现短期记忆、长期记忆、RAG、状态机、工具调用日志、任务检查点、摘要压缩。其实它们解决的是同一个问题让模型在每一步看到刚刚够用的信息。测试修复场景里的上下文取舍假设你让 Agent 做一件事帮我排查这个项目测试失败的原因并尝试修复。一个没有上下文预算意识的 Agent会把完整测试日志、全部package.json、相关源码文件、之前所有工具调用记录、每一次中间思考都塞进上下文再让模型判断下一步要干嘛。这样操作很快就会把上下文窗口撑满。比较推荐的做法是先做信息筛选当前目标保留为“修复测试失败”安全边界保留为“不要删除文件不要提交代码修改前先说明”最近报错保留为“某个测试在数据库连接阶段超时”相关文件只放数据库配置和测试初始化文件旧历史压缩成“已确认依赖安装正常Node 版本正常容器最初未启动”同时还要给下一步计划、工具调用和最终说明留出输出空间。这样虽然模型看到的信息少了但信息更干净。它不用重新阅读所有历史只要知道该怎么继续当前任务就行。注意力预算与任务稳定性我们平时看到“128K 上下文”“1M 上下文”会认为窗口越大产生的问题就越少。但在 Agent 系统中窗口只是上限真正关键的是怎么分配。同样是 128K如果当中塞满了重复日志、过期计划、不相关文档和多余工具说明模型依然会迷路。同样是较小窗口如果系统能把目标、约束、关键观察和下一步需要的信息组织好Agent 也能跑得很稳。所以上下文预算可以理解成 Agent 的注意力预算。它回答的是这几个问题这一步最需要模型看见什么哪些历史会影响当前判断哪些内容应该摘要化哪些内容应该放在外部记忆里哪些工具定义这一步用不上下一步输出需要预留多少空间一个 Agent 之所以能稳定跑长任务除了模型能力之外也依赖背后那套上下文管理方式。模型每一次思考前系统都要先替它整理桌面。小结上下文预算讲的是在有限的上下文窗口里进行信息分配。对于 Chatbot 来说上下文主要是聊天记录对于 Agent 来说上下文会变成一个动态工作台。当中有目标有规则有工具有记忆有检索资料有历史记录还有输出预留空间。Agent 每执行一步都要重新决定该带什么压缩什么丢掉什么检索什么保留什么。而上下文预算就是模型每一次思考前系统要先替它整理桌面。桌面越干净目标越清楚。目标越清楚Agent 才越有可能把长任务跑完。