跳到主要内容

goose — 本课题摘录

读了哪几篇: 03-safety-chain(安全与权限链)、04-context-management(上下文管理)。 其余三篇(中央回复循环、工具与 MCP、巧妙之处)本轮没读。

这一家最值钱的一条:它把"持久化的真相"和"喂给模型的视图"用两个开关解耦了,而且这两个开关是每条消息各自带的。

它对本课题回答了什么

决定一最重要的一条:可见性双轨

每条消息带两个独立的可见性开关:对用户可见 / 对 agent 可见。喂给模型时只取"对 agent 可见"的。

这套双轨能玩出很多花样:

场景可见性设置效果
压缩后的原始历史用户可见、模型不可见用户翻得到原文,模型只看摘要
压缩摘要 / 续接说明模型可见、用户不可见模型靠摘要续上,界面不被噪声打扰
给模型的引导提醒、拒绝理由模型可见、用户不可见引导模型而不打扰用户
命令的回执用户可见、模型不可见用户看到确认,模型不被命令本身干扰

(依据:Agent 库 · goose · 上下文管理 —— 每条 Message 带两个独立可见性开关(对用户可见/对 agent 可见),喂给模型时只取 agent-visible 的;可用于「压缩后原始历史用户可见模型不可见」「压缩摘要模型可见用户不可见」等场景)

它自己的总结句:"历史里有"不等于"模型看得到"。可见性元数据把"持久化的真相"和"喂给模型的视图"解耦了——这是它上下文管理的地基。

这条是本课题"投影"这一族里最轻量的实现。 deepseek-harness 用"日志 + 可见面 + 投影"三层概念;nanobot 复制一份再修;deepagents 在调模型那一步算; goose 只在每条消息上加两个布尔。 对最小原型来说,goose 这个粒度最实际——两个字段就把大部分需求覆盖了。

而且这两个开关是独立的,不是"一个可见性等级"。四种组合都有实际用途(见上表),这就是为什么它必须是两个布尔而不是一个枚举。

决定一:三招防撑爆,而且分工明确

是什么特点
整体压缩到达窗口上限的 80% 时把历史摘要掉大锤
工具对摘要把一对对的「工具请求 + 工具结果」单独摘要掉小锉刀,后台异步跑
可见性双轨见上地基

(依据:Agent 库 · goose · 上下文管理 —— 三招是 80% 阈值触发的整体摘要压缩、后台并行的「工具对」摘要(批大小 10)、可见性双轨;压缩分「进循环前预压」和「撞上超限错误后的恢复式压缩(最多 2 次)」)

"工具对摘要"的理由很实在:工具输出往往是上下文里最占地方的部分——一次列目录可能吐几百行。

它是在后台异步跑的:循环里派出去,不阻塞当前回合,一圈结束时再等它的结果。

"压缩放后台"这个做法别家没有。 压缩要调模型,是慢操作;放在主路径上会让每一轮都变慢。 代价:摘要落地时可能跟历史对不上,所以它加了一致性校验。

一致性校验:必须正好找到"请求 + 回复"两条匹配消息才替换,否则只告警不动——避免把对话搞成半残。

又一次撞上"调用与结果必须配对"这条不变量。 这已经是第五家强调它了。

压缩本身分两个时机:进循环前预压、以及撞上超限错误后的恢复式压缩(最多 2 次)。

决定一补充:token 怎么数 —— 用真实用量,别每次重数

优先级做法
优先用会话元数据里记录的真实用量——厂商在每次调用后回报的准确值,每圈累加
兜底本地估算(只数"对模型可见"的消息)

(依据:Agent 库 · goose · 上下文管理 —— 判断是否超阈值优先用 session 元数据里 provider 回报的真实 token 用量并每圈累加,没有才用本地 token_counter 估算(只数 agent-visible 的消息);用真实用量既准又省)

它的评价:用真实用量而非每次重数,既准又省。

这条要抄。 我们很容易一上来就写一个"估算 token 数"的函数, 但厂商每次调用后都回报了准确值——累加它就行,不用自己估。

还有一条判断:如果厂商自己管上下文(比如某些命令行包装),它就不插手。

决定三:工具执行前的检查器流水线

所有"执行前检查"被抽象成同一个接口:给一批工具请求,返回一批裁决。裁决只有三种——放行 / 拒绝 / 需要审批(可带警告文案)。

检查器按注册顺序跑,顺序就是优先级:

安全 ── 注入 / 危险命令的模式匹配(最先)

出口 ── 数据外泄检测

对抗 ── 基于模型的二次审查(需要显式开启)

权限 ── 按权限模式/缓存决定

重复 ── 检测工具调用陷入重复循环

(依据:Agent 库 · goose · 安全与权限链 —— ToolInspector 统一接口的裁决只有 Allow/Deny/RequireApproval 三种,检查器按注册顺序跑——安全→出口→对抗→权限→重复;单个检查器报错不中断整条链,只记日志继续)

两条设计值得抄:

设计说的是什么
单个检查器报错不中断整条链一个安检器挂了不该让整个 agent 停摆,只记日志、继续
裁决合并往严了走多个检查器的裁决折叠成一个结果时,取最严的

第一条是很好的健壮性判断:安全检查本身不该成为新的故障点。

最外层还有四种权限模式:自动批准 / 每次都问 / 只对敏感的问 / 纯聊天不执行工具。 "纯聊天"模式在循环里直接短路:工具请求被回一句"已跳过"而不执行。

它没回答什么

  • 循环骨架本身——那是第 1 章,本轮没读。
  • 不用原生工具调用怎么办——不在这两篇。
  • 工具调用怎么解析——不在这两篇。

坑与代价

  • "后台跑压缩"的代价是要处理"摘要回来时历史已经变了"。 它用一致性校验兜住,但兜住的方式是"对不上就不动"——也就是这次摘要白做了。
  • 五个检查器串行跑,每次工具调用都要过。 其中"对抗"那一档要调模型,默认是关的,可见成本不低。
  • 可见性双轨要求所有产生消息的地方都记得设这两个开关。 漏设一处就会出现"用户看不到"或"模型看不到"的怪事。

    判断(无锚): 这个风险可以靠默认值兜住——默认两个都为真,只有明确要藏时才改。 如果错,会错在: 如果大部分内部消息本来就该藏(比如系统提醒),那默认全可见会让界面很吵,应该反过来按类型定默认值。