OpenAI Tax AI 解读:用 Codex 构建会自我改进的 Agent

本文基于 OpenAI 工程博客 Building self-improving tax agents with Codex(作者 Aravind Srinivasan、Samay Shamdasani、Arthur Fernandes Araujo、John de Wasseige,发布于 2026-05-27)。以下为译述与解读。

过去六个月,OpenAI 与 Thrive Holdings 的工程师和研究员给 Crete 的 30 多家会计事务所搭了一个报税系统 Tax AI。本季参与试点的 Crete 事务所处理了 7000 份 1040(个人)和 1041(遗产与信托)申报,节省了从业者约三分之一的报税准备时间,吞吐量提升约 50%,草稿准确率最高 97%,系统本身比三个月前刚部署的版本更好。75% 字段完成率从上线时的 25% 在六周内涨到 86%,90% 和 100% 完成度的增长更快。

这个系统上线后没有停在「工程师修 bug」的循环里。改进的动力来自 Codex 把生产数据变成结构化信号。从业者日常做的每一次修正都被结构化记录,反复出现的模式最终归入 Codex 的工程任务列表。Codex 调查、修代码、跑验证关卡,工程师只负责审查候选 PR 和发布决策。例行修 bug 的人力消耗被替代,PR 审查、疑难案例处置和发布判断这三件事仍然是人做的。

报税领域的工程难度

Crete 的会计师每个报税季要准备数万份税表,背后是数百万份原始文档。一份中等偏复杂的申报,光是数据录入可能要花 8 小时。W-2 是雇主发的工资税务表,1099 是付给非雇员的各种收入申报,这些都相对结构化。K-1 是合伙、S 公司、信托等实体的收入分配表,Schedule E(补充收入与亏损表)、Schedule C(个体经营)、Schedule A(分项扣除)等附表,又往往需要跨多份源文档核对。表格本身是高度结构化的,但是数据源是混乱的。把非结构化材料变成结构化申报,是整个过程最耗时的部分,也是错误的高发区。Tax AI 先从 W-2 和 1099 起步,逐步覆盖到 K-1 和更难的附表,每一类都比上一类更耗时。

从业者修改可能反映的五种情况

Tax AI 刚上线时,从业者能修正系统错误,但修正动作的语义在当时没有被记录。一个被改掉的值可能反映五种完全不同的情况:

  • 抽取漏了(extraction miss):系统根本没读到源材料里的这个值
  • 映射错(mapping issue):读到了,但填到了报税引擎里错误的位置
  • 产品不支持(unsupported product behavior):字段或场景 Tax AI 当前还没实现
  • 税务专业判断(tax judgment):会计师基于专业裁量做的选择,既不是 bug 也不是随手偏好
  • 正常工作流噪音(expected workflow noise):从业者按偏好微调、沿用上一年税表里的值、或申报流程别处改动带入

这五类的处理方式完全不同。抽取漏了要修抽取逻辑,映射错要修映射器,产品不支持要排期加字段,税务判断永远不该触发任何改动,但噪音需要经审查后才有资格被考虑。早期系统没有区分这五类的机制,从业者改了值,工程师只能逐条问「你这个改动是什么意思」,迭代周期被沟通开销拖慢,每条修正都得工程师手工归因。

修正到评估集的过滤管线

要让这套机制跑起来,第一步是把修正动作本身结构化。Tax AI 改造了工作流,让每一次从业者修正都带上原始预测值、最终申报值、以及差异是否值得跟进(actionable)这三类元信息,形成字段级的 review row。

