阐述Agent状态栏
回复 Erfan: 接你上一个问题,Agent 状态栏(Agent Status Bar)其实就是专门用来解决「LLM 不擅长在一次前向传播里归纳统计隐式状态」的工程方案(出自李博杰《深入理解 AI Agent》的上下文工程章节,也是 Claude Code 等主流 ca 的底层机制)。 简单说,如果把 System Prompt 比作静态的「员工入职手册」,那 Agent 状态栏就是框架在上下文末尾给模型动态挂上的「实时仪表盘」。 可以从原理、塞什么内容、怎么注入(KV Cache 权衡)以及工程铁律四个方面来拆解: 1. 为什么需要它(本质是上下文蒸馏) Agent 跑长任务时,像“某个工具已经调了几次”“现在改到了哪个工作目录”“原本的 TODO 完成了哪几项”这些信息,全都零散埋在几十轮的历史消息里。 注意力机制擅长检索单点事实,但不擅长在单次 forward 里扫描全部历史去算统计。结果就是上下文越长,模型越容易陷入死循环(无限重试同一个报错工具)、遗忘约束或目标偏移。 状态栏的做法是:由外部框架把分散在历史轨迹里的隐式状态,直接提炼成显式的、高密度的键值结构化文本,塞到上下文最末尾(注意力权重最高的位置),让模型不用自己去数、直接照着读。 2. 状态栏里通常放哪四类信息 一是任务规划(TODO 清单):标明哪些待办、哪些进行中、哪些已完成,防止模型钻进局部 bug 忘了主线目标。 二是环境当前状态:当前工作目录(cwd)、Git 分支、工具调用次数统计(比如 bash 已调用 5 次,同一个报错连续出现 3 次)、预算消耗等。 三是事件侧信道信息(Side-channel):当前系统时间、距离上一轮操作耗费的物理时间(elapsed_ms)等模型自己无法感知的外部事实。 四是可用能力清单:比如我们刚聊过的 Skill 元数据列表(名称和简短触发描述)。 3. 怎么注入上下文(极其关键的 KV Cache 设计) 状态栏绝对不能去动态修改最开头的 System Prompt。因为一旦改了 System Prompt,整个长对话的 KV Cache 前缀就全部失效了,每轮重算的延迟和成本会爆炸。 主流实现是:在 API 消息列表的最末尾,由框架伪造一条 user 角色的消息(通常用 system-reminder 或 agent_status 这类 XML 标签包起来)注入进去。 在更新策略上也有两种权衡: 一种是「每轮替换」:发新请求前把上一轮的状态栏删掉,只在末尾放最新的一条。优点是省 token、上下文干净,缺点是删掉历史中间的消息会破坏那一段之后的 KV Cache,适合短会话。 另一种是「持久追加」(Claude Code 采用的做法):旧的状态栏消息作为历史留在原处不动,每轮只在末尾追加最新状态。虽然多占一点 token,但做到了严格的 Append-only(只追加不修改),100% 命中前缀 KV Cache,最适合长轨迹任务。 4. 落地时的三条工程铁律 第一,状态栏必须用确定性代码(正则、计数器、系统探针)去维护,绝不能让另一个小模型去批量总结历史生成状态栏——模型总结本来就会算错,一旦写进状态栏,主模型会无条件相信,错上加错。 第二,必须用紧凑的结构化键值格式,不要写散文,减少模型的解析开销。 第三,光给状态读数不够,要配对给操作策略。比如光在状态栏打印「某工具已连续失败 3 次」或「已耗时 50 秒」,模型往往无动于衷;必须成对加上提示约束(例如:连续失败达 3 次时禁止原样重试,必须切换排查方案),读数才会真正转化成自适应行为。