加一个工具四步、加一条流水线三步:OpenMontage 的扩展契约
OpenMontage 的 README 在 Contributing 一节里给扩展留了两条清单:加一个工具四步,加一条流水线三步。加起来七行。
七行看着不像门槛。但这个项目的架构前提是「没有代码编排器」——Python 只提供工具和持久化,编排、创意决策、评审标准全写在 YAML manifest 和 Markdown skill 里。在这样的项目里做扩展,「代码写完」离「agent 会照你想的方式用它」还隔着好几层。这篇就把这七行摊开,看每一步背后实际要对上哪个目录、哪个字段、哪条契约条款。
先把七行原文摆出来
README 的 Adding a New Tool:
- Create a Python file in the appropriate
tools/subdirectory - Inherit from
BaseTooland implement the tool contract - The registry auto-discovers it — no manual registration needed
- Add a skill file if the tool needs usage guidance
Adding a New Pipeline:
- Create a YAML manifest in
pipeline_defs/ - Create stage director skills in
skills/pipelines/<your-pipeline>/ - Reference existing tools — or add new ones if needed
这一节结尾还指了三份参考:docs/ARCHITECTURE.md(README 定位为完整技术参考,525 行)、docs/PROVIDERS.md(完整 provider 指南,含配置、定价、免费额度)、AGENT_GUIDE.md(agent 契约)。前两份我们没有读过内容,下面不展开,只在该指路的地方指路。
第一步的坑在「appropriate」这个词上
「放进 tools/ 的相应子目录」,前提是你知道有哪些子目录。README 架构图列了七个:video/、audio/、graphics/、enhancement/、analysis/、avatar/、subtitle/。我们实读 tools/,除这七个之外还有 capture/、character/、publishers/、_comfyui/、_kling/;顶层还有 base_tool.py、cost_tracker.py、google_credentials.py、tool_registry.py 四个 Python 文件。非 __init__.py 的 Python 文件实读为 130 个。README 的架构图是简化过的——这是两处文本之间可核实的差异,以仓库当前状态为准,我不推断原因。
子目录的语义边界也比名字宽。架构图里 tools/graphics/ 那行原文写的是 “9 image/graphics generation tools + diagrams, code snippets, math”,即除了图像还包含图表、代码片段、数学三类;README 的图像生成 provider 表里确实把 ManimCE 列了进去,而它的 Notes 写的是 “Mathematical animations”。所以你要加的东西如果是「生成一张图」之外的静态视觉产物,graphics/ 大概率仍是它的位置。
还有两处计数口径值得先知道,免得你按 README 的某个数字去对齐目录:视频那张 provider 表是 15 行,而架构图里 tools/video/ 写的是 “13 video gen tools + compose, stitch, trim”——一个数 provider,一个数 tool,不是同一个口径;TTS 那张表列了 5 个 provider,架构图里 tools/audio/ 写的却是 “4 TTS providers”,这两处写的不一样。我只陈述差异,不推断哪个是对的,也不拿它评价项目。落到实操上就一句话:确定目录时以你实读到的目录结构为准,别以架构图为准。
第二、三步:继承 BaseTool,然后不用注册
第二步「继承 BaseTool 并实现工具契约」对应的文件是 tools/base_tool.py,第三步「registry 自动发现,不需要手动注册」对应 tools/tool_registry.py。base_tool.py 的内容我们没有读过,「工具契约」具体要求实现哪些东西,请以仓库源码为准,这里不编。
「自动发现」这个设计的好处很明显:没有一张需要你手改的注册表,也就没有「代码合进去了但忘了注册」这类事故。代价是判据从「你有没有登记」挪到了「你的文件位置、类的写法、契约实现是否符合它扫描的预期」——这条路径上没有「未注册」这样一个现成的检查点可用,出问题时该看什么,取决于 tool_registry.py 实际怎么扫描,那份代码我们没有读过。
关于 registry 对象,从 README 给的两条能力查询命令的调用形式可以直接读出它至少提供 discover()、support_envelope()、provider_menu() 三个方法。它们各自返回什么结构、有哪些字段,我们没有读过 tool_registry.py 的代码,不描述。
第四步写得像可选,但契约里不是
「若工具需要使用指导,再加一个 skill 文件」——这句话的语气最容易让人跳过。把它放回三层知识里就不一样了。README 的分层是:Layer 1 是 tools/ 加 pipeline_defs/,回答「有什么」;Layer 2 是 skills/,回答「OpenMontage 希望你怎么用」;Layer 3 是 .agents/skills/,回答「这项外部技术本身是怎么回事」。原文明说:每个工具都声明它依赖哪些 Layer 3 skill。
AGENT_GUIDE.md 的 Rule Zero 第 5 条把这件事写成了强制项:使用任何带 agent_skills 字段的工具前,先读 .agents/skills/ 里被引用的 skill。文末的 What Not To Do 又重复了一遍——不要在没读 Layer 3 skill 的情况下调生成类工具,要查工具的 agent_skills 字段,读被引用的 skill,然后用那份指导来写 prompt。
于是就有了一个不太直觉的后果:你不写 skill、不填 agent_skills,工具照样会被 registry 发现、照样能被调用,但契约里那条「先读 skill 再调用」在你这个工具上落到了空处。规模上能感受到这个项目的重心在哪儿:skills/ 下实读 156 个 .md,.agents/ 下 567 个,相加 723 个,与 README 自称的 “700+ agent skill and production-knowledge files” 对得上;全仓库 .md 共 1084 个。AGENT_GUIDE.md 里那句收尾金句写的就是这个意思:The intelligence is in the skills, not in improvised code.
必须补一句限定:这些都是写给模型看的约束文本,是指令,不是工程保障。契约写了「必须先读 skill」,不等于装好之后你用的那个 agent 一定会读;能不能落地取决于 agent 本身和它当时的上下文。
流水线三步:第二步有硬形式
加流水线的三步里,第一步在 pipeline_defs/ 建 YAML manifest。README 流程图里对 manifest 的描述是「里面有阶段、工具、评审标准和成功闸」。manifest 里还可以自标稳定度——documentary-montage.yaml 里就写了 stability: beta。
第二步「在 skills/pipelines/<your-pipeline>/ 建阶段导演 skill」看着自由,其实文件名有硬形式。Rule Zero 第 4 条写的路径是 skills/pipelines/<pipeline>/<stage>-director.md,并且要求 agent 对每一个阶段,在该阶段做任何工作之前先读它。也就是说,manifest 里每多一个阶段,这个目录下就该多一份对应的 <stage>-director.md;缺了哪个阶段的导演 skill,缺的就是那个阶段的执行说明。
第三步「引用既有工具,或按需新增」把两条清单接了起来:先看现有工具够不够,不够才回到上面那四步。同理,在建新流水线之前也值得先看既有的 12 个:skills/pipelines/ 下实读有 animation、avatar-spokesperson、character-animation、cinematic、clip-factory、documentary-montage、explainer、hybrid、localization-dub、podcast-repurpose、screen-demo、talking-head 十二个子目录;README 的架构图把这一层标注为 “Per-pipeline stage director skills”,即一条流水线对应一个目录。名字能对上你要做的东西,优先走既有那条。
七行清单没写、但你八成会踩的几条
AGENT_GUIDE.md 最后那节 What Not To Do 里,有几条直接约束「新加的东西该怎么写」:
- 不要硬编码 provider 名、API key 名或安装 URL,要从 registry 的
install_instructions和dependencies字段读。 - 不要孤立地呈现单个不可用工具,永远展示完整能力图景,原文给的说法是 “X of Y providers configured for this capability.”
- 不要在 preflight 时跳过 Provider Menu——用户必须看到他有什么,以及他还能解锁什么。
- 不要使用已被删除的旧名称,原文点名了三个:
tts_cloud、tts_engine、video_gen。你如果是照着某份旧教程或旧代码片段抄的,这三个名字是最容易带进来的历史包袱。 - 不要在没有事先告知用户的情况下更换 provider、模型或渲染路径,改动重大时还要拿到批准。
第一条和第二条其实是一件事的两面:把 provider 的可用性判断交给 registry,而不是写死在你的工具里,能力菜单才有可能是完整的。
你加的如果是付费工具,默认要审批
config.yaml 的 budget 段是这样的:mode: warn(三个模式是 observe | warn | cap)、total_usd: 10.00、reserve_pct: 0.10、single_action_approval_usd: 0.50、require_approval_for_new_paid_tool: true。最后这行与扩展直接相关:新的付费工具默认需要审批。仓库里也确实有 tools/cost_tracker.py 这个文件。
看清楚这里的默认值:预算模式默认是 warn 不是 cap,total_usd: 10.00 不等于一道硬性支出上限。三种模式各自怎么执行,请以仓库代码和官方文档为准。把这几行配好也不等于不会超支——我们没有运行过这套系统,不能给「这样配就安全了」的结论。README 里出现的那几个金额,是项目方在 README 中自行标注的成本,不是我们验证过的报价,也不能拿来推算你自己的开销。
渲染路径这一层,扩展前先读规则
如果你想加的东西落在合成/渲染这一段,先注意 README 在 Composition & Rendering 表后面紧跟的那条治理规则:运行时在提案阶段被选定(render_runtime),并通过 edit_decisions 锁定;在运行时之间静默切换是一次治理违规(governance violation)。原文把完整决策矩阵指向了 skills/core/hyperframes.md,那份文件我们没有读过,不描述其内容。这条规则和 AGENT_GUIDE.md 的章节标题 “Present Both Composition Runtimes (HARD RULE)” 是配套的——两套运行时必须都呈现给用户。
环境前提上还有一处可核实的不一致:README 的 Prerequisites 要求 Node.js 18+,而 Composition & Rendering 表里 Remotion 标的是 “Local (Node.js)“,HyperFrames 标的是 “Local (Node.js ≥ 22)“,只有 HyperFrames 写了具体版本下限。也就是说,按最低前置条件装好的环境,可能达不到 HyperFrames 那一栏标注的版本。我不据此断言它一定跑不起来——我们没有运行过;但你要动 HyperFrames 这一侧,这是开工前该先确认的一件事。顺带一提,HyperFrames 在仓库里没有对应目录,README 明说它是通过 npx hyperframes 消费的,不需要 checkout 整个 monorepo;lib/hyperframes_style_bridge.py 这个文件存在,内部我们没读。
加完之后怎么看它有没有被认出来
README 给的办法是不看文档看 registry,跑这两条命令:
python -c "from tools.tool_registry import registry; import json; registry.discover(); print(json.dumps(registry.support_envelope(), indent=2))"
python -c "from tools.tool_registry import registry; import json; registry.discover(); print(json.dumps(registry.provider_menu(), indent=2))"
AGENT_GUIDE.md 的 Mandatory Preflight 一节里给这两条命令配了注释:# Full menu — grouped available/unavailable per capability.(按能力分组的可用/不可用完整菜单)与 # Raw envelope — every tool's full contract. Slow/firehose; use for debugging only.(每个工具的完整契约;原文明确警告慢、输出量大,只用于调试)。
先跑 menu 那条看你的工具有没有出现在对应能力下面,需要看完整契约再跑 envelope 那条。以上命令照抄自仓库文档,我们没有运行过,实际输出以你本地跑出来的为准。
回头看这七行
真正的信息量在于它们的不对称:加工具的四步里,前三步是形式要求(放对目录、继承对基类、不用注册),只有第四步涉及 agent 到底会不会用好它;加流水线的三步里,唯一没法靠代码兜底的也是第二步那份 <stage>-director.md。这个项目把智能放在 Markdown 里,扩展它的代价也就跟着落在 Markdown 上——你缺的通常不是 Python。
最后指两处路:docs/ARCHITECTURE.md 是 README 给的完整技术参考,AGENT_GUIDE.md 是 agent 契约本身,动手前值得先读;如果你打算把写好的东西贡献回去或对外分发,许可条款以官方 LICENSE 原文为准。
本文依据 OpenMontage 官方仓库(github.com/calesthio/OpenMontage)的 README、
AGENT_GUIDE.md、config.yaml、pipeline_defs/ 与 lib/ 下的治理模块整理,核对日 2026-08-09。
本文内容为仓库源码与文档口径,我们没有安装或运行过该系统,也没有调用过其中任何一个 provider API,
文中出现的成本数字均为项目方在 README 中自行标注的金额,非我们的实测结果。
该项目以 AGPL-3.0 发布,部分流水线在 manifest 中自标 stability: beta,请以仓库最新内容为准。
许可条款请以官方 LICENSE 原文为准,本文不构成法律意见。
安全相关做法请结合自身环境评估,本文不构成安全方案建议。