但修正动作本身并不是「从业者改过 = 标准答案」。直接拿生产 diff 当评估样本(eval)会让偏好和判断被当成失败去优化,指标涨了,但是评估集本身是脏的。原文给出的链路是:先在 review row 之上做聚类,把反复出现的模式(漏 fair rental days 字段、把同一份材料里的多套房产混淆、other expenses 处理错)从个案噪音里识别出来。聚类结果由工程师和产品团队审查,确认是产品缺陷而非个别从业者的偏好。被确认的聚类才升级为针对这一类失败的目标评估集。原文没有给出具体的聚类阈值和审查流程细节,这一步的具体做法由各团队按业务风险自行定义。三道过滤让修正值在进入评估集前先去掉偏好与判断的成分。

修正值因此只算是「候选标签」。它要经过 actionable 标注、聚类、人工确认三道过滤,才有资格成为 Codex 可以接手的评估集。

Codex 在四元组里调查根因

评估集准备好之后,Codex 拿到的不只是「输出不对」这一条信号,而是一个四元组的工作区:

  • 生产留痕(trace):从源材料到字段抽取、再到报税引擎提交的完整路径,定位在哪一步断的
  • 评估套件(evals):定义什么算修好,包括从生产数据中构造的针对性评估和原有的回归评估
  • 仓库代码(repo):可改的产品代码面,即 app/tax-ai/rental-income/ 这一限定区域
  • 技能与文档(skills / docs):怎么跑这个任务、历史决策约束、架构约定

Codex 拿到的是带证据、带可编辑代码区域、带明确验证关卡的任务,不是含糊的告警。它读取 trace 假设根因类别,检查 schema(字段定义)是否定义了相关字段、provenance(每条抽取结果在原文档里的位置出处)是否可追溯、源文档选择逻辑是否漏了材料、映射器(mapper)是否覆盖了这个字段、评判器(grader)是否把正常噪音误判成了失败,然后做定向修改,重跑针对性评估,再跑回归评估,最后产出候选 PR 交工程师审查。

读写分离的工作环境与评判器可改的风险

这套工作区的设计有一个关键约束:四元组里的 trace、source artifacts、Tax AI 预测值、最终申报值、报税引擎字段文档是只读的,Codex 只能读不能改;可写的只有 app/tax-ai/rental-income/ 下的产品代码。原文用 branch: codex/fix-rental-0042 这种分支命名、任务 ID 与分支绑定来隔离变更,让审计和回溯有据可查。

只读证据这一约束是为了让评估输入不可变。如果 Codex 能改 trace 或源材料,它就有可能通过修改证据来通过评估,这正是评估系统里典型的自证风险。但原文里允许的修复动作里也包含「refine the grader」一项,也就是评判器本身可被 agent 修改。允许 Codex 改评判器,评估的可信度靠什么保证?答案是工程师对候选 PR 的人工审查。Codex 改评判器、跑评估、产出 PR,工程师在审查 PR 时判断这次改评判器是合理的细化还是在绕过评估。工程师对候选 PR 的审查,是评判器改动可信度的唯一约束。

任务环境的目录树

原文给出的 Codex 任务环境长这样:

/candidates/FIND-RENTAL-0042/

├── repo/                                                              [1]
│   └── branch: codex/fix-rental-0042
│       │
│       ├── AGENTS.md
│       │
│       ├── tasks/FIND-RENTAL-0042/
│       │   ├── task.yaml
│       │   ├── EXEC_PLAN.md
│       │   └── RESULTS.md
│       │
│       ├── app/tax-ai/rental-income/                                  [2]
│       │   ├── agent.ts
│       │   ├── schema.ts
│       │   ├── provenance.ts
│       │   └── mapper.ts
│       │
│       ├── evals/                                                     [3]
│       │   ├── datasets/fair-rental-days.yaml
│       │   ├── suites/fair-rental-days.yaml
│       │   ├── suites/rental-income-regression.yaml
│       │   └── graders/rental-income.yaml
│       │
│       ├── skills/                                                    [4]
│       │   ├── eval-runner/
│       │   └── tax-field-docs/
│       │
│       └── docs/                                                      [4]
│           ├── architecture/
│           └── task-environments/

