跳转到内容

Agent 工作流的 Preview & Trajectory 渐进式披露

学习目标

  • 理解 Preview & Trajectory 模式在 Agent 长工作流中的价值
  • 掌握三层持久化模型(Bundle / Session / Trajectory)的设计
  • 应用 Producer/Consumer 角色分离原则
  • 设计 Agent-Cheap 的 preview live status --json 接口

前置知识

本章涉及 Agent 工作流渐进式披露的通用模式,建议先阅读:

下文假设你已理解上述概念,直接聚焦 CLI-Anything 的具体实现。


项目实践

为什么需要 Preview

Agent 操作 Blender 建模、FreeCAD 设计零件、Kdenlive 剪辑视频——这些是可能耗时数十分钟的长工作流。如果 Agent 完成所有步骤后才发现第一步就错了,代价巨大。

CLI-Anything 的 Preview 机制解决了这个问题:

preview_bundle.py 共享协议

preview_bundle.py(~500 行)是跨所有 Harness 的共享 Preview 协议实现(preview-bundle/v1):

Bundle 目录结构:

bundle_003/
├── manifest.json # 元数据:时间戳、命令、源指纹
├── render.png # 渲染产物
├── summary.json # 摘要:命令、关键属性
└── artifacts/ # 额外产物

三层持久化实现

对象可变性用途
bundle_dir不可变每次 capture 的快照,一旦发布不再修改
session.json可变Live Preview 的当前头,指向最新 Bundle
trajectory.json追加式命令 → Preview 的完整历史,可回放

关键设计_bundle_dir 不是永久的构建身份——它是单点快照路径,会随源指纹变化而改变。稳定的回放身份锚定在 session_dir + trajectory.json

Producer/Consumer 角色分离

CLI-Anything 严格分离了两个角色:

角色命令能力
Producercli-anything-<software> preview capture与后端对话、渲染、发布 Bundle
Consumercli-hub previews inspect/watch/open读取已发布的 Bundle、展示给人类

Consumer 不渲染、不回放、不合成预览制品——它只读取 Producer 已发布的状态。这个分离防止了消费者误以为自己在渲染。

Live Preview 语义

FreeCAD 和 Blender 的 Harness 展示了完整的 Live Preview 实现:

Terminal window
# 启动 Live 会话
cli-anything-freecad preview live start --name rover-design
# 每次操作后推送 Preview
cli-anything-freecad chassis build --wheels 6
cli-anything-freecad preview live push --reason "chassis built"
# 轻量状态探测(Agent 高频调用)
cli-anything-freecad preview live status --json

preview live status --json 返回紧凑摘要(trajectory_summary),让 Agent 无需读取整个 trajectory.json

{
"active": true,
"session_dir": "/path/to/session_001",
"trajectory_summary": {
"total_commands": 42,
"latest": {
"command": "chassis build",
"bundle": "bundle_007",
"timestamp": "2026-05-31T10:45:00Z"
}
}
}

真实性原则

HARNESS.md 强调:

Truthful previews matter more than pretty previews. Agents need intermediate state they can trust when deciding what to do next.

CLI-Anything 的 Preview 实现遵守:

  • 使用真实后端渲染(Blender render、FreeCAD export)
  • 禁止 Python 伪造渲染
  • 禁止屏幕抓取 GUI 窗口
  • 如果注入临时相机/灯光辅助渲染,在 Bundle 状态中标注

实战案例

FreeCAD Curiosity Rover 演示(README 中的演示 GIF):

  • Agent 逐步组装火星车模型
  • 每个步骤发布 Preview Bundle(Blender 渲染的 PNG)
  • preview live 追踪当前设计状态
  • trajectory.json 记录完整的设计历史
  • 最终产出可通过轨迹完整回放

问题与规避

问题规避策略
Agent 频繁读取 trajectory.json 浪费 Tokenpreview live status --json 返回紧凑 trajectory_summary
_bundle_dir 被当作永久身份稳定回放锚定 session_dir + trajectory.json
Consumer 被误用为渲染路径文档和 HARNESS.md 严格分离角色
Preview 伪造导致 Agent 误判坚持真实性原则,所有 Preview 来自真实后端
源指纹变化后旧 Preview 仍被引用源指纹变化时强制重新 capture

设计取舍

Preview 为可选而非必须

选择:Preview 支持是可选的,Harness 可以不实现。

原因:不是所有软件都有”可视化中间状态”。例如 Zoom CLI(API 调用)或 Eth2 QuickStart(节点管理)没有视觉产出。

何时应实现:当软件产生”有意义的可预览中间状态”时(3D 模型、视频帧、图像、设计图)。

poll-first vs push-first

Live Preview 支持两种刷新模式:

  • push-first:每次 mutation 后主动 push(默认,准确但可能有延迟)
  • poll-first:后台轮询检测变化(适用于无法精确 hook 的场景)

CLI-Anything 默认 push-first,因为 Harness 控制 mutation 流程,可以精确知道何时需要 capture。

参考来源

  • 源码验证:preview_bundle.py(~500 行)
  • 源码验证:HARNESS.md Preview & Live Preview Norms 章节
  • 源码验证:guides/preview-methodology.md 设计指南
  • 源码验证:FreeCAD/Blender Harness 中的 preview 命令实现