Skip to content

两种延续方式

编排器区分两种朝目标持续推进的路径:

  • 同会话 goal 回合(goal rounds)——一个代理在同一个会话中继续工作,由 goal 域(packages/goal/goal-round-driver)一次准入一个延续。这就是 ctx.goals 服务与同会话驱动所实现的。
  • 全新代理 Ralph——一个面向模型的工具packages/workflow/tool-ralph),运行一个固定工作流,把一个不可变目标交给一连串全新的子代理,每个子代理都没有会话种子。

两者都建立在两个引擎接缝上:执行脚本的 ctx.workflowEngine 与部署子代理的 ctx.subagents。Ralph 不是同会话 goal、agent-loop 模式、调度器或通用工作流特性——术语表称之为"由 workflow 与 subagent 原语组合而成的面向模型的工具策略"。

包家族

角色ctx key
workflowService Definition:脚本/运行/结果/错误/事件契约ctx.workflowEngine
workflow-worker-thread具体引擎:每次运行一个 Node worker 线程注册到 ctx.workflowEngine
tool-workflow面向模型的 workflow 工具注册到 ctx.tools
tool-ralph面向模型的 Ralph 全新代理工具注册到 ctx.tools
goal-round-driver基于 ctx.goals 的同会话延续驱动作为插件注册

工作流模型(ctx.workflowEngine

WorkflowEngine.start(request): WorkflowRun 会足够同步地校验,以在运行存在之前拒绝格式错误的 meta、无法解析的脚本、不可用的 provider 路由或不支持的每运行限制。请求形态:

ts
WorkflowStartRequest = {
  meta: { name, description, ... }   // 纯身份数据,非脚本
  script: string                     // 纯 JS 主体(无 `export const meta`)
  args?: unknown                     // 作为 `args` 全局暴露的 JSON 对象
  subagentProvider?: string          // 路由每个子级,对脚本不可见
  maxTotalAgents?: number            // 每运行子级上限
  parent: Agent                      // 把每个子 Agent 归于调用者
  signal?: AbortSignal
}

WorkflowRun 暴露 { id, meta, result, cancel(reason?), dispose() },而 WorkflowResult = { value, stopReason, error?, agentsStarted }——value 是纯 JSON,stopReasoncompleted / error / cancelledresult 永不 reject:执行失败以 stopReason: 'error' 兑现,取消以 cancelled 兑现。运行由持有者拥有;dispose() 在每条路径上都必须调用。

脚本 hook

在 worker 内部,脚本收到 args 以及这些 hook(来自 packages/workflow/workflow-worker-thread):

Hook行为
agent(prompt, { label, phase, schema?, provider?, model? })启动一个宿主侧子代理。带 schema 时返回校验过的结构化对象;否则返回最终文本。普通失败的子级产出 null
parallel(thunks)在配置的并发上限下运行 thunks;抛出的 thunk 兑现为 null
pipeline(items, ...stages)让每个 item 以 (prev, item, index) 经过各 stage,stage 间无屏障
phase(title)发出 workflow/phase 观察者叙述。
log(message)发出 workflow/log 叙述。

误用 hook(错误参数、未知选项、不支持的模式、触发上限、provider 启动失败、基础设施结果失败)会抛出致命的工作流错误,这些错误总能从 parallel()/pipeline() 中逃逸,而不是变成普通每-item 的 null

失败纪律

WorkflowError 携带 codefatal 标志。致命 code 包括 SCRIPT_PARSEMETA_INVALIDINVALID_ARGUMENTUNSUPPORTED_OPTIONUNSUPPORTED_SCHEMAAGENT_CAPITEM_CAPAGENT_STARTAGENT_RESULTRESULT_UNSERIALIZABLECANCELLED。以非 completed stop reason 正常兑现的子级不是基础设施异常——agent() 返回 null,让脚本自行处理。

事件

工作流事件是仅观察的,携带 WorkflowRunInfoid + meta)而非存活运行,因此监听者无法取得取消或销毁权限:

  • workflow/start / workflow/end 成对锚定运行。
  • workflow/phase / workflow/log 暴露脚本叙述。
  • workflow/agent-start / workflow/agent-endseq 成对锚定每次子级调用。

worker 线程执行

workflow-worker-thread 以每次运行一个 Node worker 线程来实现引擎。一个 ready/go 握手可防止启动信号取消与 worker 启动竞争、误执行脚本的初始同步切片。对每次 agent() 调用,worker 经类型化的 host/worker 协议发送 child-start;宿主调用 SubagentRuntime.start(使用运行的 provider 覆盖或配置的 provider),在兑现时记录运行、观察 result,然后发送 child-started。Provider 启动与已发布子级被分开跟踪,因此当一次启动仍在进行时发生取消或 worker 死亡,会以共享的每运行信号中止它。

worker 是隔离而非安全边界:worker 内的 node:vm 是 API 塑形机制,逃走脚本能以宿主的权限恢复 Node 能力。worker 仍把脚本 CPU 工作挡在宿主事件循环之外,让 worker.terminate() 成为真正可执行的最终停止,以空环境启动(凭据不会经 process.env 穿过),并使用 structured-clone 数据、在脚本边界做纯 JSON 校验。

配置默认含义
providerspawn宿主侧子代理 provider,供 agent() 使用。
maxConcurrentAgents0并发 agent() 上限;0 由 CPU 并行度解出。
maxTotalAgents1000单次运行中 agent() 调用总数。
maxItemsPerCall4096一次 parallel()/pipeline() 接受的 item 数。
syncTimeoutMs5000脚本初始同步切片的 VM 超时。
disposeGraceMs5000强制结算/终止前的上限。