└── scoped-tools/                                                      [5]
    ├── production-trace
    ├── source-artifacts
    └── tax-engine-docs

可写的 worktree 包含任务契约(task.yaml)、执行留痕(EXEC_PLAN.md / RESULTS.md)、仓库级约定(AGENTS.md)、可改的产品代码(app/tax-ai/rental-income/ 下的 agent.ts / schema.ts / provenance.ts / mapper.ts)、定义成功的评估套件(evals/)、怎么跑任务和历史决策约束的技能与文档。只读上下文(scoped-tools/)提供生产留痕、原始文档、报税引擎字段文档。原文未明确说明只读上下文是挂载目录还是受限查询工具,对复刻这套环境的团队这是需要自己定的设计点。

这套目录结构本身就是失败分类法的镜像:可改面里的 schema.ts 对应「字段未定义」类失败,agent.ts 对应「抽取模式未命中」,mapper.ts 对应「映射器未覆盖」,graders/rental-income.yaml 对应评判器误判。Codex 拿到这个工作区,等于把失败分类、修复面、验证关卡放在同一个目录里。

什么时候交给通用智能体

Codex 拿到任务环境后,从外部看仍然像一条流水线:读取任务说明、定位代码、修改、跑评估、产出 PR。这一段和自动化 CI/CD 的差别在哪?通用性落在根因定位和修复方案选择这两步:失败模式不必预先枚举。传统自动化脚本面对没见过的错误会沉默或崩溃,因为它依赖「错误模式 → 修复动作」的查表,但是 Codex 能读 trace、读仓库、读技能、读评估,自己假设根因、自己生成补丁。所以判别准则是:根因空间是高维的、需要追溯多种信号、需要理解代码而不只是匹配规则时,应该交给通用智能体;失败模式有限、动作可枚举时,传统脚本更稳。

那为什么不让 Codex 直接读生产数据、做模型微调?原文没有讨论这条路线,工程上的理由有四条:微调一轮要花几小时到几天、每次改动都要重训、出了问题回滚难、模型权重变化不可读、PR 审查无从下手。Codex 改的是产品代码,diff 可读、可回滚、可审查。改进单元是「可读的 patch + 可跑的评估」。

自动化划在哪条边界

自动化停在抽取层和映射层。从源文档到税工作流结构的转换有明确期望输出,Codex 改完可以跑回归。但架构决策、产品决策、发布判断这些没有可验证指标的环节,还得工程师拍板。从业者影响改进方向的方式,就是他们本来就在做的事:修正抽取的字段、审查税表、批准申报。

从业者不需要学任何新工具。系统把他们日常的修正自动结构化记录,作为下一轮的改进信号。改动只落在产品代码层(抽取、映射、判定规则),没碰模型。Codex 提交的候选 PR 必须经工程师审查才能合入。

跨域复制的两个支撑

这套设计正在被复制到记账、审计、IT 运维。跨过去靠的是两条独立的逻辑:一条是抽象复用,一条是组织前提。两条分开讲才能讲清楚。

第一条:抽象复用。租房子任务从立项到抽取字段达到 90% 精确率和召回率,花了大约六周,期间投入了大量工程师精力。这套投入产出了可复用的评审工件、评估约定和实现模式,税务内的 Schedule C、Schedule A 等子任务可以直接借力。但这条只够解释税务内部子任务的复用,从税务跨到 IT 运维的那一段还差别的支撑。

第二条:组织前提。Thrive Holdings 既做所有者也做运营者,工程团队进入 Crete 这种业务内部时是合伙人而非供应商,能直接接触从业者和生产数据。跨域复制靠的是这套能直接和从业者协作的位置,抽象沉淀得够不够反而不是关键。

结语

从业者日常的修正流入 review row,聚类把这批修正升级为目标评估;Codex 据此调查,产出候选 PR;工程师合并之后,这些改动又成为下一天的修正源,如此循环,优化了整个流程。

目录