OpenMontage Checkpoint 协议:为智能体视频生产管线构建可恢复、可审计、受人类管控的存档机制
【免费下载链接】OpenMontageWorld's first open-source, agentic video production system. 12 production pipelines, 100+ tools, 700+ agent skill and production-knowledge files. Turn your AI coding assistant into a full video production studio.项目地址: https://gitcode.com/GitHub_Trending/op/OpenMontage
导读
本指南系统讲解 OpenMontage 的元技能文档 skills/meta/checkpoint-protocol.md 所定义的 Checkpoint Protocol——一套以指令驱动取代旧有checkpoint_policy.py的检查点协议。它规定智能体何时、以何种状态、携带哪些工件(artifacts)为每个生产阶段写入检查点,如何向人类请求审批,以及在失败后如何精确恢复。读完本文,你将掌握检查点 JSON 的完整字段结构、write_checkpoint/init_project/get_next_stage等核心 API 的用法、in_progress阶段内心跳与partial_progress局部进度的落地方式,以及底层 lib/checkpoint.py 中门禁(gate)强制、前置阶段校验、历史归档与原子写入的实现原理。
什么是 Checkpoint:管线中的"存档点"
在 OpenMontage 的 12 条生产管线(如 cinematic、explainer 等)中,每个阶段(research、proposal、idea、script、scene_plan、assets、edit、compose、publish)完成后都会落盘一份检查点。Checkpoint 是管线运行的存档点(save point),它带来三重核心价值:
- 从失败处恢复(resume-from-failure):
compose阶段崩溃后,重启任务可以直接从compose继续,而不是从头跑到idea; - 人类监督(human oversight):创造性的关键阶段可以强制在人类审批通过后才能推进,避免无人把关的自动生成;
- 审计轨迹(audit trail):每个阶段的版本更迭与门禁转换都会被归档到
history/,整条管线可回放、可复核。
从源码看,检查点的标准目录位置被硬编码在 lib/checkpoint.py 的_checkpoint_path()中:
projects/<project_id>/checkpoint_<stage>.json而projects/目录本身由 lib/paths.py 中的PROJECTS_DIR常量定义,是 Backlot 看板监听的唯一事实来源。写检查点时必须传入仓库的projects/目录作为pipeline_dir(或直接使用lib.checkpoint.PROJECTS_DIR),并且永远要传pipeline_type——因为门禁强制逻辑需要借助它读取对应的管线清单(manifest)。
协议七步走:从清单策略到恢复续跑
Step 1:读取清单策略——checkpoint_required与human_approval_default
进入每个阶段前,先从管线清单(manifest)读取该阶段的检查点配置。清单的 JSON Schema 定义在 schemas/pipelines/pipeline_manifest.schema.json,其中stages[].checkpoint_required默认true,stages[].human_approval_default默认false。典型的 YAML 配置片段如下:
- name: idea checkpoint_required: true # 是否必须写检查点 human_approval_default: true # 是否必须征求人类审批两者的组合决定了动作,原文档给出的决策表如下:
checkpoint_required | human_approval_default | 动作 |
|---|---|---|
| true | true | 写检查点 + 提交人类审批 |
| true | false | 写检查点 + 自动继续 |
| false | * | 完全跳过检查点(罕见) |
在真实清单 pipeline_defs/cinematic.yaml 中可以看到各阶段的实际配置:research(checkpoint_required: true, human_approval_default: false)、proposal/script/scene_plan/assets/publish(均为human_approval_default: true)、edit/compose(human_approval_default: false)。也就是说,一条电影级管线的门禁落在创意与交付两端,而中间的编辑、合成环节允许自动推进。
值得注意的源码细节:human_approval_default是门禁的唯一事实来源。查询逻辑集中在 lib/pipeline_loader.py 的get_stage_human_approval_default(),而 lib/checkpoint.py 的_stage_requires_approval()通过load_pipeline_readonly()读取清单——如果传了一个拼写错误或不存在的pipeline_type,会直接抛出CheckpointValidationError(fail-closed),而不是静默跳过门禁;反之,若清单文件损坏无法解析,则记录警告并回退到调用方传入的human_approval_required标志(fail-open 有下限,但退化必须可见)。
Step 2:准备检查点数据
一次检查点需要聚合四类数据:
- Stage name——刚完成的阶段名;
- Status——
"completed",或需要审批时的"awaiting_human"; - Artifacts——该阶段的规范工件(canonical artifact);
- Metadata——评审结论、成本快照(cost snapshot)、时间信息。
各阶段的规范工件映射定义在 lib/checkpoint.py 的CANONICAL_STAGE_ARTIFACTS:research → research_brief、proposal → proposal_packet、idea → brief、script → script、scene_plan → scene_plan、assets → asset_manifest、edit → edit_decisions、compose → render_report、publish → publish_log。另有三个补充工件source_media_review、final_review、video_analysis_brief(参考视频锚定物)可能伴随产生。此外,清单还允许声明九大规范阶段之外的阶段(如 character-animation 的character_design/rig_plan),这类阶段没有规范工件,校验时按"无必需工件"处理,不会崩溃——这一点由 tests/lib/test_checkpoint_noncanonical_stage.py 专门覆盖。
Step 3:写入检查点——write_checkpoint与init_project
原文档给出的调用方式:
write_checkpoint( pipeline_dir, # 项目工作目录(projects/) project_name, # 项目标识符 stage_name, # 例如 "idea" status, # "completed" 或 "awaiting_human" artifacts, # {"brief": {...}} —— 该阶段的输出 )对照 lib/checkpoint.py 的完整签名,write_checkpoint还支持一系列关键字参数,这里给出带注释的完整版:
write_checkpoint( pipeline_dir, # projects/ 目录(必须) project_id, # 项目标识符(必须) stage, # 阶段名,如 "assets"(必须) status, # "completed" / "awaiting_human" / "in_progress" / "failed" artifacts, # {工件名: 工件数据} 字典(必须) pipeline_type="cinematic", # 管线名,门禁强制与阶段顺序依赖它(必须传) style_playbook="flat-motion-graphics", # 视觉身份,加载失败即 fail-closed checkpoint_policy="guided", # guided / manual_all / auto_noncreative human_approval_required=False, # 调用方更严格的额外门禁(只能更严,不能更松) human_approved=False, # 人类已批准的证据 review=None, # 评审结论 {"critical": [...], "suggestions": [...]} cost_snapshot=None, # {"total_spent_usd": ..., "budget_remaining_usd": ...} error=None, # 失败阶段的错误信息 metadata=None, # 任意元数据,如 partial_progress )写入过程会依次完成以下动作:
- 校验工件 schema:每个工件先经过 schemas/checkpoints/checkpoint.schema.json 的 JSON Schema 校验(
version固定"1.0"、status只能是completed/failed/awaiting_human/in_progress四选一),再逐工件调用validate_artifact()做工件级校验(见_validate_artifacts_for_stage)。completed/awaiting_human状态必须携带该阶段的规范工件,否则抛CheckpointValidationError; - 强制审批门禁(GATE VIOLATION):如果清单声明
human_approval_default: true(或调用方显式传human_approval_required=True),那么以status="completed"写入而不带human_approved=True就是硬错误,会抛出GATE VIOLATION异常并给出正确写法的提示(见 lib/checkpoint.py)。门禁只在写入时强制——历史遗留的、手工写的旧检查点仍可被读取为 completed,这是刻意的向后兼容,保证进行中的项目可以恢复; - 强制前置阶段(PREREQUISITE VIOLATION):
awaiting_human/completed属于生命周期推进,写入前_enforce_stage_prerequisites()会按清单阶段顺序检查所有前驱阶段:前驱检查点缺失、状态不是completed、或属于需审批阶段却没有human_approved=True,都会抛出PREREQUISITE VIOLATION,并列出是"incomplete or missing"还是"completed without required approval"(lib/checkpoint.py)。而in_progress心跳不受此限制,可随时写入; - 归档被取代的检查点:写入新版本前,若磁盘上已有同阶段检查点且状态不是
in_progress,会先复制到projects/<id>/history/checkpoint_<stage>_<时间戳>.json(lib/checkpoint.py)。阶段版本与门禁转换永不销毁;但反复的in_progress刷新属于心跳而非版本,不归档。归档采用 copy 而非 move,且吞掉 I/O 异常——因为 Backlot 监听器可能正打开着该文件,且归档失败绝不能导致写入崩溃; - 合并决策日志:若工件中携带
decision_log,会被追加合并到项目级projects/<id>/decision_log.json,并把引用写入proposal_packet与render_report工件(_merge_decision_log); - 原子落盘:先序列化到临时文件
checkpoint_<stage>.json.tmp,再用os.replace()原子替换正式文件——磁盘写满或元数据不可序列化时,绝不留下截断的"当前检查点"; - 附带时间戳与阶段元数据:
timestamp使用 UTC ISO-8601 时间戳。
管线初始化:在任何阶段开始前,先调用init_project():
from lib.checkpoint import init_project init_project("my-project", title="My Project", pipeline_type="cinematic")init_project()(lib/checkpoint.py)会创建标准目录布局(artifacts/、assets/images|video|audio|music/、renders/),并写入project.json标记文件——这是 Backlot 看板在首个检查点产生之前就能渲染项目身份与阶段轨道的依据。该函数是幂等的:重复调用保留原始created_at并合并字段。若传入了无法加载的style_playbook,会在创建任何目录之前就失败(fail-closed)。随后可启动看板:
python -m backlot open my-project看板不可用时不阻塞流程——它是观察者,永远不是阻塞者。
Step 4:阶段内检查点——in_progress心跳与partial_progress局部进度
进入任何阶段,先写一个in_progress检查点。这是 Backlot 看板判断"该阶段正在活跃运行而非卡死"的依据——确定性(certainty)比速度更重要。
长时运行阶段(如assets、compose循环)可能因 API 错误、速率限制或会话中断而中途失败。为了能从失败点(例如 Scene 4)精确续跑:
- 写局部进度:每成功产出一个重要条目(如一个场景的素材、一个 clip),就写一次
in_progress检查点。in_progress可以省略规范工件,但存放在已知工件名下的数据仍会被 schema 校验;如果局部数据还构不成合法规范工件,就放进metadata.partial_progress而不是artifacts:
write_checkpoint( pipeline_dir, project_name, stage="assets", status="in_progress", artifacts={}, # 尚未有完整的规范工件 metadata={ "partial_progress": { "asset_manifest_draft": partial_manifest_dict, "completed_scene_ids": completed_scene_ids, } }, )如果局部工件已经满足其 schema(例如asset_manifest带version: "1.0"和合法的assets[]条目),也可以直接放进artifacts。
- 从局部进度恢复:启动一个阶段时,永远先检查该阶段是否已存在
in_progress检查点(处理方式见 Step 7 恢复协议)。
Step 5:人类审批——门禁是强制的,"present and continue" 就是违规
清单中的human_approval_default具有约束力,是本协议绝不覆盖的唯一事实来源。没有"这次情况特殊"的例外——lib/checkpoint.py 在写入层强制这一点:门禁阶段以status="completed"写入且不带human_approved=True时抛GATE VIOLATION错误。
当human_approval_default: true时,流程为:
- 以
status="awaiting_human"写入检查点(而非completed); - 向人类提交摘要,原文档给出的模板:
## Stage Complete: [stage_name] — awaiting your approval ### Artifact Summary [工件关键细节 — 标题、时长、关键决策] [如果 Backlot 看板在运行,指向它:工件在那里渲染] ### Review Findings [评审结论摘要:N 个关键问题(全部修复)、N 条建议] ### Cost So Far [已花费预算 / 总预算,按工具拆分] ### Action Required 请审阅并批准继续,或提供修改意见。- 结束本轮(END YOUR TURN):在同一次响应中继续任何管线工作都是门禁违规。"展示并继续"不是等待——本轮必须以提问结束,下一次管线动作必须由用户的回复触发;
- 根据用户回复分支:
- 批准→ 以
status="completed", human_approved=True重写检查点,再进入下一阶段; - 要求修改→ 带着反馈回到阶段导演技能(stage director skill),产出修订版工件、重新评审、重新写检查点(被取代的检查点自动保留在
history/); - 中止→ 停止管线;
- 批准→ 以
- 审批按门逐一生效(approval is per-gate):此前任何宽泛的批准(哪怕是"很棒,整个都做下去")都不覆盖后续门禁。若用户明确预授权全程运行,必须在其表态的当下记录一条
decision_log条目(category: "approval_policy")——没有这条记录,就每个门禁都停下; - assets 门禁审查的是故事板,不是成片:
assets在所有管线中都设门禁——按场景逐个呈现生成的素材(Backlot 看板的胶片条是天然的审查界面),并包含已花费金额与预计合成成本。在素材阶段渲染草稿/完整合成来"换取"这次评审是错误做法——审查界面是填充了逐场景素材(库存素材、生成静帧、旁白波形)的胶片条,而不是渲染出的视频。对于"素材"是定制/atelier 合成(没有可缩略文件)的场景,智能体需要为每个场景写一张审查静帧到projects/<id>/snapshots/<scene_id>.png(用remotion still在代表性帧处生成,参见 skills/meta/bespoke-composition.md),看板会在胶片条上展示它们。随静帧落地刷新metadata.partial_progress,然后停在门禁处。草稿/成片渲染属于compose阶段——只有在 assets 门禁通过后才运行。在 assets 阶段渲染完整草稿,就是跳过用户本应把守的门禁。
Step 6:确定下一阶段——get_next_stage
检查点写好且(如需)获批后,查询下一阶段:
next_stage = get_next_stage(pipeline_dir, project_name)get_next_stage()(lib/checkpoint.py)读取全部已存在检查点,返回清单阶段顺序中第一个没有 completed 检查点的阶段;管线全部完成则返回None。它依赖get_pipeline_stages(pipeline_type)按pipeline_type从清单解析阶段顺序——不同管线(cinematic 与 explainer)的阶段序列不同,因而能正确推进。未传pipeline_type时回退到九个规范阶段的稳定顺序(lib/checkpoint.py 的get_pipeline_stages)。
Step 7:恢复协议——管线启动第一件事是检查已有进度
任何管线运行开始时(不只阶段间),先检查已有进度:
next_stage = get_next_stage(pipeline_dir, project_name)若next_stage不是第一个阶段:
- 告知人类:"发现已有进度。从阶段恢复:[next_stage]";
- 检查局部进度:读取
next_stage的检查点:
current_cp = read_checkpoint(pipeline_dir, project_name, next_stage)若current_cp存在且状态为"in_progress",告知人类你正从阶段中途恢复; 3.加载工件:加载先前检查点中的工件作为上下文。若从"in_progress"恢复,优先加载current_cp["artifacts"]中 schema 合法的局部工件;若局部数据在current_cp["metadata"]["partial_progress"]中,则使用该草稿数据及其完成标记(如completed_scene_ids)跳过已完成的子任务; 4.继续:从下一个未完成步骤继续生成,追加到局部工件。
若检查点状态为"awaiting_human":
- 告知人类:"阶段 [name] 正在等待您的审批";
- 呈现检查点数据供审查;
- 等待批准后再继续。
read_checkpoint()(lib/checkpoint.py)在返回前同样会做完整 schema 校验,损坏的检查点不会被静默当作有效进度。
参考驱动生产的 Sample 子检查点
当生产是参考驱动的(存在 VideoAnalysisBrief)时,提案审批与全面生产之间还有一个额外检查点。它在管线清单中以sub_stages形式声明(见 pipeline_manifest.schema.json 与 cinematic.yaml 的proposal.sample),原文档的配置表如下:
| 阶段 | checkpoint_required | human_approval_default | 备注 |
|---|---|---|---|
sample | true | true | 始终要求人类审批 |
sample 检查点的流程:
- 呈现:渲染出的 10–15 秒示例片段;
- 成本:示例成本 vs. 预估全片成本;
- 动作:批准(→ 进入 script)、修改(→ 重新生成示例)、中止。
需要强调:sample 检查点不是一个管线阶段——它是 proposal 阶段内的子检查点,不产生规范工件,只产出一个渲染预览片段,存放于projects/<name>/assets/sample/sample_v{N}.mp4。呈现格式:
## Sample Preview Ready **Sample clip:** [sample_v1.mp4 路径] - Duration: [X] 秒(钩子 + 1 个中段场景) - Voice: [TTS 提供商 + 音色名] - Visuals: [描述 — AI 图片、Remotion 动画等] - Music: [来源] **Sample cost:** $[X.XX] **Projected full video cost:** $[X.XX] 这个方向感觉对吗?我可以调整:音色、视觉风格、节奏、音乐、配色。关键原则:Checkpoint 协议的五大纪律
- 永远为已完成的工作写检查点。即使
checkpoint_required: false,如果该阶段投入了大量时间或成本,也应考虑写入——丢失工作比磁盘上多一个文件更糟; - 创意阶段绝不跳过人工审批。
idea和script决定一切,为省时间而草率越过它们,只会产出没人想要的视频; - 包含成本快照。在批准昂贵的下游阶段(assets、compose)之前,人类应该知道已花费多少、还剩多少预算;
- 检查点是恢复的前提。如果管线在
compose崩溃,人类重启后应从compose继续,而不是从idea——这正是本协议的初衷; - 审批请求要透明。不要只展示工件——要同时展示评审结论、成本与任何顾虑,帮助人类做出知情决策。
源码与测试佐证:协议如何被机器强制执行
本协议并非仅靠提示词约束,而是有代码与测试双重背书:
- 门禁强制:
GATE VIOLATION与PREREQUISITE VIOLATION的抛出逻辑在 lib/checkpoint.py,门禁阶段的completed写入必须有human_approved=True; - 清单解析:
human_approval_default的唯一查询入口get_stage_human_approval_default()位于 lib/pipeline_loader.py,注释明确要求 Backlot 看板与门禁强制读取同一字段; - Schema 约束:检查点的字段结构、状态枚举(
completed/failed/awaiting_human/in_progress)、checkpoint_policy枚举(guided/manual_all/auto_noncreative)、成本快照字段定义在 schemas/checkpoints/checkpoint.schema.json,且additionalProperties: false,杜绝随意扩展字段; - 前置校验测试:tests/lib/test_checkpoint_prerequisites.py 覆盖了"后置阶段不能跳过缺失的前驱"、"未获批准的门禁前驱会被拒绝"、"畸形前驱无法伪造完成"、"
in_progress心跳不受前置限制"、"未知 style_playbook 在创建项目前即失败"五类场景; - 非规范阶段测试:tests/lib/test_checkpoint_noncanonical_stage.py 验证清单声明的非规范阶段不会抛
KeyError,同时规范阶段仍强制携带其工件; - 看板呈现:检查点状态(
in_progress/awaiting_human/completed)会实时渲染在 Backlot 看板的阶段轨道上,供人类在等待审批或查看局部进度时直接观测。
总结
OpenMontage 的 Checkpoint Protocol 用一套简单而强制的状态机(in_progress → awaiting_human → completed)把"存档点、人工门禁、审计轨迹、精确恢复"四件事统一到了projects/<id>/checkpoint_<stage>.json这一处事实来源上。无论是智能体运行时的自我约束,还是 lib/checkpoint.py 的写入时强制,抑或 Backlot 看板的可视化呈现,最终都服务于同一个目标:让一次可能持续数十分钟、跨越多个昂贵生成步骤的视频生产,在任何时刻中断后都能从最精确的位置续跑,并确保每一个关键创意决策都有人类的知情批准。
【免费下载链接】OpenMontageWorld's first open-source, agentic video production system. 12 production pipelines, 100+ tools, 700+ agent skill and production-knowledge files. Turn your AI coding assistant into a full video production studio.项目地址: https://gitcode.com/GitHub_Trending/op/OpenMontage
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考