工作模式 (并行子 Agent 架构):
为了彻底隔离重负载上下文(含 Base64 图片和 Phase 1 漫长推理历史)并最大化提取效率,主 Agent 必须使用 Task 工具将 Phase 2 任务分流给 2 个并行的子 Agent。
taxonomy-lookup 查询和 wf-patch 校验。物理切片与图片分流:主 Agent 在启动 Phase 2 时,必须先运行物理切片脚本:
python spec/tools/prepare-subtask.py --workflow outputs/case-N/workflow.json --source input/case-N.json --out-dir outputs/case-N/_scratch
该脚本会自动在 outputs/case-N/_scratch 目录下生成最小化的子任务定义文件 task_2a.json 与 task_2b.json。
task_2a.json 和 task_2b.json 不仅包含了精简的 IO 变量与步骤信息,还在根节点内置了当前 Case 的完整图集 image_url_list,并为每一个具体的 IO 变量对象级关联了其对应的 related_images 引用数组(如识别 图05 等关联图片)。{case_dir}/_scratch/task_2a.json 或 task_2b.json,跑完查询后只返回标准的 patch_2a.json 或 patch_2b.json 补丁内容。wf-patch.py --patch 一体化应用落盘。子 Agent 召唤机制与指令示范 (主 Agent 必看):
在 run_procedure_dsl.py 环境中,我们已通过编程式(agents 字段)在 Claude SDK 中预先注册了两个常驻子 Agent 角色:
phase-2a-normalizer (作用/动作/类型归一化专家)phase-2b-matcher (实质/形式词表精确匹配专家)主 Agent 在运行中可通过以下两种极其优雅的方式激活并分流任务:
直接在 prompt 里命令子 Agent 工作,或在 Tool call 中指定其名称调用:
// 1. P2A 子 Agent 显式召唤示例:
Agent(
subagent_type="Explore",
description="召唤 phase-2a-normalizer 专家处理 2A 任务",
prompt="请 phase-2a-normalizer 子 agent 立即读取 outputs/case-N/_scratch/task_2a.json 任务文件,结合 spec/ 里的 effect.json、action.json、type.json,为各步骤和 IO 变量完成作用/动作/类型归一化。完成后请在 outputs/case-N/_scratch/ 下写入标准的 patch_2a.json 并向我汇报具体修改项。"
)
// 2. P2B 子 Agent 显式召唤示例:
Agent(
subagent_type="Explore",
description="召唤 phase-2b-matcher 专家处理 2B 任务",
prompt="请 phase-2b-matcher 子 agent 立即读取 outputs/case-N/_scratch/task_2b.json 任务文件,使用 spec/tools/taxonomy-lookup.py 工具查询词表,查出各 IO 变量最精准的 substance/form 路径。完成后请在 outputs/case-N/_scratch/ 下写入标准的 patch_2b.json 并向我汇报具体修改项。"
)
由于 SDK 在后台配置了 AgentDefinition,主 Agent 在发起一般的 prompt 对话时如果提到相关职责,Claude SDK 也会基于 descriptions 自动路由调用:
Use the phase-2b-matcher agent to run taxonomy lookup for task_2b.json and generate patch_2b.json
这样:
context: workflow.json + spec §A.1 (作用树, 9 叶) + §A.2 (动作树, 5 L1 + 控制) + §A.3 (类型树, 4 大类) + 现有 type_registry — 全部小, 整体进 context。
任务:
提取/化学提取/反推、生成/元素生成); 控制类 控制/并行 控制/遍历 自动转到 特性 字段类型归一 (对每个 input/output 的 type, 走以下 funnel 不要省步骤):
候选扩展: 基于 IO 的 name + value 描述, 显式列出 3-5 个候选 type 词 (不是只猜一个).
<图: 苏晚 25 岁年轻女性肖像, 卧室床上> →
候选: [参考图, 主角图, 人物肖像, 人物参考, 分镜图]字典匹配 (按优先级, 命中即停):
$leaves)? 用它 (e.g. 候选含"参考图" → 命中)b. extends 桥接: 都没命中, 但有候选语义贴近某叶子 → 选最近 leaf 做 extends. Edit workflow.json, 在该 procedure 顶层加 type_registry 段 (每个 procedure 独立 type_registry, 单 case 多工序时不冲突). 格式:
// workflow.json (部分)
{
"procedures": [
{
"id": "p1-simple",
"name": "...",
"type_registry": {
"主角图": {"extends": "参考图", "desc": "case-specific 主角肖像"}
},
"steps": [ ... ]
}
]
}
⚠ 不要只在 IO item 内 inline 写 extends 子字段 — renderer 走 procedure 顶层 type_registry 找, IO inline 字段它不读.
不必手工写 type_suggestions.md:
Phase 3 跑 bin/lint-case.py --workflow 时, 会自动扫每个 procedure 的 type_registry 把所有 case-specific entry record 到 spec/taxonomy/type_suggestions.md (幂等, 同 (type_name, case_id) 只写一次). 你只要保证 procedure.type_registry 每个 entry 含 extends + desc 就行, suggestions 文件让工具维护.
lint 自查 (轻量自检, 真正校验由 Phase 3 lint-case.py 跑):
[ ] 每个 IO 的 type 要么命中 §A.3 叶子 (type.json $leaves), 要么所在 procedure 的 type_registry 段里有该 type 的 extends + desc 项
[ ] 走 2b 的所有新 type 都在对应 procedure 的 type_registry 段出现
[ ] 不允许 type 字段写"自由名"但所在 procedure 的 type_registry 缺对应 entry — 这种 silent gap 会让 Phase 3 渲染 HTML 时 drawer metadata 全丢, Phase 3 lint-case.py 会捕捉到
输出: 写回 workflow.json (几十个字段批量用 wf-patch.py --patch, 见开头工作模式; type_registry 也能 --set p1.type_registry.X.extends=... 注册), 给每个 step 加 effect / action / feature / control 字段 + 给每个 IO 加 type 字段 (Phase 1.2 已有则归一, 没有则填). 不写新文件, 不写生成脚本.
context: workflow.json 中所有 input/output 的 name + value + 上下文 + 调 spec/tools/taxonomy-lookup.py tool. 实质·形式 JSON 词表本身不进 context, 完全通过 tool 查询。
tool 接口: ```
spec/tools/taxonomy-lookup.py --dim {实质|形式} --list-l2 # 列二级路径 spec/tools/taxonomy-lookup.py --dim {实质|形式} --subtree # 返回子树 (叶子 + alias) spec/tools/taxonomy-lookup.py --dim {实质|形式} --match "" # 多 token 拆词聚合 (推荐用法) spec/tools/taxonomy-lookup.py --dim {实质|形式} --narrow "" # 层级下钻 (--match miss 兜底) spec/tools/taxonomy-lookup.py --dim {实质|形式} --validate # 校验路径存在 ```
任务 (对每个 input/output value):
--match "tok1 tok2 tok3" (空格分隔, tool 自动拆词聚合)
<图: 苏晚 25 岁年轻女性肖像, 卧室床上> → --match "年轻女性 卧室 床上 肖像"--match 返 (无匹配) → 同 query 切 --narrow 走层级下钻 (按子树整体语义打分)--subtree <候选> 列叶子细节, 选最贴的--validate <chosen_leaf> 确认前再写回; 完全无法匹配 → unmatched产品需求、结构化提示词、分层提示词 等文本,虽然物理形式上是“文本”,但它们在实质(Substance)上承载了具体的业务内容(例如:提示词若描述冲锋衣,实质即为 /理念/知识/商业/产品服务/产品特征;若描述登山场景,则为 /理念/知识/商业/产品服务/使用场景)。它们决非纯工具参数,必须为其匹配对应的实质路径。i、纯控制流指令等)才允许设为 null。⚠ 避坑: 不要把整段 value 描述塞进
--match(e.g.--match "苏晚 25 岁年轻女性, 卧室床上, 湿发素颜"), 标点会被当 token 一部分干扰拆词. 提炼 2-5 个干净的描述性词组就够.
输出: 写回 workflow.json (几十个 IO 批量用 wf-patch.py --patch, 见开头工作模式; substance/form 会自动走 taxonomy-lookup 校验, 设 null 传 __null__), 给每个 IO 加 substance: /xxx/yyy 或数组 ["/xxx/yyy", "/zzz"] + form: /xxx/yyy 或数组 (或 null). 不写新文件, 不写生成脚本。对于复杂内容,推荐在 CLI 传入时用 + 连接多条路径 (如 /表象/视觉/人物 + /表象/视觉/空间),wf-patch.py 会自动校验并将其作为 JSON 数组保存至 workflow.json 中。