外观
委派工作的持久化记录:任务记录(mission)把运行包装起来以便事后恢复,调度则按定时器启动工作。
任务记录
任务记录是围绕运行(run)的持久化包装。名词对应关系如下:
- 项目/代码库(Project/codebase)—— 工作发生的地方。
- 任务记录(Mission)—— 委派工作存在的原因与事后恢复方式。
- 运行(Run)—— 一次实际的子智能体执行。
- 回执(Receipt)—— 外部产出的证明或链接,例如 PR、CI 检查、部署或发布。
默认情况下,常规的工作流启动会创建一个外层任务记录,其下的详细 JSON 记录位于 ~/.pi/agent/missions/projects/<project-hash>/,用于关联目标、运行 id、生命周期状态、决策、产物路径与投递回执。工作流子任务不会创建独立的任务记录。每次工作流子任务的尝试都存储在外层任务记录中,带有稳定的工作流键、已知时的运行 id、使用的智能体、任务元数据、时间戳、会话与产物路径以及最新的状态心跳。
旧默认路径 <project>/.pi/subagents/missions 下创建的记录仍保留在磁盘上。可通过把该项目的 missions.directory 指向该路径,或把记录复制到新的 agent 目录项目存储来继续使用。不存在自动迁移。
行为规则:
- 自动持久化的失败不会阻塞运行,并以
details.missionWarning报告。显式missionId与mission请求在启动前仍然严格校验。 - 人类可读的回执以
Mission: <id> (<status>)结尾,JSON/结构化输出文本保持不变,details.missionId为权威字段。 - 对有意临时的工作流传入
mission: false。它既不为该工作流也不为其子任务创建任务记录,且没有state全局。 - 设置
missions.enabled: false可禁用自动创建任务记录;显式的 mission 字段与动作仍然有效。 - 带有任务记录的工作流可以使用
await state.get(key)与await state.set(key, value)持久化 JSON 状态。缺失的键返回undefined。键名格式与runs.run键相同。每次 set 都会获取状态文件锁,读取最新文件,合并键,然后原子地写入<mission-directory>/<mission-id>/state.json。完整文件大小不能超过 256 KiB。每个工作流在首次get时缓存该文件。mission:false的工作流没有state全局。
显式 mission 对象必须且只能有一个非空的 title 或 summary。objective 与 labels 可选。若提供 goal,其值必须为 true,且需要 budget: { tokens: <positive integer> }。
ts
const created = subagent({
action: 'mission.create',
mission: { title: 'Ship auth refresh', objective: 'Implement and validate token refresh' }
});
subagent({
workflowScript: `return runs.run("main", { agent: "worker", task: "Implement the approved auth refresh plan" })`,
missionId: '<mission-id>'
});
// 或者在一次启动中创建并关联
subagent({
workflowScript: `return runs.run("main", { agent: "worker", task: "Implement the approved plan" })`,
mission: { title: 'Ship auth refresh' }
});目标型任务记录
设置 goal: true 与令牌预算,把开放的任务记录变为活跃的续接驱动器:
ts
subagent({
action: 'mission.create',
mission: {
title: 'Ship auth refresh',
objective: 'Implement and validate token refresh',
goal: true,
budget: { tokens: 400000 }
}
});每次父轮结束后,空闲的目标型任务记录会发送一条"需要关注"通知,包含其标题、剩余令牌预算与下一个就绪动作。该动作取自 state.nextReadyAction、state.nextAction、status: "ready" 的状态项、未决决策,或关联的运行状态。工作流可以写入 state.nextReadyAction 来告知下一条通知具体什么工作已就绪。当最新关联的工作流带有可续接的保留子任务时,通知会将其命名为 resume 目标。不可续接的保留子任务会在 children.list 中保留并附上原因,但目标通知不会把它们呈现为 resume 目标。本扩展不会自行启动或重新规划目标工作。
关联运行的令牌总量存储在每次运行上,并汇总入任务记录的 usage。处于活跃状态的关联运行会抑制通知。达到令牌预算后,目标状态变为 budget-exhausted,通知停止,但任务记录不被关闭,也不报告成功。
使用 mission.update 与 { goal: { paused: true } } 或 { goal: { paused: false } } 暂停与恢复通知。设置 { goal: false } 禁用目标模式。mission.close 也会结束循环。
管理任务记录
使用 mission.list、mission.show、mission.update、mission.resolve-decision、mission.attach-run、mission.close。
- 使用
mission.update在工作进行中记录决策、产物、标签、摘要与投递回执。添加决策会把活跃或已完成的任务记录门控为needs_decision;计划中与等待中的任务记录在决策可见期间保留其生命周期状态。通过mission.resolve-decision、missionId、决策的id以及summary中的解决方案来消除该决策。当最后一条未决决策被消除后,被门控的任务记录恢复为active。 mission.show包含每个工作流子任务的最新状态、阶段、更新时间、会话路径元数据与心跳。该账本是恢复用记录,不调度也不重启子任务。- 回执是 PR、CI、部署或发布的持久化链接,每条都包含
kind、status、title、url,以及可选的description。它们只记录投递状态;pi-subagents 不会合并代码、轮询 CI 或执行部署。 - 当任务记录完成时,使用
mission.close并传入终态状态与摘要。 - 压缩或重启后,先从
mission.list/mission.show恢复:mission.show会在可用时刷新关联的异步状态,然后使用关联的运行 id 进行常规的status、steer、resume、stop动作。 - 带
missionScope: "global"的mission.list读取 Pi agent 目录下的用户本地指针索引。项目记录仍为权威源;缺失记录会被报告为陈旧,而非隐藏其他项目。
跨项目工作
把同项目的任务保留在普通子智能体上。对其他项目中小的、有边界的工作使用显式 cwd。
对另一项目中大规模或长期运行的工作,使用 project.open 打开一个项目自有的 Herdr 面板,并给该项目的 Pi 会话一个狭窄的 mission/result 契约(参见 extension-api.md)。项目面板拥有自己的子智能体;不要把它建模为普通的子嵌套,也不要指望现有的无头运行会移入该面板。
任务记录存储配置(missions.directory、retainTerminal、globalIndex)位于 configuration.md。
调度
持久化的调度默认启用,按项目存储于 .pi/subagents/schedules/<id>/。
创建一个一次性调度:
ts
subagent({
action: 'schedule.create',
id: 'evening-review',
name: 'Evening review',
at: '+30m',
baseRef: 'refs/heads/release',
workflowScript: `return runs.run("main", { agent: "reviewer", task: "Review the current diff." })`
});创建一个固定周期的工作流:
ts
subagent({
action: 'schedule.create',
id: 'backlog',
every: '6h',
catchUp: 'latest',
workflowScript: '...'
});固定间隔支持 m、h、d、w 单位,并按计划时间推进,不会因完成时间漂移。
创建一个静默的周期工作流,其成功完成保持可见但不会唤醒父会话:
ts
subagent({
action: 'schedule.create',
id: 'nightly-sweep',
every: '24h',
quiet: true,
workflowScript: '...'
});使用 schedule.list、schedule.show、schedule.history、schedule.pause、schedule.resume、schedule.run、schedule.run-due、schedule.delete 管理调度。
行为规则:
- 运行始终以异步方式启动,携带全新上下文,并禁用自动创建任务记录;任务记录的关联在该首片中延后处理。
- 可选的顶层
baseRef选择托管工作树使用的安全 Git 引用(默认HEAD);它随调度持久化,并在每次触发时转发。源码检出目录仍需保持干净。 - 定义、有界的历史、仅追加的事件以及每次运行的回执都以模式
0600存储。 overlap当前固定为skip;catchUp支持latest(默认)与none。- 一次成功的
schedule.run满足下一次自然触发;失败的手动启动不会跳过该次触发。 quiet仅在周期(every)调度上持久化。成功的自动触发保持可见但不进入父轮;失败、停止或暂停的结果仍会唤醒会话。一次性at调度与schedule.run保持喧闹,除非该次启动显式传入quiet: true。schedule.run-due允许外部启动器启动到期的项目工作,而无需把pi-subagents变为守护进程。- 日历型循环、cron、队列/替换型 overlap 以及调度 TUI 检查器被刻意延后到下一片。
- 旧的
schedule、schedule-list、schedule-status、schedule-cancel动作已在硬切换中移除。
通过 configuration.md 中的 scheduledRuns 配置键禁用或限定调度。