workflow 工具(dsh-tool-workflow

面向模型的 workflow 工具接受 meta(name/description)、script(纯 JS)与可选的 args。一条 tool:<toolName> 系统提示区段承载使用策略:只在用户明确要求工作流 / 大规模多代理编排时使用;一两处委派应优先用普通 subagent 调用。 收集是同步的:execute 等待 run.result 并总是销毁运行。成功返回规范的 { runId, agentsStarted, result },渲染为 workflow "<name>" completed (<count> agent(s)),随后是 Return value: 和 pretty-printed JSON。非 completed 的 stop reason 映射为 errored 结果,绝不以部分输出充当成功。

配置默认含义
toolNameworkflow面向模型的工具名。
maxResultChars50000渲染结果上限;更长的 JSON 会被截断并附注说明。

Ralph(dsh-tool-ralph

ralph({ objective, maxRounds? }) 运行一个固定的前台工作流,把一个不可变目标交给一连串全新子代理。部署配置的 maxRounds 既是默认值也是调用覆盖的上限。每轮通过 subagentProvider 启动一个子级;该 provider 必须存在、支持结构化输出,并申报 inheritsParentContext: false。配置的 provider 作为 WorkflowStartRequest.subagentProvider 传递(固定脚本无法查看或改变路由),而解析出的轮次上限作为 maxTotalAgents 传递(把循环与引擎的总子级后盾协调起来)。

每个子级只收到不可变目标、自己的当前轮次与上限、以共享工作区为权威的指令,以及上一份结构化的 Ralph 交接(handoff)。共享工作区是长期记忆;父会话与前一个子会话被播种。交接报告包含 status: continue | complete | blocked、非空摘要、证据、后续步骤与阻塞文本。

配置默认含义
subagentProviderspawn每轮使用的全新结构化输出 provider。
maxRounds256单次运行的默认与部署上限。
maxHandoffChars16384一份轮次报告中序列化的最大字符数。
maxResultChars16384完整成功父结果中的最大字符数。

成功的终结结果是 completeblockedbudget-limited,附最后一份有界的报告与轮次数。完成与阻塞标签明确说明是某个 worker 报告了该结果,而非独立认证——Ralph 完成是 worker 的自我声明。普通子级失败会产出一条命名失败轮次并保留最后一份成功交接的错误;循环不会重试该轮。

同会话 goal 回合(dsh-goal-round-driver

goal-round-driver 通过公开的 Agent 与会话服务,把一个已激活、已 armed(armed)的 goal 变成接续的 goal 回合goal 回合是当前 goal 准入的一个延续周期,物化为一个由 goal 驱动的 turn。当某个确切的存活 Agent 处于 idle、持有已激活且已 armed、仍有剩余容量的 goal 时,驱动会先检查点待定的 goal 变更,然后为当前的 { goalId, revision } 预留 roundsStarted + 1,并以 GoalMessageSource 排入一个 <goal_round> prompt。

保留的 prompt 写出用 JSON 引用的目标与 round/maxGoalRounds,以当前工作区/工具结果/持久会话状态为权威,要求完成前有证据,并告诉模型在仍有工作未完成时保持 goal 为激活态:

<goal_round>
Objective: "<…>"
Round: <round>/<maxGoalRounds>
Continue working toward the objective in this same session. …
</goal_round>

关键性质:人类消息消耗 goal 上限;只有进入的 user/message 使 roundsStarted 递增;被视为过期的预留不会消耗轮次数。激活(armed/disarmed)是进程本地的,且刻意排除在持久化重放之外,因此恢复与 fork 需要一个后续经 /goal 或模型工具做人类授权的恢复。maxGoalRounds 属于 goal 定义;面向模型的阻塞阈值属于 dsh-tool-goal——驱动两者都不复制。

Goal 回合Ralph
Agent同会话、复用每轮全新的子级
会话种子不复制任何内容,历史保留无(只有共享工作区)
跨迭代记忆会话日志共享工作区 + 有界交接
上限maxGoalRoundsmaxRounds
评估经 goal 策略由模型驱动worker 自我声明
所在位置ctx.goals + goal-round-driverctx.workflowEngine + ctx.subagents

已知限制

  • 每次运行一个 worker 线程——没有池、热运行时或跨运行脚本缓存。
  • 无日志/恢复——进程重启无法继续一次运行。
  • 仅前台收集——没有后台启动/轮询、spill 句柄或分离式收集。
  • 无保存或嵌套工作流——脚本收不到 workflow() hook,无法递归编排。

延伸阅读

  • 子代理——每次 agent() 调用和每轮 Ralph 所使用的 ctx.subagents 接缝。
  • 会话查询与日志导出——检索 goal 回合视为权威的持久会话日志。
  • 术语表——goalgoal roundgoal activationroundRalph loopRalph handoff
  • 仓库内的子系统参考:docs/subsystems/workflow.md
  • worker 引擎 README:packages/workflow/workflow-worker-thread/README.md,以及 Ralph 工具 README:packages/workflow/tool-ralph/README.md
  • Agent Note:.agents/notes/implemented/feature/2026-07-05-dynamic-workflows.md2026-07-19-fresh-agent-ralph-workflow-tool.md
  • 同会话驱动:packages/goal/goal-round-driver/README.mdsrc/prompt.ts