system/work-graph-templates/
Work Graph(org node 级 workflow)的骨架模板库。与 system/org-graph-templates/(公司级)同构,
只是低一层:那边一家公司一张图、活整个公司生命周期;这边一个 org node 接到一次任务规划一张图,用完即归档。
每个 *.json 是一种 org node 职能的执行流图起点。org graph 上的节点被执行到时,引擎调
workgraph-planning(全局通用本体,27-REQ R-15.2),它会 ls 本目录、逐个读取、对照各自的 whenToUse
选型,再结合宿主 org node 的角色定义、本次任务描述、可读的 artifacts/、上一轮 remediation_note,
裁剪 / 替换 / 组合出这次真正要跑的 work graph。
设计依据:27-P3/P4 §四.D.0 / §四.D.2.2 / §四.D.3 / §九bis 命名规范:27-NAMING §二 / §三
这是起点集合,不是穷举枚举。 加一种起手式只需往本目录扔一个 JSON 文件,不改任何代码。
模板里的 systemAgentId 只是建议,workgraph-planning 必须拿真实的 system agent 清单核实。
当前模板
| 文件 | id | 宿主 org node | 节点链 |
|---|---|---|---|
planner.json |
planner |
规划类(org-planner) |
brd → prd → sdd → benchmark → validator |
executor.json |
executor |
执行类(org-coder / org-writer / org-monitor),单交付物 |
impl → test → validator |
executor-fanout.json |
executor-fanout |
执行类,可并行拆分 | split → (impl/test)×N → merge → integration → validator |
validator.json |
validator |
org-validator 专用 |
validator-reflection → benchmark-validator → testdata-validator |
四张图共享一个形状:做 → 自检 → 本层验收,验收失败沿 backward 边退回重做。差异只在中段。
{{占位符}} 必须替换
executor*.json 里的 {{orgNode}} / {{implAgent}} / {{testAgent}} / {{validatorAgent}} /
{{splitAgent}} / {{mergeAgent}} / {{integrationAgent}} 是占位符,不是合法值,
提交前必须全部替换成真实的节点名与本体名,否则落库出来的是一张引用不存在 agent 的废图。
{{orgNode}}← 宿主 org node 的全名(如org-coder)。{{xxxAgent}}← 一个真实存在的 system agent 本体 id。核实方式见下一节。
planner.json / validator.json 没有占位符——因为 org-planner 与 org-validator 在三个
org graph 模板里首尾同名(27-NAMING §3.1),它们的 work graph 节点名可以写死。
节点名 ≠ 本体名(27-NAMING §3.2,最容易搞错的一条)
| 规则 | 例 | |
|---|---|---|
nodeName |
图内唯一,带宿主 org 节点前缀 | org-coder-validator / org-planner-benchmark |
systemAgentId |
跨图复用的本体,不带领域前缀 | coder-validator / goal-benchmark |
本体若被迫带前缀,coder-validator 会复制成多份,与 P1「同一份本体、多处引用、各自私有语境」直接冲突。
⚠️ 唯一的例外是
validator.json里的三个节点:validator-reflection/benchmark-validator/testdata-validator按 §3.1 字面规则本应写成org-validator-reflection等,但 27-P3/P4 全文用的是 父节点职能的简写,27-NAMING §3.5 记为待定案。定案前一律按简写书写,不要以任一方去改另一方。
validator.json 为什么归因排第一位
org-validator 判定任务未达成时该退回 org-planner(规划有问题)还是 org-coder(实现有问题)?
这个判断不由失败节点顺手吐出,而是由 org-validator 自己 work graph 里排第一位的专职归因节点
validator-reflection 做出(27-REQ R-16)。它的产出 fail_reason + remediation_note 随子 run 收敛
透传回 org 层(§四.D.0 三值透传),成为 org graph 选边的唯一依据。
三个 fail 出边的走向由此确定:
benchmark-validator/testdata-validator验收不过 → 兜底 backward 边退回validator-reflection归因;validator-reflection故意不留 fail 出边——它归因完发现「这层修不了」时以 fail 收尾, 引擎判为死路 → 节点blocked→ 子 runblocked→ 父节点拿到fail+fail_reason+remediation_note, 回到 org 层按 §四.D.2.2 选边。这是设计好的收敛出口,不是漏画的边。
反复归因不会失控:backward 边有单边 loop_count ≤ 3 与 run 级 backward_count ≤ 5 的双层熔断
(§四.D.2.1),撞顶直接 force_terminated,纯整数比较,不依赖任何 LLM 判断。
文件格式
{
"id": "planner", // 必填,与文件名同名(不含 .json)
"label": "规划型 org node 的 work graph", // 必填,给人看的中文名
"whenToUse": "……", // 必填,LLM 选型的唯一依据:适用场景 + 典型信号词 + 与其他模板的区别
"ownerOrgNode": "org-planner", // 必填,这张图挂在哪类 org node 下;占位符写 {{orgNode}}
"nodes": [
{ "nodeName": "org-planner-brd", "systemAgentId": "brd-planning" },
{ "nodeName": "org-planner-benchmark", "systemAgentId": "goal-benchmark",
"writesArtifacts": true }, // 可选,声明它有权写 root run 的共享 artifacts/
{ "nodeName": "benchmark-validator", "systemAgentId": "benchmark-validator",
"readsArtifacts": ["goal-benchmark.json"] } // 可选,声明它读哪些共享产物
],
"edges": [
{ "from": "org-planner-brd", "to": "org-planner-prd", "condition": "success" },
{ "from": "org-planner-validator", "to": "org-planner-prd", "condition": "fail",
"failReason": "input_underspecified", "edgeKind": "backward" },
{ "from": "org-planner-validator", "to": "org-planner-sdd", "condition": "fail",
"edgeKind": "backward" } // 无 failReason = 兜底边
]
}
condition:"success"|"fail",边的语义是执行流(上游出这个结果时流向下游)。edgeKind:"forward"(默认,可省略)|"backward"。指向拓扑序更早节点的边必须显式标backward。failReason:仅condition: "fail"的边可带,是失败的细分路由键(对应work_graph_edges.fail_reason列)。 省略即为该节点的兜底边。取值域不由引擎约束,推荐取值见 27-P3/P4 §四.D.2.2 (impl_bug/input_underspecified/skill_defect/infra_flake)。nodeKind:"agent_call"(默认,可省略)|"subgraph"。work graph 节点默认是一次 agent 调用; 只有确实要再下钻一层图的节点才写subgraph。writesArtifacts/readsArtifacts:可选声明,对应 §四.A.5 的共享产物区读写权。 写artifacts/是特权动作,只有被显式标记的节点才有,防止任意节点往共享区乱写。
加一个新模板
- 新建
system/work-graph-templates/{id}.json,按上面的格式填。 - 节点名遵循
{宿主 org 节点全名}-{职能},本体名不带前缀(27-NAMING §3.1 / §3.2,见上文对照表)。 - 避开这 6 个命名冲突 id:
agent-creator/digester/evolver/evolver-youtube-crawler/hunter/innovator。它们在system/agents/与system/templates/下同名但内容可能不同步。 workgraph-planning自己不要出现在图里——它规划图,但不是图上的节点。- 不要把
RESEARCH → PLAN → EXECUTE → VERIFY四段式画进图里,也不要指望节点内部去跑它 (27-P3/P4 §九bis)。work graph 本身就是那张图的泛化版,两层并存会让两层 Context Flush 互相清对方的上下文。详见下一节。 - 人工验算五项校验(写入 API 也会校验,但模板先自查能省一轮 LLM 重试):
| # | 规则 | 怎么自查 |
|---|---|---|
| 1 | 无环(只看 forward 边) | 把所有 backward 边划掉,剩下的边必须能排出拓扑序 |
| 2 | 恰好一个入口 | 只数 forward 边的入度,入度为 0 的节点必须恰好一个 |
| 3 | 全可达 | 从入口沿 forward 边 BFS,必须覆盖 nodes 里每一个节点 |
| 4 | 回退边显式标注 | 任何 to 在拓扑序上早于 from 的边,必须带 "edgeKind": "backward" |
| 5 | fail 兜底边 | 有 fail 出边的节点,其中必须至少有一条不带 failReason |
- 自验:直接拿引擎真正用的那套校验跑一遍本目录全部模板(占位符不影响校验,它只做名字匹配):
node -e "
const fs=require('fs'),p=require('path'),{validateWorkGraph}=require('./server/services/work-graph-db.js');
const d='system/work-graph-templates';let bad=0;
for(const f of fs.readdirSync(d).filter(f=>f.endsWith('.json'))){
const t=JSON.parse(fs.readFileSync(p.join(d,f),'utf-8'));
const r=validateWorkGraph(t.nodes,t.edges);
console.log(f,r.ok?'OK':'FAIL',r.ok?'':JSON.stringify(r.errors));
if(!r.ok)bad++;
}
process.exit(bad?1:0);"
🚫 不要在节点内部再套四段式(27-P3/P4 §九bis)
system/templates/base/ 的基座员工被要求跑 RESEARCH → PLAN → EXECUTE → VERIFY,
每次流转靠 node bin/lemon.js task transition 清空上下文(Context Flush)。
work graph 的节点本身就是这套东西的泛化版——同一次执行里两层都跑,两层 Context Flush 会互相清对方的上下文。
定案:图是唯一的流转层。 阶段顺序由边定义提供,阶段间产物由 output_ref 传递,
失败回退由 backward 边 + 熔断提供,不需要节点内部再来一遍。
| ❌ 不要 | ✅ 要 |
|---|---|
| 一个节点的 prompt 里写「先 research 再 plan 再 execute 再 verify」 | 一个节点只做一件能一句话说清「做完什么算成功」的事 |
让节点自己调 task transition 换阶段 |
让引擎按边推进到下一个节点 |
| 把四段式画成图里的四个节点,再让每个节点内部也跑四段式 | 要拆调研/规划就直接拆成图上的相邻节点,只拆一层 |
把四段式改写成引擎上的一张标准图模板是 P3 之后的待办,本目录不预先实现它。