<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>OpenAI Agents on CAO ZUOHUA</title><link>https://caozuohua.github.io/tags/openai-agents/</link><description>Recent content in OpenAI Agents on CAO ZUOHUA</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Fri, 18 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://caozuohua.github.io/tags/openai-agents/index.xml" rel="self" type="application/rss+xml"/><item><title>Agent Framework Lab 开发实录：从比较 demo 到企业就绪 Alpha</title><link>https://caozuohua.github.io/posts/2026-09-18-agent-framework-evaluation-5-development-journal/</link><pubDate>Fri, 18 Sep 2026 00:00:00 +0000</pubDate><guid>https://caozuohua.github.io/posts/2026-09-18-agent-framework-evaluation-5-development-journal/</guid><description>&lt;p&gt;这是 &lt;a href="https://caozuohua.github.io/posts/2026-09-18-agent-framework-evaluation-series/"&gt;Agent 框架评测实验室系列&lt;/a&gt;第五篇，也是阶段开发记录。&lt;/p&gt;&#10;&lt;h2 id="起点先让不同框架完成同一任务"&gt;起点：先让不同框架完成同一任务&lt;/h2&gt;&#10;&lt;p&gt;Lab 最早解决的是兼容性：统一 stdin/stdout 的请求与结果契约，让不同 Python/Node 框架可以在各自隔离环境运行。这个阶段最直观的产物是 matrix 和报告，但也很快暴露问题：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;每个 adapter 对 usage 的理解不同；&lt;/li&gt;&#10;&lt;li&gt;有的框架隐藏模型重试；&lt;/li&gt;&#10;&lt;li&gt;MCP SDK 与 CLI 协议不同；&lt;/li&gt;&#10;&lt;li&gt;同名模型可能被 gateway 路由到不同后端；&lt;/li&gt;&#10;&lt;li&gt;prompt、工具包装稍有不同，分数就不可比。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;因此第一条经验是：&lt;strong&gt;先统一证据格式，再谈统一排行榜。&lt;/strong&gt;&lt;/p&gt;&#10;&lt;h2 id="v20v21运行时从附属代码变成核心边界"&gt;V2.0—V2.1：运行时从附属代码变成核心边界&lt;/h2&gt;&#10;&lt;p&gt;普通 runner 只关心子进程退出码。企业 Agent 还需要 job、attempt、lease、事件 revision、预算 reservation、checkpoint 和 immutable artifact。&lt;/p&gt;&#10;&lt;p&gt;runtime-v1 采用 SQLite WAL 和 append-only event/reducer：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;command -&amp;gt; validate current snapshot -&amp;gt; append events&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -&amp;gt; reduce new snapshot -&amp;gt; transactionally persist both&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这个阶段没有急着做远程服务，而是坚持单机、一次命令、可验证状态。事实证明这是正确取舍：并发和网络还没加入时，就已经发现事件序列、预算结算和终态工件之间有大量边界条件。&lt;/p&gt;&#10;&lt;h2 id="v22恢复不是再跑一次"&gt;V2.2：恢复不是“再跑一次”&lt;/h2&gt;&#10;&lt;p&gt;接下来加入 host crash、SQLite reopen、orphan attempt 回收和 checkpoint resume。LangGraph composed 与 OpenAI Agents native 都通过了“researcher 已完成后恢复，只继续 analyst/reviewer”的测试。&lt;/p&gt;</description></item><item><title>Agent 框架开发与评测踩坑实录：从能跑到可审计、可比较</title><link>https://caozuohua.github.io/posts/2026-09-17-agent-framework-lab-pitfalls/</link><pubDate>Thu, 17 Sep 2026 18:00:00 +0800</pubDate><guid>https://caozuohua.github.io/posts/2026-09-17-agent-framework-lab-pitfalls/</guid><description>&lt;p&gt;很多 Agent demo 的成功标准是：“模型能调用工具，最后返回一个答案。”&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;本文现作为&lt;a href="https://caozuohua.github.io/posts/2026-09-18-agent-framework-evaluation-series/"&gt;《Agent 框架评测实验室系列》&lt;/a&gt;的代码型伴读；系列正文进一步讨论公平赛道、企业场景、故障证据、评分统计和项目演进。&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;但只要把它放进真实系统，问题马上变成另一组问题：任务执行到一半进程崩了怎么办？审批通过的到底是哪一次工具调用？工具重试会不会重复扣款？两个框架比较时，是否真的使用了同一份提示词和工具？模型价格变化后，旧实验的排名还能不能复算？&lt;/p&gt;&#10;&lt;p&gt;我在 Agent Framework Lab V2 RC 中把这些问题做成了一个可以运行、恢复、审计和比较的实验台。本文不讲“Agent 很有前景”，只记录实现过程中最容易被低估的坑、最终采用的设计，以及可以直接复制的代码片段。&lt;/p&gt;&#10;&lt;h2 id="先给结论agent-评测是一条证据链"&gt;先给结论：Agent 评测是一条证据链&lt;/h2&gt;&#10;&lt;p&gt;可信的评测结果必须能回答：这次运行用了哪个框架、模型、provider、提示词和工具？模型调用、工具调用、审批、checkpoint 的顺序是什么？崩溃或重启后哪些动作被恢复，哪些动作绝不能重放？结果怎么评分？换一组权重后能否只重算排名？排名是否因为 ground truth 写错了？&lt;/p&gt;&#10;&lt;p&gt;因此数据流不是：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;prompt -&amp;gt; model -&amp;gt; score&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;而是：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;任务契约 + 模型契约 + 工具契约&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ↓&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; append-only 运行事件&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ↓&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 不可变 RunResult 原始证据&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ↓&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 可重算的 ScoreProfile&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ↓&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 排名、图表和审计报告&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="坑一把任务成功和评分高混成一件事"&gt;坑一：把“任务成功”和“评分高”混成一件事&lt;/h2&gt;&#10;&lt;p&gt;一次运行可能在运行时层面成功完成，但答案质量只有 60 分；反过来，一个答案看起来不错，也不能掩盖未授权工具调用、预算超限或事件账本损坏。&lt;/p&gt;&#10;&lt;p&gt;Lab 将两者拆开：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;RunResult&lt;/span&gt;(BaseModel):&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; run_id: str&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; matrix_id: str&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; framework: str&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; case_id: str&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; status: Literal[&lt;span style="color:#e6db74"&gt;&amp;#34;completed&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;failed&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;blocked_gateway_contract&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;unavailable&amp;#34;&lt;/span&gt;]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; final_output: str &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tool_calls: list[ToolCallRecord] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; []&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; model_calls: list[ModelCallRecord] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; []&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; usage: Usage &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Usage()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; score: Score &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;None&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;None&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; trace_id: str &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;None&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;None&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; metadata: dict[str, Any] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;status == completed&lt;/code&gt; 只表示执行器完成生命周期；&lt;code&gt;score.total&lt;/code&gt; 是评测器对结果的判断。模型返回错误 JSON 时，运行可以成功但结构化输出为 0；预算结算失败时，即使模型输出正确，也必须判为运行时失败；评分规则改变时，可以重算分数，但不能重写原始执行状态。&lt;/p&gt;</description></item></channel></rss>