1. 先把概念说清楚:Agent场景里,“模型的学习”到底指什么
前两天我在梳理 Agent 技术栈的时候,发现一个特别容易混淆的点:很多人把“Agent 会学习”挂在嘴边,但真去追问他“模型到底是怎么学习的”,往往就说不清了。这不是基础不基础的问题,是整个 Agent 领域的术语本身就容易绕晕人。所以这篇精读的开头,我先把这块最容易产生误解的地基给铲平。
先说我的结论:Agent 场景中,“模型的学习”绝大多数时候指的不是重新训练模型,也不是给模型喂更多数据做微调,而是指模型在推理过程中,利用上下文信息进行“动态学习”的能力。也就是所谓的 In-Context Learning(上下文学习)。模型本身的权重没有变化,但它在读取上下文的时候,能够从你给它的示例、工具返回结果、历史对话中“现学现用”。这就像你临时拉了一个人进项目组,不需要他重新上大学,只需要给他看两三条过往项目文档,他就能立刻上手干活——这就是 Agent 的“学习”。
为了更严谨,我把 Agent 项目中“模型的学习”拆成了三个层面:
第一个层面是权重学习(Weight Learning)。这是传统意义上的“训练”,发生在模型真正投入使用之前,比如预训练、指令微调、RLHF。这一层决定了模型的基础能力,但它在 Agent 运行过程中不会发生。你不可能在 Agent 跑任务的时候实时去改模型权重,成本太高,也没有这个必要。
第二个层面是实例对齐(Example Alignment),也就是把几个 few-shot 示例塞到 prompt 里。很多人认为这只是在“给模型看例子”,但更准确的比喻是:这是在给模型划定一个“答题风格”。比如说,你给它看了三个客服对话案例,它就会模仿案例里的语气、信息密度、追问方式。Prompt 里放例子,本质上是在做“即时风格对齐”,而不是在做“知识灌输”。
第三个层面是上下文推理(Context Reasoning),这是 Agent 最核心的学习方式。模型把当前的任务描述、工具返回的报错信息、历史对话中已经尝试过的方案全部拼接在上下文里,然后基于这些信息推导下一步动作。注意,这些信息中有相当一部分是之前几轮才产生的,换句话说,模型是在“读过自己刚刚做过的事情之后”,再来决定下一步怎么做——这是一种动态的、边做边学的机制。
这三个层面搞清楚之后,你就不难理解一个关键问题了:为什么 Agent 项目里大家疯狂追求长上下文?因为上下文就是 Agent 的“短期工作记忆”。窗口越长,模型能“读到”的历史越多,能做的推理就越连贯。1M 上下文之所以成为热门话题,就是因为它在工程层面把工作记忆的容量拉到了一个新的量级。理解了这一点,我们再往下看上下文怎么构成,就顺理成章了。
2. Agent 的“学习”机制,核心是上下文工程
2.1 从提示词工程到上下文工程,到底发生了什么变化
这两年圈子里有个明显的趋势——大家讨论的重心逐渐从“提示词工程(Prompt Engineering)”转移到了“上下文工程(Context Engineering)”。这两个词的区别一开始我以为是噱头,真正跑过几个 Agent 项目之后才发现,两者完全不在一个层级上。
提示词工程的关注点是:怎么用一段精心构造的文字,让模型给出更好的回答。它的对象是单轮、短文本、模型内部的 pattern matching。你调的是措辞、结构、语气,本质上是在“哄模型”。
上下文工程的关注点是:怎么构造、组织、管理模型读取到的所有信息,让 Agent 在多轮工具调用中保持稳定和高效。它的对象是多轮、跨工具、动态变化的完整信息流。你调的是哪些信息该放进来、放在什么位置、什么时候该丢弃、什么时候该滚动出窗口。
我举个具体例子。单轮提示词工程里,你写“请扮演一位资深运维专家,帮我分析这段日志”——这就是全部了。但在 Agent 场景里,你需要同时管理:系统指令、用户当前问题、上一次工具调用返回的报错堆栈、前三次尝试过的命令行历史、从知识库里检索到的运维文档片段、以及本轮模型的推理轨迹。这些信息加起来可能超过一万 token。这时候你面临的核心问题已经变了——不是怎么把问题问得更清楚,而是怎么在一堆信息里让模型找到它真正需要的部分。这就是上下文工程的活儿。
在我自己的 Agent 开发经验里,提示词工程大概只占整个上下文设计的 20% 工作量,剩下 80% 都在做信息架构:什么东西该常驻,什么东西该按需注入,什么东西该压缩,什么东西该直接扔掉。如果你还停留在“把 prompt 写漂亮一点”的思路来做 Agent,大概率会被上下文爆炸、模型跑偏、工具调用失序这些问题折磨得焦头烂额。
2.2 Agent 为什么离不开长上下文:滑动窗口的启示
长上下文不是炫技,而是 Agent 工作方式的硬性需求。要理解这一点,可以从一个和 Agent 关系密切的经典算法——滑动窗口滤波模型——说起。
滑动窗口滤波模型的核心思想是:只对最近一段时间窗口内的数据进行处理,窗口外的旧数据逐步衰减或丢弃。这个算法在信号处理、时间序列预测、流式计算中广泛应用,而在大模型场景里,它几乎就是 Transformer 注意力机制的一种直观形态——模型在生成当前 token 时,注意力权重只会集中在它可见的上下文范围之内,超出范围的内容对当前生成结果“不可见”。
Agent 的推理过程也类似:每一轮工具调用之后,都会产生新的信息(工具返回值、错误日志、中间结果),这些信息进入上下文后,会构成后续推理的依据。模型相当于在一个“滑动的上下文窗口”上持续做决策——窗口够长,就能覆盖更多的历史信息和工具调用链条;窗口被截断,它就只能基于不完整的信息继续干活,结果就是逻辑断裂、重复尝试、甚至幻觉。
这也是为什么 Claude 的 1M 上下文一出来,我身边做 Agent 的朋友几乎都在讨论它。1M token 意味着什么?大约相当于《三体》三部曲的总字数。放到 Agent 场景里,就是模型可以一次性把几十轮工具调用的完整历史、几千行代码文件、多份参考文档全部装进窗口,而不需要频繁压缩和截断。做长任务、跑复杂工作流的时候,这个优势是致命的。
但注意,长上下文不是越多越好。我实测过,上下文窗口拉长之后,模型对早期信息的“注意力”会被稀释——就算是 1M 窗口,模型也并不是对窗口内每个 token 都一视同仁。实际经验是:超过一定长度之后,模型对中部内容的记忆效果明显变差,这就是所谓的“lost in the middle”现象。所以,与其盲目追求超长窗口,不如学会“在合适的位置放合适的信息”。这就是我们接下来要说的内容:上下文的构成。
2.3 上下文如何影响模型输出:一个形象的类比
为了把“上下文影响”这件事讲得更直观,我常用一个类比:上下文就是模型在推理时拿到的“剧本卡”。
想象一个演员(模型)上台演戏。他不可能临时背诵整个剧本,而是靠场务(Agent 框架)在每一幕开始前递给他一叠卡片。卡片上可能写着:你的角色设定(系统指令)、你现在在哪个场景(当前目标)、上一位演员刚刚说了什么(对话历史)、道具组临时改了什么(工具返回值)。这个演员演得好不好,不只看他演技多强,更要看场务递的卡片够不够清晰、有没有相互矛盾、有没有漏掉关键剧情。
这个类比能帮你解释很多 Agent 开发中的怪现象:为什么同一个模型,在一个框架里表现惊艳,换一个框架就蠢得像人工智障?大概率不是模型的问题,而是上下文组织方式变了。为什么有时候模型会反复调用同一个工具、陷入死循环?因为上一轮调用返回的结果没有被正确地放进上下文,模型压根不知道自己已经试过一次了。所以,上下文不是简单的“信息堆叠”,它直接影响模型的行为轨迹——这比单轮 prompt 的影响面要大得多。
3. 上下文的构成:从内到外,拆解每一层信息
3.1 上下文的物理构成:一段拼接起来的 Token 序列
要理解上下文的构成,先看物理层面。大模型接收的输入本质上是一段 token 序列,而 Agent 框架做的“上下文组装”工作,就是把各种来源的信息按某种顺序拼接到这段序列里。
一个典型的 Agent 上下文长这样(按出现顺序):
- 系统指令(System Prompt)
- 工具定义(Tool Schemas)
- 对话历史(Conversation History)
- 外部检索结果/知识库片段(RAG Context)
- 用户当前输入(Current User Message)
- 最近一轮工具调用的返回值(Tool Result)
这套结构绝大多数 Agent 框架都类似,区别在于顺序、截断策略、以及各部分占用的 token 预算。而在实际使用中,模型最先读到的是头部内容,最后读到的是尾部内容。头部内容(系统指令和工具定义)决定了模型的全局行为,尾部内容(工具返回值、当前输入)决定了模型的立即行动,中间部分(对话历史、检索结果)负责提供背景信息支撑。这就是为什么这类信息排列顺序是有讲究的:把不该被忽略的信息放在头部或尾部,把次要信息放在中间,是上下文工程的基本操作。
3.2 上下文的分层视角:人设层、状态层、知识层、即时层
如果从“信息职能”来分类,上下文还可以分成四层。我一般这样划分:
人设层——对应系统指令和固定的任务模板。这层信息描述 Agent 的角色、行为边界、输出格式、解决什么类型的问题。它的特点是几乎恒定不变,每一轮对话都要带上,但内容必须精简,因为它会长期占用上下文空间。写系统指令时我习惯控制在 500 token 以内,只交代“你是谁、你要做什么、你不做什么”。
状态层——对应对话历史和工具调用历史。它记录 Agent 到目前为止“做过什么”“得到过什么结论”“当前处于哪一步”。这层是动态的,每轮结束都会追加新的内容,也是上下文膨胀的主要来源。状态层的管理策略就是“取舍”——保留对后续任务有影响的信息,压缩或丢弃纯过渡性的内容。
知识层——对应 RAG 检索到的文档、外部数据库查询结果、预先准备的参考材料。这层信息通常不是用户主动输入的,而是 Agent 按需拉取的外部知识。知识层的关键在于“按需注入”——不要在对话一开始就把所有知识塞进上下文,而是等 Agent 需要的时候再检索对应片段,塞进去。这样可以大幅节省 token 预算。
即时层——对应当前用户输入、最近一次工具返回的原始数据。这层直接决定了模型本轮做出什么决策。即时层的优先级最高——即使上下文前面写得不够好,模型通常也会优先响应最后出现在窗口里的信息。
理解了这个分层,你在设计和排查 Agent 行为时就多了一个维度:模型表现不对劲时,先问一句——是状态层丢了关键信息?还是知识层注入的内容和用户问题矛盾?还是人设层写得含糊,导致模型不知道自己的职责边界?大多数 Agent 故障,都能归到这四个层的某一段上。
3.3 框架视角:Agent 框架中的上下文变量是怎么设计的
最近热度很高的几个 Agent 框架,比如 Swarm、DeepAgent、Hermes Agent、Pi Agent,它们的上下文设计逻辑各有侧重。我把它们看成三种典型范式:
范式一:显式上下文变量传参(典型代表:Swarm)。Swarm 框架里有一个很核心的概念叫“上下文变量(Context Variables)”,它和普通的函数参数不一样,是用来在整个 Agent 运行过程中跨步骤共享数据的。比如说,第一步工具调用获取了用户信息,后续步骤就不用重新读取,而是从上下文变量里直接取值。这种设计的好处是状态透明,排障容易——你随时可以打印出当前上下文变量列表,看看哪个数据丢了或覆盖了。缺点是:变量多了之后,Agent 需要手工维护变量名和数据生命周期,工程复杂度随之上升。
范式二:隐式全历史回放(典型代表:Claude Code 这类编程 Agent)。框架不主动管理哪些信息重要、哪些不重要,而是把全部对话历史、工具返回、文件读取记录一股脑放在上下文里。好处是信息完整、实现简单;坏处是随着对话轮次增多,token 消耗和“lost in the middle”问题会越来越严重。这类框架的共同解法是“压缩”——把早期对话摘要成几句话,腾出空间给新内容。
范式三:混合编排式(典型代表:各类企业级 Agent 框架)。框架允许开发者对上下文做精细化控制,可以设定哪些系统内容常驻、哪些对话历史保留最近 N 轮、哪些外部知识按需检索注入。这种设计最灵活,也最难配置,因为你要理解业务场景中哪些信息是必要的,哪些是噪音。
我建议做 Agent 开发的人,先把这三个范式都跑一遍。跑 Swarm 理解显式变量;跑 Claude Code 理解长上下文场景下的压缩需求;再上手一个混合式框架理解工程化调度。三套都跑完,你对“上下文的构成”才算真正建立起了体感。
3.4 上下文数据流:从输入到输出是如何流转的
上下文不是静态的,它在一次 Agent 运行中会经历“组装—消费—更新—再组装”的循环。理解这个数据流,对排查问题至关重要。
我把它拆成五步:
- 第 1 步:初始化。框架读取配置,组装系统指令、工具定义、用户初始输入,形成第一轮上下文。
- 第 2 步:模型推理。上下文作为输入,模型生成输出。这个输出可能是最终回答文本,也可能是一个工具调用请求。
- 第 3 步:工具执行。如果是工具调用请求,框架解析出工具名称和参数,执行对应函数(比如调用 API、读文件、跑命令),得到原始返回结果。
- 第 4 步:结果回填。框架把工具返回结果附加到上下文中,形成新一轮的上下文——模型现在能“看得到”自己上次调用的结果了。
- 第 5 步:迭代循环。回到第 2 步,模型基于更新后的上下文继续推理,直到触发停止条件(完成目标、达到最大轮数、模型主动结束)。
这个循环中,最容易出问题的就是第 4 步——工具返回结果有没有被正确回填。很多时候 Agent 出现“明明调用了工具却像没调用过一样”的情况,就是因为框架把工具结果截断了、格式化了错误、或者压根没拼进上下文。排查这类问题时,直接把框架渲染出来的完整 prompt 打出来看看,一目了然。
4. 上下文管理实操:预算分配、压缩策略与持久化
4.1 上下文 Token 预算分配:一段可以抄的配置经验
上下文窗口不是越大越好,而是要“花在该花的地方”。我自己的经验是把上下文窗口当成一个预算表来分配,而不是等它满了再去截断。下面是一套我常用的预算分配逻辑,以 128K(约 131072 token)窗口为例:
| 上下文部分 | 预算占比 | 说明 |
|---|---|---|
| 系统指令 | 1%~3% | 只写不可省略的角色、约束、输出规范 |
| 工具定义 | 5%~15% | 有多少个工具就要多少空间,工具越多占用越大 |
| 对话历史 | 30%~50% | 保留最近 N 轮完整对话,更早的做摘要压缩 |
| RAG 知识 | 20%~30% | 按需注入,每次检索只取命中片段,不整篇灌入 |
| 工具返回 | 10%~20% | 关键返回值完整保留,长日志做截断 |
| 当前用户输入/输出 | 5%~10% | 当前任务的最新信息 |
你可能会注意到,这份预算表的核心逻辑是“压缩中间、保全两端”。系统指令和当前输入是模型最敏感的区域,必须完整保留;对话历史和工具结果信息量大,但优先级相对低,是可以压缩和摘取的对象。
到这里你可能会冒出一个问题:这不是把问题弄复杂了吗?我的回答是:如果你做的是只有两三个工具的简单 Agent,随便放都没问题。但当你开始做真正复杂的 Agent——比如一个带 20 个工具、需要跨 50 轮对话、每小时执行上百次调用的自动化工作流——不建立预算管理,上下文一定会失控。我见过太多项目上线后模型表现突然下滑,最后一查原因,全是上下文里堆积了太多无用信息。
4.2 上下文压缩与截断:给 Ultra Long Context 场景的几种策略
长上下文窗口带来一个实际工程问题:窗口再大,只要任务够长,总有塞满的一天。所以上下文管理必不可少。这里分享三种我在项目中实际用过的策略,按“从轻到重”排列。
策略一:滑动窗口截断(Rolling Window)。最朴素的方式,只保留最近 N 轮对话,超过的部分直接丢弃。适合工具调用频率不高、各轮之间关联度较低的场景。优点是零成本、实现简单、响应速度快;缺点是信息损失大,Agent 可能忘记早期的任务约束,导致后续行为偏航。
策略二:摘要压缩(Summarization)。当对话历史超过阈值时,用模型把早期对话压成一段摘要,放进上下文顶部。摘要保留关键结论与决策理由,但去掉对话过程细节。这个方案能保留远期的关键信息,同时控制 token 增长,但有两个坑:一是摘要本身要花一次模型调用,有额外成本;二是摘要可能失真,模型概括时漏掉影响后续判断的细节——缓解办法是用带结构的摘要模板,强制要求摘要包含“已完成目标”“未完成事项”“当前障碍”三个字段。
策略三:外部记忆持久化(External Memory)。把对话历史和中间结果存到外部存储(比如向量数据库),每轮只把与当前任务最相关的记忆片段以 RAG 方式检索回来。这个方案几乎不受上下文窗口限制,适合超长任务、跨会话续跑的场景。代价是要维护一套检索系统和记忆索引,工程复杂度上了一个台阶。
我实际做过的项目里,大多数时候是混合策略:RAG 只检索知识库,不检索对话历史;对话历史用摘要 + 滑动窗口组合管理;工具返回结果按大小分两类,小的完整保留,大的压缩成结论。这套混合方案在长任务里跑了两个月,模型稳定性明显优于单用任何一种策略。
4.3 上下文持久化与跨会话恢复:续跑的前提条件
还有一个和上下文构成强相关的问题:跨会话恢复。很多人用 ChatGPT 时都会遇到切账号之后上下文丢失、对话记录加载不出来的情况——这在 Agent 开发里同样是常见问题。核心原因是上下文没有做持久化,session 一断,所有历史状态全没了。
做 Agent 上下文持久化时,需要在数据库里存三类信息:对话消息记录(用户消息、助手消息、工具调用记录)、上下文变量快照(当前任务状态、已获取的数据)、压缩摘要(早期对话的提炼结果)。恢复时,先从库里读出摘要和变量,再把最近的原始对话载入上下文,组成一个“带记忆的新 session”。
这里有个实操细节:恢复时不要把全部历史都塞进上下文,因为模型可以从摘要获得远期的背景信息,而近期对话只需要保留最近几轮就够。否则,你又回到了“上下文膨胀—性能衰减”的老路上。所以持久化恢复的核心理念是:上下文里只放“模型做下一代决策真正需要的信息”,其余的都放到外部存储里等着按需取用。
5. 常见问题与排查技巧实录
5.1 与长上下文相关的典型疑问
先整理几个我经常被问到的、也是网上热度很高的问题。
问:1M 上下文是什么意思?是不是必须开启才能用?1M 上下文就是模型单次可处理约 100 万 token 的输入窗口。很多大模型产品把它作为高级功能或灰度功能,默认可能只有几百 K。如果你的场景是短对话、单次分析,没必要强行开启。但跑 Agent 长任务、处理大代码库、分析超长文档时,1M 窗口能明显减少“对话中段遗忘”的问题,值得开启。
问:上下文长度设置多少合适?设置上下文长度不是“越大越好”。窗口设得过大,显存/内存消耗随之上涨,响应速度也会下降。我的经验是:先按任务类型估算,简单 QA 场景 4K~8K 足够;需要多轮工具调用的 Agent 起步 32K~64K;跑超长代码分析或文档处理再考虑 128K 以上。等你发现“截断历史导致模型遗忘关键信息”时,再逐步往上加,不要一上来就拉满。
问:为什么模型多轮对话之后表现越来越差?绝大多数原因是早期重要信息被滚动截断了。排查思路是:检查历史压缩策略里有没有保留“任务目标”和“关键结论”;确认工具结果有没有被完整回填;确认早期系统指令没有被后续对话淹没。我的常用补救办法是:定期把“当前任务目标 + 已完成步骤清单”重写一遍,放到上下文头部,模型会重新聚焦。
问:自定义模型是否适合拿来做 Agent 底座?如果模型本身不支持工具调用或指令遵循能力弱,做 Agent 会非常吃力。你能在开源模型上跑 Agent,但要做好心理准备——指令遵循、复杂多步推理、从错误中恢复这三项能力,是 Agent 对模型的核心要求。我的排序建议是:CLI Agent 用支持工具调用的前沿 API 模型最省心;本地部署场景,优先选在 Agent benchmark 上有公开成绩的模型,而不是只看通用榜单分数。
5.2 上下文工程里的排查三板斧
排查 Agent 上下文问题时,我一般按以下顺序操作——这条“三板斧”路径等于把黑盒变成白盒:
第一板斧:打印完整 Prompt。把框架提交给模型前的最终上下文完整打印出来,人工过一遍,往往一眼就能看出问题:工具返回被截断、对话历史顺序颠倒、系统指令被淹没在中间。这一步能解决 50% 以上的问题。
第二板斧:检查 Token 消耗分布。记录每一轮的 token 使用情况,看哪一部分增长最快。如果 80% 的 token 都花在工具返回值上了,说明工具返回的截断和压缩策略没有生效;如果对话历史增长异常,说明循环中没有正确实施历史压缩。
第三板斧:做最小回归测试。把复杂任务降维成一个简单测试用例,只测某一个上下文环节是否正常。比如“只保留系统指令和一句输入,调用一个工具,看模型能否按预期推理”。逐环节加回复杂度,就能定位问题出在哪一层。
这三步听起来简单,但恰恰是很多 Agent 项目里被跳过的步骤。我见过太多团队花一小时在模型选型上争论,却不愿意花十分钟看一眼实际发给模型的 prompt 是什么样的。上下文工程的第一原则就是:先看清事实,再谈优化。
5.3 关于模型选型与低资源部署的一点补充
和上下文构成同样影响 Agent 效果的因素是模型本身的底座能力。如果你在本地部署 Agent,低显存运行模型是现实需求。我的经验是:低于 8GB 显存,基本告别本地跑 7B 以上模型的 Agent 场景,就算勉强跑起来,推理速度也慢到无法支撑高频工具调用。可以考虑量化版本(比如 4bit),但要做好能力下降的心理准备。另一个思路是“小模型 + 大模型”混合调度:本地小模型负责工具调用和简单任务,复杂推理转发给云端大模型——这也是目前不少 Agent 框架推荐的架构。
另外关于模型学习相关的热搜词汇——比如“深度学习”“强化学习”“transformer 模型”之类——如果你想在 Agent 领域深耕,这些底子迟早要补。但我的建议是:不要为了“学习”而学习,而是带着 Agent 项目里的实际问题去补。比如你发现模型在长任务里遗忘严重,就可以去读 transformer 的注意力机制和位置编码原理;如果你做的是让 Agent 通过奖励信号优化行为策略,再去认真看强化学习。问题驱动的学习路径,效率远高于从教材第一页开始刷。
写给同行的一段话
做 Agent 项目这一年多,最大的感受是:这个领域看起来每天都有新框架、新模型、新概念,但剥开外壳,真正决定成败的还是那些最基础的东西——模型能力、上下文组织、状态管理、工具调用的正确性。“模型的学习”和“上下文的构成”这两个话题,本质上是同一枚硬币的两面:模型会“学”什么,取决于你在上下文里“教”了什么。把上下文工程做扎实了,你的 Agent 就赢在起跑线上了。希望这篇精读能帮你少踩几个坑。