Agent上下文管理新范式:用显式状态替代对话历史
发布时间:2026/9/4 21:02:49 锦皓数字建站

这次我们不聊能直接下载的一键包也不聊某个开源模型而是聚焦一个可能改变 Agent 长期任务处理方式的研究方向Google 新研究的 SKILL.state用显式状态替代对话历史。先快速说结论。这项研究面向的核心痛点是现在的大模型对话系统、编码 Agent、客服 Agent普遍依赖“对话历史”来维持上下文。模型每次生成前都要读完一遍完整历史历史越长token 成本越高旧信息对当前决策的干扰也越明显。SKILL.state 的思路是不要总是把原始对话历史交给模型而是把对话推进过程中真正影响后续决策的部分整理成一个可更新的显式状态模型每一轮只看这个状态而不是重读全部历史。这篇文章我会围绕三个问题展开SKILL.state 到底在解决什么问题核心价值在哪里“显式状态替代对话历史”在编码 Agent、自动化任务、多轮工具调用这些场景里怎么落地就算官方代码还没放出来作为开发者我们可以先按什么思路自己设计一套最小可验证的状态管理模块。顺便也回答一个经常被问到的问题Claude Code 这类编码 Agent 工具里的“保存对话历史”和 SKILL.state 说的“显式状态”到底是不是同一件事。如果你正在做 Agent 应用、接口编排、批量任务或者被长对话的上下文管理折腾得够呛这篇值得看完。1. 核心能力速览先说清楚这不是一个可以直接 pip install 的项目也不是一个能双击启动的 WebUI。它的形态更像是研究论文加配套的机制设计真正的价值是给 Agent 上下文管理提供了一个新范式。能力项说明研究主题大模型多轮任务中的上下文管理核心思想用显式状态表示会话推进中的关键信息替代直接拼接对话历史主要场景任务型 Agent、编码 Agent、多轮工具调用、批量自动化任务显存需求不适用属于推理调度与上下文结构层不决定模型权重本身启动方式无单一启动器需要在具体 Agent 框架中接入是否支持 CPU / GPU与基础模型部署方式一致机制本身不要求特定硬件是否支持 API公开材料未见统一 API 定义可自行封装状态读写接口是否支持批量任务理论上适合批量评测需要自己搭建评测任务集上手成本理念容易理解工程落地需要自己设计状态结构和校验逻辑适合读者大模型应用开发者、Agent 框架使用者、研究复现者从信息完整度来看目前能确认的并不是“SKILL.state 已经发布了一个可直接运行的仓库”而是它提出了一个设计方向。所以这篇文章更多是解释这个方向并抽象出普通开发者能立刻用上的思路。2. SKILL.state 要解决什么问题大模型做任务型对话时最常见的实现方式是把每一轮的用户输入、模型输出、工具返回结果全部追加到一个 message 数组里。新的一轮开始时把整段数组拼进 prompt让模型在前文基础上续写答案。这个设计很简单但在真实任务中会越来越难受第一历史越长生成成本增长越明显。对话从 10 轮长到 100 轮prompt 里的历史占据绝大部分 token。对多轮工具调用类任务来说可能 80% 的 token 都花在了翻旧账上真正用于推理和生成的空间被压缩。第二历史里包含大量对当前任务已经无意义的信息。比如用户中途改过一次需求前一次的需求描述已经作废但旧文本仍然留在历史里。模型需要在多段矛盾描述中分辨“哪个是最新的”状态一旦复杂就很容易错判。第三长历史会放大上下文干扰。模型越往后越容易遗忘早期约束或者把较早的中间结果当成当前结果。尤其涉及 API 调用、代码文件生成、批量数据处理时一条过时信息就可能让 Agent 执行了错误的分支。SKILL.state 的核心假设很直接一个任务能不能继续推进并不取决于模型记住了多少原文而是取决于模型是否掌握“任务现在进行到哪一步、哪些条件已满足、哪些参数已确认、还需要什么”。前者是历史后者是状态。历史是线性记录的状态是结构化抽象的。会话可以进行一百轮但真正控制任务走向的关键状态可能只有十几项。让模型维护清晰的状态机比让模型从一百轮文本里自己推断当前进度要稳定得多。3. 显式状态与对话历史的核心差异为了讲清楚差异我们假设一个典型的多轮任务用户在编码 Agent 中说“帮我实现一个文件批量重命名工具要求支持正则匹配不要覆盖已有文件先输出 dry-run 结果”。传统方式下模型每轮都需要看到用户原始需求、自己之前的回答、工具返回结果然后自己判断当前到底执行到哪一步。这个过程中存在大量不必要的重复理解。显式状态方式下模型只维护一份结构清晰的脚本状态{ task_id: batch-rename-001, goal: 实现支持正则匹配的批量重命名工具, constraints: [ 不覆盖已有文件, 先输出 dry-run 结果 ], collected_params: { source_dir: ./downloads, pattern: IMG_\\d{4}\\.jpg, replace_to: photo_$1.jpg }, pending_actions: [ confirm_conflict_policy ], active_skill: file_rename_skill, steps_done: [ regex_pattern_validated ] }两者对比是这样维度对话历史显式状态信息组织方式线性、按时间追加结构化、按任务要素组织长度变化随轮次单调增长基本稳定只更新变化项token 成本每轮几乎全量重读只提交当前状态与增量更新陈旧信息处理难以主动清理覆盖式更新天然淘汰旧值是否便于校验只能靠模型自行解读可以写 schema 做严格校验可回溯审计完整但杂乱需要额外保存历史才能还原调试友好度需要通读每次改动的上下文状态文件即当前全貌显式状态并不是把对话历史物理删除而是切分了两种用途原始历史用于审计、追溯、人工复盘存进日志或会话文件不直接进入模型上下文状态用于驱动生成让模型基于结构化的当前事实做下一步决策。这个切分一旦完成你会发现 Agent 的任务稳定性忽然变得可控了。因为状态更新可以由规则、工具返回值、模型抽取共同完成每一步都可以验证而不是把一切希望寄托于模型从头到尾理解一段冗长对话。4. 对 Claude Code 类编码 Agent 的直接启发标题下面相关的热词很有意思很多人搜“Claude Code 怎么保存对话历史”。这说明大家在使用编码 Agent 时真实遇到了一个问题任务太长一旦会话中断、重启上下文丢失Agent 就忘了自己之前做到哪里。Claude Code 这类工具之所以强调保存对话历史是因为它的工作记忆完全建立在消息记录上。保存历史相当于保留了任务的“原文底稿”。下次继续时模型重读底稿从中理解任务进度。但 SKILL.state 提供了一个更工程化的思路如果你只有一个会话记录文件模型要继续工作就得从几千行消息里重新推断任务状态。如果能把状态单独抽出来比如一件事一个 skill一个 skill 对应一份 state那恢复任务的成本就会低很多。对编码 Agent 来说显式状态至少可以包含以下几类内容当前任务目标和验收标准已完成的文件修改列表用户提出的禁止性约束当前正在调试的问题和已经排除的可能性待运行的命令和尚未验证的假设代码中已经确认的问题根因需要用户拍板的开放问题。把这类信息写入一个 session 状态的 JSON 或 Markdown 文件每次 Agent 启动时先读状态而不是先读完整历史。如果状态文件已经能描述任务现状就让模型只基于状态继续工作只有状态缺失或不明确时再回溯历史。这样做的收益是用户可以真正实现“隔天继续任务”。不需要重新把整个对话历史发给模型不需要让模型重新梳理上下文状态文件本身就是任务进度的唯一事实来源。真正的编码 Agent 工作流中原始历史仍建议保留但它的角色更像是备份日志。模型推理的主输入可以用结构化状态替代。这也解释了为什么很多重度使用者会觉得“长任务跑久了Agent 越来越笨”因为历史像滚雪球一样积累而 Agent 在每轮都要重新消化这段越来越大的历史。显式状态是解决雪球问题的正确方向。5. 显式状态机制怎么设计要把 SKILL.state 的思想从研究语言翻译成工程实现我们需要设计四件套状态结构、状态更新入口、更新模式和校验机制。5.1 状态结构怎么定义状态不能是一段自由文本否则和对话历史就没有区别了。它应该尽量贴近任务领域。我的建议是从五类字段开始字段类型作用示例Identity标记当前是哪个 skill 的状态skill_id、task_id、versionGoal用户最终想达成的目标“实现文件重命名工具”Context当前已知的环境信息目录结构、文件权限、依赖版本Memory已确认的事实与参数pattern 已经确认、输出目录已创建Plan下一步行动与待定项等待用户确认冲突策略可以把这些固定成一个通用 schema按 skill 做扩展。重点是保证任何一个开发者在任意时间点读到状态文件都能独立判断任务进度不需要额外翻历史。5.2 更新入口谁负责修改状态一个常见错误是希望模型在输出文本时“顺手”改状态这会让状态非常不稳定。合理的方式是设置一个独立的update_state入口并且让更新的输入来源不只是用户消息。状态更新的来源应该包括用户新输入新增约束、修改目标、补充参数工具返回命令执行成功、文件生成、API 返回结果模型推理结果模型从当前上下文判断下一步执行动作外部事件定时器触发、文件系统变更、队列消息到达。推荐把更新动作收敛到一个函数。示意代码如下from typing import Dict, Any, List class SkillState: def __init__(self, task_id: str, skill_id: str, version: str 1.0): self.task_id task_id self.skill_id skill_id self.state_version version self.goal self.constraints [] self.collected_params: Dict[str, Any] {} self.pending_actions: List[str] [] self.steps_done [] self.active_skill self.last_updated_turn_id 0 def apply_update(self, updater: str, update_content: Dict[str, Any]): self.last_updated_by updater if goal in update_content: self.goal update_content[goal] if constraints in update_content: self.constraints update_content[constraints] if params in update_content: self.collected_params.update(update_content[params]) if step_done in update_content: self.steps_done.append(update_content[step_done]) if new_pending in update_content: self.pending_actions.append(update_content[new_pending]) if resolved_pending in update_content: self.pending_actions.remove(update_content[resolved_pending]) def to_prompt_fragment(self) - str: return f 当前任务状态 - 目标{self.goal} - 约束{; .join(self.constraints) if self.constraints else 无} - 已收集参数{self.collected_params} - 已完成步骤{; .join(self.steps_done)} - 待处理事项{; .join(self.pending_actions) if self.pending_actions else 无} 这段代码不是任何官方实现而是演示一个可以落地的状态管理雏形。实际项目里可以把apply_update对外封装成 HTTP 接口也可以作为工具函数被 Agent 调用。5.3 更新模式整包覆盖还是字段增量状态更新有两种模式可以混用。整包覆盖适合用户明确变更了目标或某个核心字段例如用户说“不要批量重命名了改成批量压缩图片”。此时直接更新goal旧目标不再保留在状态中。字段增量适合推进过程中的细小变化比如新增一个已完成步骤、收集到一个参数、解决一个待办。推荐做法是以“事件驱动”的增量更新为主以用户或模型发起的整包重建为辅。每次更新都记录一个操作日志{ turn_id: 17, updater: model, changes: { collected_params: { source_dir: ./downloads, pattern: IMG_\\d{4}\\.jpg }, steps_done: [dry_run_generated] }, timestamp: 2025-01-12T14:30:0008:00 }这能保证状态即使写错也能定位是哪一轮、哪个模块改的。5.4 校验机制是显式状态能否成功的关键如果状态没有校验它就会退化成一种“格式化的幻觉”模型往状态里填了错误的事实比直接用对话历史错得更隐蔽。因此工程上必须给状态做约束校验例如必填字段是否存在字段类型是否正确constraints 里是否存在互相冲突的值collected_params 里的路径是否存在active_skill 是否是已注册技能已完成步骤是否和整体流程顺序一致。这些校验最好同时做两层。第一层是规则校验用 JSON Schema 或自定义检查函数完成第二层是语义校验由模型审核当前状态是否与最近几轮对话一致。如果第二层发现矛盾就把矛盾回传给状态更新模块重新修正。通过设计合理的结构、统一更新入口、记录更新日志、执行严格校验状态才能成为 Agent 可信的任务记忆。6. 最小可行实验路线如果你不想停留在概念理解层面想自己动手验证一下“显式状态替代对话历史”是否有效我建议从小规模实验开始。不需要等到官方代码发布也不需要高端显卡。6.1 用什么任务做实验选择任务时优先挑选具备这三个特征的任务轮次多至少需要超过 20 轮交互中间存在用户需求变更旧信息会和新信息冲突每轮都需要根据早前确认的参数执行工具调用。比如一个带文件操作的表格处理任务用户要求处理一份 CSV中途突然改需求要求保留前 N 行不处理又要输出两份不同格式的结果。这类任务里消息历史会快速膨胀而显式状态能清晰区分“初始需求”和“变更后需求”。6.2 对照组怎么设建议设置两个完全相同输入的任务流。组 A模型每轮读取完整对话历史不加状态组 B模型每轮只读取显式状态历史不进入主上下文组 C可选模型读取显式状态加最近五轮历史。然后比较三类指标任务完成率、完成时间或调用轮数、总 token 消耗。记录格式可以这样设计[ { task_id: csv-process-01, group: state_only, success: true, total_turns: 24, input_tokens: 0, state_updates: 11, total_cost_estimate: 0 } ]输入 token 和总成本需要根据实际模型计费方式自行计算。核心是看状态机制是否在减少 token 的同时保持了成功率。6.3 状态提示词怎么写实验中的状态片段可以直接由to_prompt_fragment组装。给模型的消息不再是几十条历史消息而是类似这样你是文件处理 Agent。当前请只依据下方状态推进任务。缺少关键信息时询问用户。 当前任务状态 - 目标处理 ./downloads/orders.csv生成清洗报告和分类汇总 - 约束前 50 行不处理不覆盖原文件 - 已收集参数inputorders.csv, keep_first_rows50 - 已完成步骤格式检查、字段映射确认 - 待处理事项等待用户选择汇总维度模型不会知道前 20 轮里用户是否犹豫过但也不需要知道。被状态淘汰的信息本来就不应影响决策。6.4 什么结果说明实验成功状态的组 B 不一定在每个任务上都比组 A 强。如果任务很短、需求稳定、历史只有几轮显式状态反而增加额外结构成本。真正能证明价值的是长任务上的表现。一个实验成功与否至少应该同时满足以下几条在多轮长任务上状态组的完成率不低于历史组状态组的总 token 消耗明显更低在用户中途变更需求的任务上状态组的正确率更高状态文件可以被单独存储并在新会话中恢复任务执行能力。这四点如果都成立说明显式状态确实比全文历史更适合作为 Agent 的主要上下文。这也正是 SKILL.state 方向最有价值的地方不是在“要不要保存一份历史日志”这个层面讨论而是直接重新定义了模型应该为什么信息买单。6.5 批量评测怎么做显式状态机制天然适合批量任务回归。因为状态是结构化文件开发者完全可以写一个批处理脚本把几十个任务轨迹逐一喂给 Agent跑完后批量统计成功率、失败原因、状态冲突次数和 token 消耗。批量评测可以按目录组织benchmark/ tasks/ task_001/ input.json history.json expected_state.json task_002/ input.json history.json expected_state.json runs/ group_a_full_history/ group_b_state_only/每次跑完任务把 Agent 最终生成的 state 文件与expected_state.json做 diff能清楚看到状态更新错在哪一步。这种可回放、可对比、可回归的流程是对话历史方案很难做到的。因为对话历史只能对比谁更流畅而状态方案能对比字段级差异。7. 资源占用与 token 成本观察显式状态方案最大的吸引力之一就是节省 token。它的成本模型与对话历史完全不同。对话历史的 token 成本随轮次增加而上涨大致可以简化为每轮输入 token ≈ 系统提示词 累计历史 当前输入也就是说第 50 轮的 prompt 需要包含前 49 轮的内容成本几乎是滚雪球式上涨。显式状态的 token 成本模型则是每轮输入 token ≈ 系统提示词 固定大小的状态结构 当前输入状态结构大多数字段是覆盖更新长度相对稳定。真正增长的部分只发生在确实新增了约束或步骤清单的场景。需要提醒的是显式状态不是零成本。状态结构本身需要占用一部分固定 token状态更新也要产生一次额外的模型调用或规则处理。在短任务、低轮次场景中这套机制反而可能比直接读历史更贵。所以它的收益要在长任务里才能兑现。如果要在自己的 Agent 任务里观察成本收益建议记录以下数据每一轮进入模型的实际输入 token 数模型生成本轮回答的输出 token 数状态更新的调用次数和时间最终任务是否成功完成用户中途改需求的次数。运行几次后对比是否出现“当前几轮状态 token 明显小于累计历史 token”的局面。这个数据比听任何理论分析都有说服力。8. 常见理解误区和问题排查任何一个新方案都会带来新的坑。显式状态不是简单的上下文技巧它会把一部分“模型记忆问题”转成“工程一致性问题”。从设计上说我们要提前预判这些容易出错的地方问题现象可能原因排查方式解决思路模型忽略状态里的新约束状态结构与实际 prompt 拼接不自然检查状态片段在 prompt 中的位置和格式将状态放到历史之前并用固定格式突出显示状态和其他轮次信息矛盾状态更新逻辑不完整审查 update 调用点和触发来源增加“对立检查”状态变更前后做一致性校验状态文件本身无法帮助恢复任务状态只记录目标不记录进度检查状态中是否缺少 pending_actions增加步骤列表、待办列表和历史操作摘要显式状态的使用反而更贵任务轮次少状态结构复杂统计单轮输入 token短任务建议退回历史方案或使用混合方案工具执行结果没有同步到状态工具返回后缺少 update 步骤观察工具调用与状态变更的先后顺序在工具结果处理处强行调用状态更新状态更新成功但 Agent 生成结果错误状态被错误校验掩盖做字段级 diff引入模型评审状态是否与实际输出一致多人协作时状态文件冲突状态是单文件多端同时修改检查同一 task_id 是否有多次实例使用带版本号的状态存储更新前做冲突检测真正要实现状态替代历史必须有三个意识第一状态不是总结。总结仍然是一种文本压缩信息提取后仍是模糊的。状态是强约束的结构字段与任务执行逻辑直接对应。第二状态更新不能只靠模型自觉。模型生成完文本后应该有一个独立步骤决定当前状态再由规则层做校验。如果你只让模型“顺手”输出一个 JSON它很可能会遗漏重要约束或虚构已完成步骤。第三状态方案要求 Agent 框架具备可观测性。如果整个 Agent 是个黑盒用户无法看到状态中间值那就很难排查问题。建议在任何任务节点输出当前状态方便定位是哪一轮更新把状态带偏了。9. 最佳实践与使用边界聊完了理论和实验最后把这些思路收拢成可直接执行的最佳实践。先小规模验证不要一上来重构整个 Agent 框架。选一个低频但轮次多的内部任务设计一份状态 schema跑 20 个预置任务对比完成率、轮次和 token 消耗确认效果后再推广。建立 schema 版本机制。状态结构会随业务需求演化。增加一个state_version字段保证旧任务能用迁移逻辑读到新版本。状态文件和历史日志建议同时保存。状态负责驱动模型原始历史负责审计。历史不一定要进入 prompt但一定要留底。这样如果状态更新出错还能回到历史重演。私有数据必须脱敏后再写入状态。显式状态是一个结构化文件很可能被持久化到磁盘、数据库、日志系统。如果状态中直接写入用户手机号、身份证号、代码仓库凭据就等于把敏感信息平铺在存储层。正确的做法是在进入状态前完成脱敏或改为引用外部安全存储的 key。对模型可修改的字段做最小权限控制。有些字段比如task_id、state_version、completed_steps应尽量由规则层管理模型只能更新collected_params、goal等任务要素字段。权限粒度越细状态被带偏的概率越低。接口服务要考虑状态读写隔离。一旦把状态能力封装成内部 API就要设计好鉴权和隔离避免一个任务直接读取或篡改另一个任务的状态。涉及自动化执行文件操作、代码生成、数据处理的场景需要把操作边界写进约束字段并且人工复核最终产物。比如对文件执行删除覆盖前应该将危险操作拆成独立步骤经过用户确认后再执行。状态系统本身再精确也只是一种辅助记忆机制不能替代对敏感操作的安全兜底。10. 值得关注的点和真实结论SKILL.state 这个方向真正值得关注的地方是它把 Agent 研究里的经典争论重新拉回了工程视野到底要不要让模型依赖一个外部记忆系统而不是完整对话历史它的答案很明确要。而且不是简单做摘要不是把历史文本压缩成更短的文本而是把任务推进过程中真正有持久价值的要素提炼成显式状态用一套可校验、可更新、可持久化的状态机制替代历史作为模型的主输入。如果你现在正被长任务 Agent 的上下文问题困扰我建议先做一次小实验挑一个现阶段最容易失败的多轮任务写一份状态 schema把模型的主输入从“拼接全部历史”改成“读状态”跑 20 轮记录 token 和成功率。这套实验不需要等官方发布复现也不需要复杂的深度调优它验证的核心问题只有一个你的 Agent 到底是在靠理解状态做决策还是在靠翻阅聊天记录猜进度。最容易踩的坑是结构设计得过于复杂把状态系统变成一个沉重的规则框架。正确的做法是先以最简单的方式让状态可读、可改、可校验跑通之后再根据真实失败案例扩展字段和规则而不是在第一天就把所有可能状态全部建模进去。从研究到工程化通常还需要一段时间但这个方向提醒我们的东西很朴素模型不需要记得所有发生过的事它只需要知道现在该做什么、已经完成了什么、还差什么。剩下的工作交给一个可靠的结构化状态就够了。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。