Goals
Goal 让 Qwen Code 跨轮次持续工作,直到满足指定条件。使用 /goal <objective> 设置一个 Goal,会话便会自行持续运行。每一轮次都会被记录为证据;当模型提出目标已完成或受阻时,一个独立的验证器仅根据证据来判定该提案。当验证器接受,或者 Goal 被暂停、清除或因限制而停止时,会话结束。
命令
| 命令 | 行为 |
|---|---|
/goal | 显示当前 Goal 及其状态。 |
/goal <objective> | 创建 Goal,或替换当前活动的 Goal。 |
/goal set <objective> | 与上面相同,显式形式。 |
/goal edit <objective> | 修改活动 Goal 的措辞,无需从头开始。 |
/goal pause / resume | 停止或继续循环,不会丢失 Goal。 |
/goal clear | 移除 Goal。 |
/goal-draft <intent> | 在设置之前让系统帮你编写目标(见下文)。 |
创建、编辑或恢复 Goal 需要 trusted workspace(/trust)。无头模式用法请参阅无头模式。
一旦 Goal 计费了一个轮次,底部药丸和每个状态卡片都会显示它在允许窗口内的花费,格式为 1.2k/30.0m。该数字统计的是 Goal 在自己的轮次中发起的模型调用;子代理和验证器自身的检查不计入。窗口由 model.goalTokenBudget 设置;恢复一个已耗尽窗口的 Goal 会在已花费的基础上再授予一个窗口,因此数字显示为 30.0m/60.0m 而非从头开始。没有预算的 Goal 仅显示已花费的量。尚未计费任何轮次的 Goal 不显示任何数字。
还有两个窗口可用,默认关闭:model.goalMaxTurns 限制 Goal 可完成的轮次数,包括用户驱动的 Goal 轮次;model.goalMaxActiveMinutes 限制其在运行进程中保持活动状态的墙钟时间,包括轮次之间的等待和空闲时间。Goal 处于暂停、阻塞或停止状态时的时间不计入第二个窗口,重启期间的停机时间也不计入;仅被挂起的进程仍会计费。无论哪个窗口先耗尽,Goal 都会获得同一个收尾轮次进行交接,然后停止直到你恢复它,恢复会在已使用量的基础上再授权一个窗口。只有耗尽的窗口会移动;其他窗口保持不变,-1 退出选项同样只对一个已耗尽它的 Goal 取消上限。时间窗口在轮次之间读取,而非通过计时器强制执行,因此 Goal 可能在超过窗口后仍继续运行一段时间才停止:已在运行的轮次不会被中断,在没有轮次运行时耗尽的窗口要等到下一个轮次结束才会被注意到。活动时间在记录的转换之间计算,因此被重启中断的轮次中的时间不计费。对任一设置的更改在重启后生效。两个窗口仅对在更改后创建的 Goal 生效,因此限制已记录在案的 Goal 意味着使用 /goal set 替换它——一个处于修订版 1 的新 Goal,其轮次、token 和活动时间计量器重置,其证据窗口从替换处开始,因此旧 Goal 记录的证据不再可引用——或者清除它并重新开始。恢复或编辑永远不会添加创建时未启用的上限。
会话自行采取的每个轮次都会报告 Goal 迄今为止的花费、已完成的轮次数,以及——除非 Goal 无限制运行——其被允许的窗口。除最终的收尾交接外,每个这样的轮次还携带常驻指令:重新检查工作区而非信任先前轮次的报告,朝着目标所要求的终态推进,当上一轮没有任何改变时做不同的事(从第二轮开始,在有上一轮可供判断之后),并在提出 Goal 已完成之前根据可引用的证据检查每一项要求。
一个长时间运行的 Goal 会周期性地将已记录证据压缩为检查点声明,通过一个 side model 调用完成,以便后续轮次和验证器仍可引用。该检查受 model.goalCheckpointTimeoutSeconds 约束,默认 180 秒。如果其声明超出总字节预算、包含超过单条声明字符上限的声明、数量超过单个检查点可容纳的数目、引用了请求中不存在的 id,或更改了其所引用来源的证明类型,它会发起一次纠正性模型调用指出错误所在,两次调用共享该上限。包裹在 markdown 代码围栏中的回复会在去除围栏后读取。不是包含非空 claims 数组的 JSON 对象的回复不会触发纠正调用,包含任何格式错误声明的回复也不会——即使同时存在可用的声明:任一层级的多余键、无法识别的 proofKind、空声明,或者 sourceRefs 列表为空、包含非字符串或空 id、重复 id,或包含超过 32 个 id。未能在时限内完成的检查将作为不确定的检查被放弃;仅当证据窗口已溢出时,它才计入检查点停滞限制,而未溢出的检查则保留连续计数并在后续轮次重试。这些调用是流式的,因此每个请求的传输超时仅约束连接和首次响应,而其上限本身在 stream guard 的 15 分钟生命周期上限处终止,因为超过该时限后,是 guard 而非该设置结束检查。该设置的 15 分钟上限是固定的,提高 stream guard 自身的上限也不会提升它。
失败的检查点会在其停止 Goal 之前显示出来。当活动 Goal 的停滞连续计数运行时,底部药丸会自动切换为 checkpoint N/3 stalled;一旦 Goal 暂停或停止,药丸则显示该状态。Web Shell 的 Goal 状态栏无论状态如何都会显示该计数。每当终端 Goal 状态卡被渲染时,例如通过 /goal 或暂停、恢复、验证器卡片,它会显示在 Goal 允许的三次检查中有多少次连续停滞,以及最后一次失败(如果有记录);Web Shell 的 Goals 对话框和无头 /goal 文本输出显示同一行,而 Web Shell 的 Goal 事件转录卡片仅显示停止原因,模型在读取 Goal 时会看到这两个字段。在窗口仍有空间时失败的检查也会显示,但不会消耗停滞计数,且仅在 Goal 处于活动状态时显示,或者当该失败本身就是导致 Goal 停止的原因时显示,例如检查点请求过大无法发送。因任何其他原因导致的检查点停止会清除失败并保留连续计数,已完成的 Goal 不显示检查点行。失败信息保留为单行,控制字符已移除。因三次停滞检查点而停止的 Goal 会说明最后一次遇到的情况。无法在检查点声明边界内适配窗口的检查,无论是仍留下证据的完整声明列表,还是超出声明数量或大小预算的声明,都意味着目标产生的证据超过一个窗口所能容纳的,因此需要缩小目标。无法折叠为声明的回答意味着检查点模型未返回所要求的结构化输出,缩小目标无法修复此问题。从未响应的检查可能意味着提供者不可达或受到速率限制、检查未在 model.goalCheckpointTimeoutSeconds 内完成,或检查本身出错;记录的失败信息会说明是哪种情况。在以上任何一种情况之后恢复都会开始一个新的证据窗口。
中断 Goal
取消 Goal 的轮次会暂停该 Goal。在模型回答时或其工具仍在运行时按 Esc,轮次停止,Goal 移至 paused,卡片和 /goal 都会说明停止原因。在你运行 /goal resume 之前,不会有任何继续。
在 Goal 处于活动状态时输入消息不会暂停它。你的消息会作为下一个 Goal 轮次运行,因此可以用它来引导工作;使用 /goal pause 或 /goal clear 来停止。
每次暂停都会说明原因:是你中断了它,是你运行了 /goal pause,是会话 token 限制阻止了下一个模型请求,还是轮次失败了,还是连续三个轮次都没有记录验证器可判定的内容且没有提案——Goal 簿记读取(get_goal、update_goal)不算作进度。因限制而停止的 Goal 保留该限制的原因。
Goal 如何判定
验证器不会自行运行命令或读取文件。它只能看到对话记录中已有的内容:
- 可见的助手输出和工具结果算作证据。目标文本、你的 prompt 和模型的隐藏推理不算。
- 打印的文本只能证明文本被打印了。关于测试通过、文件已更改或远程已更新的声明需要对话记录中有相应的工具结果。
- 关于你确认、选择或批准了某事的声明需要来自你的真实消息;验证器会拒绝假设已确认的提案。
- 当证据缺失时,判定结果为”尚未完成”,而非”已完成”。没有人能提供证据的条件会让循环持续运行,直到限制将其停止。
因此,目标必须让代理产出证据:运行指定的检查并展示决定性的输出。
编写一个好的目标
按以下顺序将这些部分写入目标:
| 部分 | 要写的内容 |
|---|---|
Outcome: | 一句话:完成时什么是成立的。 |
Done when: | 编号的二进制检查。至少一项要指定命令及其预期退出码或输出行,并要求粘贴该行。 |
Must not: | 不要触碰的文件、不要弱化的测试或阈值、不要采取的不可逆操作(push、delete、publish)。 |
Budget: | 关于何时放弃的建议性模型指令,例如 “stop as blocked after 20 turns”。要强制执行限制,请在设置中设置 model.goalMaxTurns 或 model.goalMaxActiveMinutes,而非在此处。 |
On block: | 受阻时报告什么,以及人类必须做出什么决定。 |
Context: | 仅包含代理无法在工作区中找到的事实:分支、环境、早期决策。 |
保持一个目标。/goal set 和 /goal edit 接受任意长度,但大致不超过 1,200 个字符:目标会在每个 Goal 轮次重新发送。模型通过 propose_goal 提出的目标上限为 1,500 个字符。两个命令都会将换行折叠为空格,因此请对条目编号,而不要依赖换行。
Budget 是给模型的指令,告诉它何时停止并报告阻塞;模型可能会也可能不会遵守它。要使运行时本身在轮次数或时长处停止,请设置 model.goalMaxTurns 或 model.goalMaxActiveMinutes。在目标中写入这两者不会配置它们,也不会更改 Goal 的 token 预算。
| 弱目标 | 失败原因 | 更强的目标 |
|---|---|---|
| make checkout faster | 没有阈值,没有检查。 | Outcome: checkout p95 is below 250 ms. Done when: 1) npm run bench:checkout exits 0 and prints p95 < 250 (paste the line); 2) npm test exits 0. Must not: change the benchmark or skip tests. Budget: as model guidance, stop as blocked after 20 turns. On block: report the measured p95 and what blocks it. |
| clean up the auth module | ”Clean”没有可观测的证据。 | 思考什么是可观测的:src/auth 中零 lint 警告、覆盖率阈值、文件数量。 |
| ship the release | 不可逆,且需要人类决定。 | 缩小为可检查的预发布状态(tag 存在、npm run release:dry-run 退出码为 0),并将”do not publish”写入 Must not。 |
| after I confirm the design | 验证器无法看到从未发生过的确认。 | 将其移至 On block: 作为人类必须做出的决定。 |
让 /goal-draft 帮你编写
/goal-draft <what you want done> 是一个内置 skill,可以帮你完成上述工作。它只读取工作区中足以确定范围和真实验证命令的内容,不会运行测试、构建、安装依赖或启动服务。当关键选择不明确时,它最多询问一轮问题,然后编写一个紧凑的目标,通常包含 3–5 个完成检查(足够时更少)。显式需求会被保留;它不会为了凑数而添加检查。
对于审计,完成意味着覆盖约定的场景并报告证据,包括已确认缺陷的复现步骤。未发现缺陷也是有效结果。草稿不应发明最少的场景数、证据文件数、探索轮数或缺陷数。
如果无法确定成功标准、命令、输入路径或关键决策,该 skill 会返回一个标记为 “Needs clarification” 的草稿,其中包含 <TODO: …> 项。它不会提供该草稿供批准,也不会打印可运行的 /goal set 或 /goal edit 命令。非必要的默认值标记为 [ASSUMPTION];它们不能替代缺失的成功标准。
目标准备好后,交互式终端或 Web Shell 会话可以显示下文所述的 propose_goal 审批对话框。不支持 Goal 提议的客户端、无头运行、工具被禁用的会话以及已有活动 Goal 的会话会收到一个手动运行的命令。交接说明会指出草稿尚未应用。该 skill 永远不会自行开始工作,未经你的批准不会设置任何内容。
传入现有目标以使其更严谨:/goal-draft all tests pass and the lint is clean。对于活动的 Goal,明确的收紧请求会生成 /goal edit;替换则使用 /goal set。如果预期操作不明确,该 skill 会在其单轮问题中包含该选择。
批准模型提议的 Goal
在交互式终端或带有附加客户端的 Web Shell 轮次中,模型拥有一个 propose_goal 工具。当 /goal-draft 完成时,或者当你请求一个跨多个轮次的结果时,它可以提议目标,而不是打印一行 /goal set … 让你复制。提议以审批对话框的形式出现,显示完整的目标。批准它会像 /goal set 一样设置 Goal,在当前轮次结束时生效(模型确认并停止;第一个 Goal 轮次随后自动开始),拒绝则不设置任何内容——模型仅看到工具调用未被允许,其指令告诉它不要询问原因,也不要再次提议相同的目标。审批绑定到发起请求的轮次:如果该轮次被取消或以其他方式未到达结束,审批将被丢弃,而不会在后续消息或自动轮次下生效。任何权限规则或审批模式(包括 YOLO)都不会跳过此对话框,且该工具在另一个 Goal 处于活动状态、计划模式以及不受信任的文件夹中时会拒绝执行;子代理永远不会被提供此工具。Web Shell 使用其现有的允许/拒绝权限面板。已停止的 Goal 仅在其仍与审批时显示的版本匹配时才能被替换;更改它会使提议失效。无头运行、Web Shell 通道交付和自动轮次,以及缺少所需审批和轮次生命周期支持的 ACP 客户端保留打印的 /goal set 交接方式。
通过在用户设置中使用 goals.modelProposed: "disabled" 来关闭它。由于该设置决定模型是否可以请求启动自主循环,因此仅从用户和系统作用域遵守;工作区 .qwen/settings.json 值会被忽略并给出警告。
该 skill 被指示为只读,且只有其非变更工具会被自动批准(get_goal、read_file、glob、grep_search)。ask_user_question 故意不被自动批准,因此其问题对话框会在 skill 根据你的答案起草之前显示。与其他内置 skill 一样,名为 goal-draft 的项目或个人 skill 会覆盖它,skills.disabled 可以将其关闭。请参阅 Skills 了解内置 skill 的发现方式。