多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

拆解OpenWorkBuddy:Agent Harness如何让LLM输出成为可验收办公成果

拆解OpenWorkBuddy:Agent Harness如何让LLM输出成为可验收办公成果 我把 OpenWorkBuddy 拆开看过之后意识到Agent Harness 真正要解决的问题不是怎么调大模型LLM生成更漂亮的文案而是怎么让每一次 LLM 调用都有办法变成一份可验收的办公产物。过去大半年我跟各种 Agent 框架打交道踩得最多的坑就是模型回答得头头是道结果却落不成一份能直接交出去的工作成果。OpenWorkBuddy 给我的启发是它把“调用模型”这件事从自由对话重塑成了受控流水线每一步都有输入、有校验、有产物。这篇文章不聊空泛的概念就从我实际拆它的设计、跑它的小场景、踩它的坑出发把“Agent Harness 到底在哪些环节做事”讲清楚给正在折腾 LLM 办公自动化的朋友一个可复现的参考。1. Agent Harness 是什么先别急着写代码把概念捋清楚这个圈子里最容易被滥用的两个词一个是 Agent另一个就是 Harness。很多人把带 Function Call 的 LLM 应用叫 Agent把带工具调用的都叫 Harness实际上两者的目标和约束逻辑完全不同。OpenWorkBuddy 之所以强调自己是 Agent Harness是因为它的设计重心不在“让模型更聪明”而在“让模型的输出更合格”。1.1 Harness 不是 Agent两者的血缘和目的不一样我给一个比较直白的区分Agent 框架的重心是“自主性”模型拿到一个目标之后自己去规划、调用工具、自我纠错典型的循环是 ReAct思考、行动、观察、再思考。这种模式适合探索型任务比如浏览器搜索、开放问答、写一段创意文案结果允许有偏差用户接受“大概对”的产出。Harness 的重心则是“受控性”。这个词在工程领域原意是“将设备固定在特定轨道上的约束装置”放到 LLM 场景里它强调的是模型在预先定义好的轨道里运行什么时候调模型、调完之后输出要过什么校验、不合格怎么处理这些都不是模型说了算的。OpenWorkBuddy 给我的感觉就是这样模型只是产线里的一个执行工位而不是拍板的人。我整理过一个对比表适合团队内部讨论选型时用对比维度Agent 框架Agent Harness如 OpenWorkBuddy 思路核心目标自主完成任务按契约产出合格结果输出要求自然语言允许发散符合 Schema字段可校验容错策略靠模型自我修正靠外部校验器和重试逻辑状态管理通常无状态或轻量显式状态机可断点恢复验收方式用户自行判断规则校验加上人工确认适合场景研究探索、问答、创意办公文档、报表、审批类任务这不是说 Agent 不好而是说它们的定位不同。如果一件事允许“错了再试”Agent 很合适如果一件事是“错一个字段就要返工”那必须用 Harness 的思路把它约束住。1.2 为什么普通 Agent 框架产不出“可验收”的东西我自己拿通用 Agent 框架写过办公辅助工具做出来的东西看起来能跑但实际交付时发现三个硬伤。第一个硬伤是输出自由度高。LLM 本质上是个采样模型同一个 prompt 每次出来的文本都会有差异。写邮件、写摘要这种任务无所谓但办公产物要求的往往不是“差不多”而是字段齐全、格式统一、数值准确。比如一个销售周报它要求“计划完成率”必须有不能这周叫“计划完成率”下周叫“完成计划百分比”。普通的对话式 Agent 很难保证这种一致性。第二个硬伤是状态不可恢复。办公自动化任务经常是长流程要查数据、写报告、做图表跑一半遇到网络超时或者工具报错普通 Agent 框架往往只能重新来一遍。一次两次还能忍天天跑就受不了了。第三个硬伤是上下文黑盒。模型生成了什么、依据了什么、哪一步消耗了多少 Token这些东西大部分框架不记录。真出了问题只能对着聊天记录猜。办公产物是要写进工作流里供人审阅、存档的没有追溯能力根本谈不上“验收”。OpenWorkBuddy 的思路恰恰是针对这三点做约束的输出必须匹配 Schema流程必须按状态推进所有步骤必须留痕。这是它值得拆的原因。1.3 “办公产物”的验收标准先说清楚既然说“可验收”就得先定义什么算合格。我的定义是四件事结构化、可复现、可审计、可编辑。这四条是针对长期做过办公自动化的共性总结。结构化指产物不是一段纯粹的散文而是有明确字段的交付物比如 Excel 的一行记录、Word 的一个章节、邮件的一个正文模板。可复现指同一份输入、同一套配置产出的结果应该尽量稳定至少不出现字段缺失或格式漂移。可审计指每一项内容都能追溯到数据来源和模型调用记录出了问题能倒查。可编辑指产物本身要落到真实文件里方便人在最终交付前手工微调而不是只存在于聊天窗口里。验收维度解释反面例子结构化信息有固定字段和类型模型输出一段混合格式的文字可复现相同输入产出稳定结果两次生成字段名不一致可审计可追溯生成依据与过程说不清某结论出自哪份数据可编辑产物以标准文件形式落盘只能复制聊天内容格式全丢这四条是后面所有设计的总纲。你记不住细节没关系记住这四件事就能看懂 OpenWorkBuddy 每一步到底在干嘛。2. OpenWorkBuddy 的整体设计思路给 LLM 加一条流水线OpenWorkBuddy 最核心的转变不是新增了什么功能而是把思维模型从“对话”切成了“流水线”。它不关心模型能不能跟你聊得开心只关心任务能不能在一个个阶段里稳定地往前推进最后在终点交付一个合格文件。2.1 从“模型对话”到“任务管线”的思维切换我常拿实习生写报告来类比这件事。你交给一个实习生整理月度数据不会让他站你面前口述一段就算完事而是会给他一个模板让他查数、填表、写说明、自查、提交。每一个步骤是可确认的最后是有一份实物交付的。OpenWorkBuddy 做的就是把这个过程显式建模出来。它的核心编排逻辑可以抽象成这么一条管线定义产物契约、拆解任务、执行各步骤、规则校验、落盘归档。每一步都是独立可执行的模块模型只负责其中“生成”和“理解”相关的环节其余环节由工程代码控制。# OpenWorkBuddy 风格的任务管线示意简化版 pipeline [ {step: collect_inputs, handler: read_commits}, # 收集原始资料 {step: draft_report, handler: llm_generate}, # 模型生成初稿 {step: validate, handler: schema_check}, # 规则校验 {step: judge, handler: llm_as_judge}, # 模型评分 {step: export, handler: save_artifact}, # 产物落盘 ]这种设计的好处是每一步都有明确的输入输出坏在哪一步延迟、报错、返工都能定位。最直接获益的是调试体验以前模型跑偏了你只能跟它“再聊一次”现在你可以精准地发现是第 3 步校验不过然后只调整第 3 步的策略其他环节完全不动。2.2 任务状态机让长流程可中断、可恢复多步骤的办公任务往往要跑几十秒甚至几分钟期间可能遇到网络抖动、工具超时、模型接口限流。OpenWorkBuddy 把任务用显式状态机管理起来我认为这是它区别于大多数“对话式 Agent 封装”的关键设计之一。状态的划分也不复杂大概是这样一组created、running、await_tool、validated、failed、done。每个任务实例在任何时刻都处于其中一个状态状态变更时会写一条事件日志。所谓“events”包含当前状态、触发原因、涉及步骤、时间戳有时候还会带上输入输出的摘要。状态含义可能的流转created任务已创建等待执行进入 runningrunning正在执行某一步进入 await_tool、failed、validatedawait_tool正在等待外部工具返回回到 runningvalidated校验通过等待最终处理进入 donefailed执行失败或校验不通过可重试回到 running或终止done产物已归档终态有状态和没状态的区别在真实跑批时非常明显。没有状态机的方案一旦断线连“刚才跑到哪了”都要靠猜有了状态机重新连上之后可以直接恢复到最近一个 checkpoint把之前已完成的步骤作为输入传给下一个步骤继续跑而不是从头来一遍。2.3 验收视角的数据设计每一步都留痕可验收的另一个前提是“过程可见”。OpenWorkBuddy 会对每个任务实例持久化一份元数据内容包括任务 ID、模型版本、prompt 模板版本、各步骤耗时、Token 消耗、校验结果以及关键步骤的输入输出快照。{ task_id: task_2025W12_9f3a, model: gpt-4o-mini, prompt_version: v3.2, steps: [ {name: collect_inputs, duration_ms: 320, status: done}, {name: draft_report, duration_ms: 4820, status: done, tokens: 1240}, {name: validate, duration_ms: 15, status: validation_failed, reason: missing_planning} ], validation: {passed: false, issues: [planning 字段为空]}, artifact_path: output/weekly_report_2025W12_v2.md }举个实际场景你收到一份周报里面某个数据明显不对普通 Agent 你是没办法知道这个数怎么来的但在 OpenWorkBuddy 的任务记录里你可以找到生成这段内容时输入了哪些 commit 记录、是哪个模型版本、用了哪版 prompt。这种透明度才是办公场景敢把 AI 纳入正式流程的基础。3. 把 LLM 调用变成可验收产物的三个关键实现如果说上一部分是整体架构思路这部分就是血肉。我拆 OpenWorkBuddy 时最有收获的是它在具体实现上拷问了三个问题怎么约束模型的输出格式、怎么安全地让模型调用工具、怎么让产物真的被“验收”而不是看一眼就完事。3.1 用 Schema 给 LLM 输出定契约模型输出的自然语言不能直接作为交付物这是办公自动化的第一性原理。OpenWorkBuddy 的做法是在任务一开始定义产物 Schema让模型只能在这个结构里填空而不是自由创作。以周报场景为例一份电子表格或文档的字段结构可以被这样定义from pydantic import BaseModel, Field class WorkItem(BaseModel): title: str Field(..., max_length50) status: str Field(..., pattern^(done|doing|blocked)$) owner: str Field(..., min_length2) class WeeklyReport(BaseModel): week: str Field(..., pattern^2025-W\\d{1,2}$) completed: list[WorkItem] Field(..., min_length1) planning: list[WorkItem] risks: list[str] Field(default_factorylist, max_length5)为什么这步重要因为模型的输出是概率采样没有外部约束时字段名、顺序、枚举值都会漂移。有了 Schema 之后校验器可以直接检查结果是否满足结构要求缺字段就报错枚举值不合法就报错列表太短也可以拦截。模型的自由度被限制在“怎么写内容”而不是“写什么结构”。我的实操体会是字段定义不是越细越好要抓关键约束。一开始我把每个字段都加了长度限制和枚举结果模型频繁触发校验失败实际并非字段错了而是我的枚举设计不接地气比如“进行中”既可能对应 doing 也可能对应 in_progress。后来我将枚举先放宽、长度限制只作用于最关键字段整个通过率明显提升。3.2 工具层级让模型在沙箱里干活而不是放手乱跑办公自动化躲不开读写文件、查数据库这些动作。OpenWorkBuddy 对工具的管理方式并不是简单地把 Function Calling 暴露给模型而是把工具当成需要注册、限量、留痕的“受控资源”。每个工具在注册时要提供名字、功能说明、参数 Schema以及可执行的目录白名单。模型能调用的不是任意函数而是这几个约定好的入口。对于文件类工具还会做一次沙箱隔离模型读写路径被限制在指定工作目录内触碰目录之外直接拒绝。工具名参数示例权限策略超时设置read_filefilename仅白名单目录可读5swrite_filefilename, content仅输出目录可写5squery_excelfilepath, clause只读不运行宏10sdry_run_emailto, subject, body预览模式不真实发送10s我见过不少失控案例比较典型的是让 Agent 自由执行 shell 命令结果它真跑去删了一个临时目录。OpenWorkBuddy 这种“沙箱加白名单”的约束在办公场景非常必要。安全不是亡羊补牢而是从一开始就不给 LLM 破坏的机会。3.3 双通道校验从“生成结束”到“验收通过”有了 Schema 和受控工具还差最后一步——判定产物合不合格。OpenWorkBuddy 用的是规则加模型的混合校验而不是单一通道。规则校验跑在最前面检查 Schema、必填项、枚举值、格式正则这类硬性要求速度快、结果确定。比如前面周报例子里的 week 字段正则不匹配直接打回。通过规则校验之后会再走一道模型自评也就是 LLM-as-Judge让另一个模型实例对内容质量打分看有没有明显的事实冲突或逻辑混乱。最后一道是人工确认因为办公产物有责任属性不能让模型自评通过就自动发出得留一个真人审阅的位置。模型生成 - 规则校验 - 模型自评 - 人工确认 - 产物归档 | | | | ---失败返工-----低分返工-----修改后提交-这条链路的价值在于把“验收”变成了工程流程的一部分。模型生成的不是终稿而是“待检稿”。验收通过的产物才会被写入最终成果目录才算真正交付。4. 实操复盘用 OpenWorkBuddy 跑通“周报自动生成”理论说再多不如跑一个实际场景。我拿周报自动生成当案例完整走了一遍 OpenWorkBuddy 的流程。选它的原因很简单这个场景足够小人人都懂但又有代表性涉及数据收集、内容生成、格式校验、文件产出全链路。4.1 场景定义与任务拆分任务目标很简单读取本周 Git 提交记录自动生成一份符合团队模板的周报包含已完成事项、下周计划、风险与阻塞三项最终落成 Markdown 文件。我把任务拆成了五个子步骤收集提交记录、生成初稿、规则校验、模型质量自评、落盘归档。任务规格以 TaskSpec 形式描述每个子步骤明确输入输出。这个拆法看起来很朴素但它保证了一个重要的事每一步都有独立的成败判定。比如初稿步骤如果失败我只要重跑生成不需要再重新收集数据收集步骤如果超时我可以只修数据源而不用动生成逻辑。4.2 Agent 行为配置文档任务要把随机性压到最低真正测试之前我调整了几个关键的模型行为参数这些参数对结果稳定性影响极大。文档生成不是创意写作随机性越低越好。我把 temperature 调到 0.2top_p 调到 0.9max_tokens 限制在 2000同时在系统提示词里明确要求“只基于给定的提交信息不要发挥”。这里有个容易被忽视的点办公产物类任务上下文里的信息越干净输出越可靠。我最初把整年的 git log 都塞进去期望模型自己挑重点结果它挑得混乱不堪。改成只传本周提交记录之后产物质量立刻稳定了。给模型少量精准数据远比给海量杂乱数据管用。[system] 你是周报撰写助手。只依据用户提供的 commit 记录整理内容 不得编造未出现的事项。输出必须符合 WeeklyReport 的 JSON Schema。 [user] 本周提交记录如下 - fix: 修复订单模块空指针 - feat: 新增导出 Excel 接口 - docs: 更新接口文档 ... 请生成本周周报。4.3 执行过程与 trace 日志一次校验失败的现场回放运行过程中OpenWorkBuddy 在每个关键节点都会写一条结构化日志。我把一次实际运行的事件记录精简后放在下面可以看到第 4 步校验曾经失败过而后被重试机制纠正。{event: step_start, step: collect_commits, time: 10:02:01} {event: tool_call, tool: git_log, params: {since: 2025-03-17}, status: ok} {event: model_generate, step: draft_report, tokens: 1240, status: ok} {event: validation_failed, reason: planning 字段为空, attempt: 1} {event: retry, message: 重新生成第 2 版草稿, attempt: 2} {event: validation_passed, duration_ms: 18} {event: judge_score, score: 8, comment: 内容完整格式符合要求} {event: artifact_saved, path: output/weekly_report_2025W12_v2.md}重点看第 4、5 行的价值。模型第一次生成的草稿漏掉了“下周计划”如果这是普通的聊天式 Agent它可能不会发现这个缺陷周报就直接发出去了。Harness 的规则校验发现了缺字段自动触发一次重试第二次生成在系统提示词的修正提示下补齐了内容最终通过了校验。这就是“可验收”机制的实感。4.4 产物落盘怎么组织版本化、元数据、可追溯产物落盘不是扔一个文件到桌面就完事。OpenWorkBuddy 会把最终产物和任务元数据一起存入固定目录而且每次运行生成一个新版本不覆盖旧文件。这样即使后来发现问题也能回到历史版本核对。output/ ├── weekly_report_2025W12_v1.md ├── weekly_report_2025W12_v2.md └── meta/ └── task_2025W12_9f3a.jsonmeta 文件记录了这个产物的完整生成背景任务 ID、模型版本、温度参数、各步骤耗时、校验记录。我强烈建议大家在自己搭建类似系统时也保留这个习惯不要为了省存储去覆盖旧版本。模型生成天然有随机性留版本就是留证据也是让业务团队信任这套系统的基础。5. 常见问题与排查技巧实录OpenWorkBuddy 这套思路跑起来之后日常运维一定会遇到几个典型的故障模式。我把遇到的、以及听身边同事聊过的问题整理一下给正在搭类似系统的人一些排障路径。5.1 模型输出频繁被校验器打回这是配置初期最常见的现象。症状是任务成功率低日志里大量 validation_failed。排查逻辑是先看失败原因是结构问题还是内容问题。结构问题比如缺字段、枚举不合法多半是指令没说清楚或 Schema 定义过严内容问题比如字段填了但明显牛头不对马嘴多半是给模型的参考资料太杂或者角色设定不够强。我的处理习惯是先放宽非关键字段约束跑通主链路再逐步收紧。一上来就追求完美 Schema容易把精力耗在枚举映射上而不是产物质量上。5.2 工具调用超时或失败工具层的问题比较直接日志里会暴露两类信号。一类是工具返回超时比如 git log 在超大仓库上跑很久需要给工具设置合理的超时时间并对命令做裁剪。另一类是权限类错误比如模型试图读白名单之外的路径Harness 拒绝执行并记录违规这种通常需要对工具策略做调整而不是去迁就模型。值得嘱咐一句不要因为出了几次工具报错就放开白名单宁可在代码里增加重试和补偿逻辑也不要给模型更大的破坏面。5.3 长任务中途上下文爆窗办公任务如果输入材料很多很容易在几步之后把上下文窗口塞满模型开始遗忘早期指令输出质量断崖式下跌。我的处理方案是基于状态机的 checkpoint 机制每完成一个步骤就压缩一次上下文只保留该步骤的结构化结果丢弃原始过程文本。这样既保留追溯能力又避免上下文累积。如果你的任务链条很长可以考虑把“资料获取”和“内容生成”严格分家获取步骤产出的是一份干净的中间数据文件生成步骤只消费这个文件。5.4 不同批次产物字段对不上这个问题往往不是模型造成的而是 Schema 版本升级后没有做迁移。比如这周给 risks 字段加了 max_length上周的任务记录还按旧结构存储。排查方式是检查任务元数据里的 prompt_version 和 schema_version统一版本后再做对比分析。所有类似工具都建议在 Schema 里显式维护版本号并在变更时刷新所有下游校验逻辑。5.5 常见问题速查表现象排查入口常见原因解决建议频繁校验失败validation_failed 日志Schema 过严或 prompt 不清放宽非关键字段逐项收紧工具超时工具调用日志命令执行时间过长限制命令范围加超时控制权限拒绝事件日志模型访问白名单外路径调整目录白名单不改全局权限上下文爆窗token 消耗记录上下文累积过多引入中间文件与压缩策略产物字段错乱schema_versionSchema 版本未迁移统一版本治理更新校验器内容事实错误judge 评分低参考资料不足或过杂精简输入强化“只依据给定资料”约束按这套速查表去排查大多数问题半小时内能定位到具体环节。真正停下来发现需要返工的情况反而很少因为 Harness 已经把绝大多数模型层面的问题挡在了验收之前。我自己的经验是判断一个 LLM 办公自动化方案值不值得投入就看它有没有一套“说得出凭什么不合格”的机制。OpenWorkBuddy 给我的感觉就是它把模型从“答案输出器”变成了“受约束的作业员”每一次调用都有目的、有依据、有出口。如果你也想搭自己的 Agent Harness不用急着做大而全的平台先从“一份周报、一张表格、一篇邮件”这样的小场景开始把产物 Schema、工具沙箱、双通道校验这三个核心机制建起来后续扩展就顺理成章了。
返回列表