一次 Video Agent 迭代如何长成 Harness 方法
前段时间我在优化一个特定视频风格的 video agent。
任务不是“让它能生成视频”这么宽泛,而是让它稳定产出某一类风格:参考品牌的 Instagram / Reel 视觉语言,替换成另一个品牌或产品,同时保留构图、灯光、色调、运镜节奏,不把参考品牌的 logo、包装、文字带进最终画面。
这个任务很容易让人误判。
单看某一次输出,可能只是“还不错”或“不像”。但迭代几轮之后,问题会变得很难描述:有些版本更稳了,但风格变平了;有些版本更像参考视频,但产品识别变差了;有些修复看起来合理,下一轮却把原本好的 case 改坏。
我最开始没有想做一套方法论。
我只是想把每轮迭代效果记录下来,方便在开发 meeting 里对齐生成效果:这一轮到底改了什么,哪些 case 好了,哪些 case 退了,下一轮应该继续修哪里。
后来才发现,真正要优化的不是某一个 prompt,也不只是某段代码,而是整套 agent 迭代的反馈系统。
过程记录:从“对齐效果”开始
第一步很朴素:让 coding agent 每次跑完测试后,把结果同步到飞书文档里。
这些文档最初不是论文式记录,也不是写给外部读者看的报告。它更像一次开发协作里的效果看板。
一类文档负责横向对比:同一批 case,在不同版本、不同策略、不同生成链路下分别产出了什么结果。重点不是表格长什么样,而是所有人可以在 meeting 里指着同一行说:这个 case 是变好了,还是退化了。
另一类文档负责纵向展开:一个 case 从用户输入开始,经过素材抓取、风格分析、产品分析、素材编排、prompt 生成、工具调用,再到输出结果。它把 agent 的中间产物摊开,让问题不再只落在最终成片上。
这两类记录解决的是同一个问题:不要让 agent 只凭对话记忆理解上一轮发生了什么。
video agent 的一次失败,往往不是“成片不好看”这么简单。它可能是素材阶段拿错了参考,也可能是产品识别阶段没有拿到真实 SKU,也可能是 prompt 阶段把“参考构图”写成了“复刻参考产品”。
如果没有 trace,coding agent 很容易只改 render 那一层。
共享上下文:飞书文档变成外部记忆
跑了几轮之后,飞书文档的角色变了。
它不只是效果看板,而是 coding agent、sub agent 和我共同工作的界面。
coding agent 把测试结果写进去;sub agent 在文档里做独立 review;我会在旁边补充人工判断,比如“这个版本看起来更像参考风格,但产品主体变弱了”“这不是 bad case,是这个风格本来就应该保留的粗糙感”“这个修复方向不对,会把整体带向模板化广告片”。
这时飞书文档承担了三个角色。
Shared Context:所有参与者都围绕同一批 case、同一轮输出、同一组评论工作。
External Memory:跨轮次保存判断,不依赖一次对话窗口。
Review Surface:评论直接挂在具体段落、表格或结果上,不停留在泛泛的“效果不好”。
这一步让我对 harness 有了更具体的理解。
harness 不只是运行测试的脚本。对 agent 工作流来说,它还包括 agent 能读取的历史、能复用的案例、能被审阅的输出,以及能把审阅结果带回下一轮修改的通道。
独立评审:sub agent 更客观,但不是客观真理
后面我加入了 sub agent review。
它的价值在于独立上下文。
coding agent 刚改完 workflow,往往会顺着自己的补丁解释结果。比如它刚加了更强的 product constraint,就容易把“产品更清楚”看成进步;但我真正关心的可能是,产品清楚之后,原来那种参考品牌的随手感没了。
sub agent 从另一个上下文进入,只看到测试文档、输出结果和评审要求。它没有参与刚才那轮修改,所以更容易指出 coding agent 没意识到的副作用。
但这里不能神化 sub agent。
sub agent 仍然是主观评审。它可能偏向更清晰、更完整、更商业化的输出;也可能把某个风格里本来应该保留的噪声判断成缺陷。所以它不是最终裁判,而是一个上下文隔离的 AI reviewer。
这也是后面为什么需要人工校准,甚至需要迭代 sub agent 自己的评审 prompt。
三层 Review:固定脚本、AI、人工
做到这里时,我想起之前读过的 harness engineering 相关文章。
当时触发我的不是某个具体术语,而是一个判断:可靠的 agent review 不能只有一种信号。
我记得类似的观点是,harness 里的 review 至少需要三类东西一起工作:固定脚本、AI review、人工 review。
这和我正在做的事情刚好对上。
固定脚本负责没必要争论的硬规则。比如有没有生成文件,视频链接是否可访问,时长是否在目标范围内,输出里是否出现明显禁止的字幕、水印、品牌文字。
AI review负责高吞吐的语义判断。比如风格是否接近参考,产品是否被错误替换,镜头节奏是否明显偏离,某个版本相比上一版有什么退化。
人工 review负责方向和取舍。比如某个“粗糙”到底是失败,还是这个风格本来就需要的质感;某个规则要不要进入下一轮,还是只作为这次 case 的观察。
这时我意识到,我不是在让 coding agent“多改几轮”。
我是在给它搭一个小型 harness:运行 case、保存 trace、发起 review、读取评论、改代码,再回到下一轮 case。
Judge Calibration:AI 评审也要被迭代
sub agent 的判断有用,但不能默认可靠。
在视频风格任务里,AI reviewer 很容易稳定地偏向某些方向:更清晰、更完整、更像广告、更少噪声。这些偏好在普通质量评估里可能是优点,但在某些风格拟合任务里反而会把系统带偏。
所以我开始把 sub agent 也当成需要迭代的组件。
人工评论不只是补充漏判,而是在校准 judge 的方向:
- 它把哪些风格特征误判成缺陷?
- 它在哪些维度上判断比较稳定?
- 它是不是过度奖励清晰度、产品占比或商业感?
- 它的评审 prompt 是否需要加入“保留低保真质感”之类的约束?
这就是 Judge Calibration。
它不一定一开始就有 precision、recall、agreement 这些完整指标,但思路已经在那里:AI reviewer 的输出也要被抽检、降权、修正,而不是直接进入 coding agent 的修改依据。
边界知识:从评论走向条件
第一版循环的问题很快出现。
飞书评论对人有用,但对 coding agent 仍然太松。
比如我写“这个更像广告片了”,人能理解这背后可能包含过度打光、产品摆拍感太强、镜头太稳定、后期太干净。但 coding agent 可能只抓住其中一个点,把它改成“降低产品清晰度”。
这就是自然语言评论到代码修改之间的 grounding gap。
所以我开始沿着已有 harness 的实践,按照“积累边界”的逻辑整理问题。
边界不是一句“这个不好”,而是带条件的判断:
- 当目标是保留 Instagram 随手感时,过度干净的 studio lighting 会把输出推向广告棚拍。
- 当参考素材里出现的是源品牌产品时,只能提取构图、光线、颗粒和色彩,不能让目标 prompt 复刻源产品形状。
- 当产品图分析没有拿到足够真实 SKU 时,继续 render 可能会生成虚构产品,这时宁可 fail fast。
- 当为了强化产品识别而把主体放得过大时,style transfer 会退化成 product hero packshot。
这对应到后面整理出来的方法论,就是 Boundary Knowledge。
它的作用是把 bad case 从“某次输出很差”升级成“某类条件下会失败”。coding agent 读到的不再是情绪化评论,而是更接近规则的修改依据。
结构化边界:减少 Agent 之间的语义损耗
只积累自然语言边界,还是会有损耗。
同一句“产品被硬塞进场景”,可能指产品占比过大,也可能指光照不匹配,也可能指产品和人物动作没有关系。人能靠上下文补齐,coding agent 不一定每次都补对。
所以边界需要逐步结构化。
一个更稳的 boundary 至少应该包含:
- category:问题属于风格、产品识别、素材选择、prompt 约束、运镜节奏,还是安全规则。
- condition:问题在什么条件下出现。
- failure:它伤害了什么目标。
- evidence:关联哪些 case。
- severity:它是必须修,还是观察项。
- confidence:这个判断来自人工、sub agent,还是二者一致。
这不是为了把写作变成表格。
它是为了让 coding agent 少猜一点。尤其当 agent 之间靠文档传递信息时,结构化字段能减少“我以为你说的是另一个问题”的概率。
双信号:只积累 boundaries 效果一般
最开始我顺着 harness 的思路,主要在积累 boundaries。
这个方向是对的,但效果一般。
原因也很简单:只有 bad case,系统只知道哪里不能去,却不知道哪里值得保留。
每个 bad case 都在告诉 agent 不要做某件事:不要让产品太小,不要让 logo 泄漏,不要让画面太乱,不要让镜头太跳。规则越加越多,输出就越像安全模板。
但视频风格不是只要“不坏”就够。
有些东西恰恰是风险带来的:手持感、偶然构图、轻微过曝、素材里不那么商业的生活气、镜头切换里的不规整节奏。
所以我开始想把反馈做成双向的、系统化的。
一边是 boundaries,记录“什么条件下会坏”。
另一边是 exemplars,记录“哪些东西要保留”。
比如某个版本虽然产品没有最大化展示,但它保住了参考品牌的画面语气;某个 case 虽然有一点噪声,但整体最像真实 Instagram post;某个 prompt 结构虽然不够干净,但它减少了 AI 默认的棚拍感。
这就是 Good Case 回放。
good case 的作用不是证明系统很棒,而是给 coding agent 一个正面参照:下一轮修问题时,不要把这些东西一起修掉。
Golden Set:防止修一个坏一个
双信号再往前走,就会自然走到 Golden Set。
如果某些 good case 已经被人工确认过,下一轮修改就不应该破坏它们。否则 agent 会对最新评论过拟合。
我刚评论完“产品主体太弱”,它下一轮就可能把所有 case 的产品都推到画面中心;我刚评论完“参考风格不够强”,它又可能让源品牌元素卷土重来。
Golden Set 的作用是让 coding agent 先证明:这轮修复没有把已经成立的行为打坏。
它不一定一开始就有完整自动化。
最小版本可以很土:固定拿一批人工确认过的 case 回放,对比关键维度有没有下降。等 workflow 稳定后,再把它升级成 Regression Gate:通过率下降超过阈值,本轮修改就不能直接放行。
这就是我后来方法论文档里写的 Golden Set + Regression Gate。
Active Probing:从随机撞问题到主动找边界
早期测试更多是随机 case 或自然 case。
这种方式能发现问题,但效率不高。很多失败要撞运气才会出现。
比如一个边界可能不是“短转场一定坏”,而是“慢节奏叙事里短转场坏,快节奏音乐里短转场可以接受”。如果只靠随机 case,可能很久都看不清这个边界。
所以后续方法论里,我把它扩展成 Active Boundary Probing。
Probe Agent 的任务不是普通生成 case,而是围绕已有 boundary 构造边界附近的测试:
- 在已知 bad case 的参数附近微调,找真正的临界点。
- 把两个边界条件交叉组合,看是否出现新失败。
- 专门生成 judge 低置信度的 case,逼出未知区域。
这部分不是我最初完整实践过的模块,而是从“随机 case 效率低”这个问题继续推出来的下一步。
Convergence:不要让循环变成无限修补
还有一个后续才变清楚的问题:什么时候该停?
agent 迭代很容易变成无限修补。每一轮都能找到一点问题,每一轮也都能改一点。但继续改不代表继续变好。
所以方法论里需要一组收敛信号。
这些信号可以很简单:
- Golden Set 是否稳定。
- 新 bad case 的数量是否下降。
- 新增 boundary 是否还在快速增长。
- 每轮 fix 后,原 bad case 变好的比例是否足够高。
- sub agent 和人工判断的一致性是否稳定。
我不想把这部分写成“当时已经搭了完整 dashboard”。
更准确的说法是:实践先暴露了“靠感觉停不下来”的问题,后来方法论才把它扩展成 Convergence Metrics。
方法演化:从一套实践到一组工程模块
这套方法不是一开始设计出来的。
它是这样长出来的:
- 我先记录每轮 video agent 生成结果,用来在开发 meeting 里对齐效果。
- 记录文档变成 shared context,开始承担外部记忆和审阅界面的角色。
- 我加入 sub agent,让它在独立上下文里做 AI review。
- 我发现 sub agent 也有主观偏差,所以人工 review 变成 judge calibration。
- 我按已有 harness 思路积累 bad case 和 boundaries。
- 我发现只积累负反馈效果一般,于是加入 good case 和 exemplars。
- 我发现修复会破坏原本好的 case,于是需要 Golden Set 和 Regression Gate。
- 我发现随机 case 探索效率低,于是继续推到 Active Probing。
- 我发现循环需要停止条件,于是补出 Convergence Metrics。
这比给它起一个新名字更重要。
名字可以不要,但这组模块应该保留下来:Trace、Shared Context、AI Review、Human Calibration、Boundary Store、Exemplar Store、Golden Set、Regression Gate、Active Probing、Judge Calibration、Convergence Metrics。
它们共同解决的是一个问题:如何让每一轮实践产生的经验,真的进入下一轮修改。
最小可复用版本
如果把这套流程压到最小,我会保留六个模块。
Case Trace
每轮结果必须可回看。至少要能看到 case、版本、输入、输出链接、关键中间产物和 tool calls。对 video agent 来说,只看最终视频不够,最好能看到素材分析、manifest 和 render prompt。
Shared Review Doc
评论必须挂在具体结果上。不要只在聊天里说“这一版不行”,而是把评论放到具体 case、具体阶段、具体输出旁边。
Isolated AI Review
让没有参与修改的 sub agent 做 review。它不负责最终拍板,但负责发现 coding agent 可能忽略的副作用。
Human Calibration
人工评论负责方向、审美和取舍,同时校准 sub agent 的评审偏差。
Boundary / Exemplar Store
confirmed bad case 进入 boundary,confirmed good case 进入 exemplar。前者告诉 agent 哪些条件下会坏,后者告诉 agent 哪些东西不要被下一轮修掉。
Golden Set / Regression Gate
每轮修改后回看一批人工确认过的好 case。先保证不退化,再继续探索新问题。
这个最小版本已经能解决很多 agent 迭代里的走偏问题。
Active Probing、Judge Calibration 指标化、Convergence Metrics,可以作为下一阶段增强件接上。
关键 takeaway
- 共享文档不是普通日志,而是 agent 迭代里的 shared context、external memory 和 review surface。
- sub agent review 的价值在于上下文隔离,但它仍然需要人工校准和自身迭代。
- 只积累 boundaries 不够,必须同时保存 exemplars 和 Golden Set,否则 agent 很容易越修越保守。
- 从实践里长出来的 harness,本质是在设计反馈系统,而不是让 coding agent 凭感觉多跑几轮。
参考
我在实践中明确想起并对照过的文章:
- OpenAI: Realtime Eval Guide
- OpenAI: Harness engineering, leveraging Codex in an agent-first world
- Cursor: Continually improving our agent harness
后续和 agent 讨论这套方法论时补充的理论参照:
- Reflexion: Language Agents with Verbal Reinforcement Learning
- Self-Refine: Iterative Refinement with Self-Feedback
- Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena
- EDDOps: Evaluation-Driven Development for LLM Agents
- Self-Generated In-Context Examples Improve LLM Agents for Sequential Decision-Making Tasks