← 返回目录

第 2 卷

第 2 / 3 卷日期:

每次变更都带 GoalRef(就是 id + revision)做比较后写入:revision 对得上才写,对不上(陈旧引用)就被拒绝;

已有非 complete 的目标时,create 被拒;目标 complete 之后,就能 create 一个新的了。

resume 只在还有剩余轮次容量时才接受;目标已经 active 且 armed 时也被拒,resume 本就是把它变成 active + armed,它已经在了。

activation(armed / disarmed)是进程本地状态,不写进日志,goal/change 事件里只有目标的持久字段,没有它。所以会话恢复、分叉,或进程重启后,它都回到 disarmed:

续跑不自动开,要由人明确 resume 才重新启用。这是刻意的安全设计:重启后环境(工作区、工具、provider)可能和崩溃前不一样,让模型在变了的环境里自动接着跑会出错,所以

日志回放出的 active 目标不会自动续跑,得等人确认环境、明确 resume 才继续。

怎么自动续跑:goal-round-driver 排下一轮

goal-round-driver 是一个插件,职责就一件:等 Agent 干完回到 idle(第 13 讲说的 “闲”状态),自动把下一轮排进去,也就是开篇说的“续跑”。

它只靠监听 goal/changed(goal/change 落盘后发出的事件,不写日志,只用来通知监听者)和 idle 状态,只在每次 agent 回到 idle 时做一次判断:

phase 是 active、activation 是 armed、且 roundsStarted < maxGoalRounds → 预留 roundsStarted + 1,调 agent.followup 往队列(第 13 讲的 agent.inbox)

里排一条续跑提示词。

这条续跑提示词会点明完整目标与 round / maxGoalRounds(比如 Round: 1/5),要求模型在标 complete 前给出证据、在尚未完成时保持目标 active。它还要求模型把当前工

作区、工具结果、会话状态当作判断依据,而不是只凭一句目标描述。

示例里,驱动器自动续了这么一段:

复制代码 1--- 驱动器在 idle 时自动排下一轮 ---

2第1次回到idle:phase=active,roundsStarted=0
3第2次回到idle:phase=active,roundsStarted=1
4第3次回到idle:phase=complete,roundsStarted=2

第 1 次 idle 时目标刚建好、第一轮还没开始(0 / 5);第 2 次是第 1 轮干完、驱动器自动排了第 2 轮;第 3 次是第 2 轮把目标标成 complete,驱动器随即停手。

roundsStarted 是“已准入”的轮次数:先排进队列只算预留,模型真的开始跑、进了日志才算数。

每一轮的边界(turn/start、turn/end)和 goal 变更(goal/change)都落在日志里:

复制代码 1--- 会话日志里的 goal 与轮次事件 ---

2seq0goal/change(create)
3seq2turn/start
4seq5user/message(goal,round 1)
5seq14turn/end
6seq16turn/start
7seq19user/message(goal,round 2)
8seq26goal/change(complete)
9seq39turn/end

沿着 seq 读一遍:0 是 create 落盘的目标,2 到 14 是第一轮,16 起是第二轮,26 是第二轮里模型报 complete 落盘的目标,39 收尾。注意 goal/change 只在目标变更时出现,所

中间那两条 user/message(seq 5、19)就是 round-driver 排进来的 goal 消息。它虽然记录成 user/message,但来源要看 source,round-driver 是这样构造消息的:

复制代码 1createUserMessage({

2content, 3source: { kind: 'goal', goalId, revision, round },*// ← 来源是 goal,不是 user*

4})

kind: 'goal' 就是它和用户直接发的消息的区别(13 讲里用户消息是 kind:

'user');round 是轮次编号,所以日志里能看到 round 1、round 2。

怎么停下来:三种自然停

停这件事,主要靠模型报。模型操作目标,不直接调 ctx.goals,而是走 tool-goal 注册的三个工具:

工具作用
get_goal()读当前目标,没有则返回null
create_goal(objective, max_goal_rounds?)建一个目标

改目标:edit / pause / resume / complete / update_goal(goal_id, revision, action, ...)

blocked

这三个工具都是 ctx.goals 的模型门面:get_goal 内部就是调 ctx.goals.get, create_goal 内部就是调 ctx.goals.create,update_goal 的 action 参数对应

ctx.goals 的 edit / pause / resume / complete / block(工具里这个 action 叫

全站分卷索引 · 3 卷
  1. 1第 1 卷
  2. 2第 2 卷
  3. 3第 3 卷