第 2 卷
| script | 是 | 要执行的脚本 |
|---|---|---|
| meta | 是 | 脚本的元信息(name、description等) |
| 每个子 都归属它( 讲的 ) 并继承 作目 |
start 返回一个 WorkflowRun(运行句柄),await 它的 result 就行,不用 try/catch:失败不会抛异常,而是记在结果里。result 的字段:
字段含义
脚本 return 的值(只有 completed 时才有意义),必须是纯 JSON value (不能带函数、类实例或循环引用)
| stopReason | 为什么停:completed / cancelled / error |
|---|---|
| error | 非completed时的失败信息 |
| agentsStarted | 这次一共启动了几个子agent |
Workflow 怎么编排:模型现写脚本
Workflow 是模型驱动的那条路:模型现场写一段脚本、传给 workflow 工具,编排逻辑全在脚本里。
Workflow 示例取了个最小任务:运行时在系统临时目录(os.tmpdir())下新建一个 ch17-workspace-* 目录、往里放好 src(5 个文件)和 docs(3 个文件),提示词
让模型派两个子 agent 各数一个目录,实际路径运行时会打印在控制台。注意:真实场景 Workflow 面向更大规模,一两项委派用普通 subagent 就够。
workflow-demo.ts 给模型的提示词就一句:
模型据此调了 workflow 工具,传的参数长这样,本次传 script 和 meta,args 可选没传:
复制代码 1{
2"meta": { 3"name": "count-src-docs-files",
| 4 | "description":"Fan out two subagents to count files in src/ and docs/ …", |
|---|---|
| 5 | "whenToUse":"…", |
| 6 | "phases": [ |
| 7 | {"title":"count-directories","detail":"…"}, |
| 8 | {"title":"aggregate","detail":"…"} |
| 9 | ] |
| 10 | }, |
| 11 | "script":"(脚本正文,见下文)" |
| 12 } |
工具内部调 workflowEngine.start() 时,引擎实际收到的 request 长这样,其中 script/meta 原样转、parent/signal 由工具补:
复制代码 1{
2"script": "(同模型传的 script)", 3"meta": "(同模型传的 meta)",
| 4 | "parent":"(当前调用workflow工具的agent)", |
|---|---|
| 5 | "signal":"(取消信号)" |
| 6 | } |
script 的正文展开是下面这段,它就是普通 JavaScript,以顶层 await 的方式执行,所以可以 await 子 agent 的结果、最后 return 汇总;它只干两件事:一是用 agent() 派
注意:这里只留关键⻣架,失败兜底等次要部分省略:
复制代码 1*// 模型写的脚本。ROOT 是它把工作区目录写死成的绝对路径
2const ROOT = '/tmp/ch17-workspace-xxx' 3
| 4 | //让子agent返回一份对象(结构化输出),而不是一段话 |
|---|---|
| 5 | constcountSchema = { |
| 6 | type:'object', |
| 7 | properties: { |
| 8 | fileCount: {type:'number'}, // ←脚本最后要的"文件数" |
| 9 | // …还有directory / exists / sampleFiles / method |
| 10 | }, |
| 11 | } |
12
| 13 | functioncountPrompt(dir) { | //教子agent:用find数文件、别猜 |
|---|---|---|
| 14 | return`Count the regular files under "${ROOT}/${dir}" …` | |
| 15 | } |
16
| 17 | //编排核心:parallel()并发跑这两个agent(),各自派一个子agent |
|---|---|
| 18 | const[src, docs] =awaitparallel([ |
| 19 | () =>agent(countPrompt('src'), {schema: countSchema }), // schema →子agent |
| 20 | () =>agent(countPrompt('docs'), {schema: countSchema }), |
| 21 | ]) |
22 23// … 汇总(真实脚本还有失败兜底:子 agent 失败变 null → 记 agentFailed;还会拼 summary 等
24**return { totalFiles: src.fileCount + docs.fileCount, perDirectory: [src, docs]
运行后(示例输出):
复制代码
| 1 | ---子agent内部:每一步都留在它自己的会话里--- |
|---|---|
| 2 | 子agent#1(会话…) |
| 3 | 第1步:等模型回话 |
| 4 | 调工具bash({"command":"find \"…/src\" -type f | wc -l", …}) |
| 5 | 工具返回:5 |
| 6 | 第2步:等模型回话 |
| 7 | 调工具bash({"command":"find src -type f | head -5 …", …}) |