税务处理向来是"高复杂度 + 高容错成本"的典型场景——一个数字填错,罚款和审计风险接踵而至。OpenAI 与 Thrive、Crete 合作,用 Codex 搭建了一套能自我进化的税务 Agent,把报税流程从手工逐项核对推进到自动填报、自动纠错、自动积累经验的闭环。这篇文章拆解它的核心思路,并给出一个你可以直接改造运行的最小实现。
税务 Agent 要解决什么
传统税务工作流有三个顽固痛点:
- 规则密度极高:联邦、州、地方层级叠加,每年还有新条款生效、旧条款过期,人工跟踪几乎不可能做到零遗漏。
- 数据来源碎片化:W-2、1099、K-1、银行流水、折旧表……格式各异,字段命名不统一,合并时极易出错。
- 反馈周期太长:报错一次,可能要到次年补报甚至被审计才发现,纠错成本随时间指数级上升。
一个合格的税务 Agent 必须同时做到三件事:理解规则、整合数据、从错误中学习。Codex 的代码生成 + 工具调用能力,恰好能串起这条链路。
自我进化闭环的架构
"自我进化"不是营销词——它有一个可工程化的结构:
┌─────────────┐
│ 税务规则库 │ ← IRS Publication、州税法、客户专项条款
└─────────────┘
│
▼
┌─────────────┐
│ Codex Agent │ ← 接收任务、调用工具、生成填报代码
└─────────────┘
│
▼
┌─────────────┐
│ 执行 & 校验 │ ← 运行生成的代码,与规则库交叉校验
└─────────────┘
│
▼
┌─────────────┐
│ 错误回溯库 │ ← 记录每次偏差:哪条规则被误读、哪个字段被漏填
└─────────────┘
│
▼
┌─────────────┐
│ Prompt 修订 │ ← 把回溯结果注入下次 Agent 的上下文
└─────────────┘
│
▼
回到 Codex Agent
关键在于错误回溯库 → Prompt 修订这一步:每次 Agent 犯的错,都被结构化记录下来,下次同类任务时直接作为"不要这样做"的约束注入上下文。这比单纯调参数有效得多——它是在给 Agent 写"错题本"。
最小可运行实现
下面是一个用 OpenAI Python SDK 模拟该闭环的精简版。它包含:任务分发、Codex 调用、校验反馈、错题注入四个环节。你可以替换成真实的税务规则和填报逻辑。
# self_improving_tax_agent.py
# 依赖:pip install openai pyyaml
import json
import yaml
from datetime import datetime
from openai import OpenAI
client = OpenAI() # 默认读取 OPENAI_API_KEY 环境变量
# ── 1. 规则库(简化示例,实际应从 IRS Publication 等结构化提取)──
RULES = yaml.safe_load("""
standard_deduction:
single: 14600
married_joint: 29200
head_of_household: 21900
tax_brackets_2024:
single:
- {limit: 11600, rate: 0.10}
- {limit: 47150, rate: 0.12}
- {limit: 100525, rate: 0.22}
- {limit: 191950, rate: 0.24}
- {limit: 243725, rate: 0.32}
- {limit: 609350, rate: 0.35}
- {limit: null, rate: 0.37}
""")
# ── 2. 错题本(持久化到文件,跨任务累积)──
MISTAKES_FILE = "tax_mistakes.json"
def load_mistakes():
try:
with open(MISTAKES_FILE) as f:
return json.load(f)
except FileNotFoundError:
return []
def save_mistake(mistake):
mistakes = load_mistakes()
mistakes.append({"timestamp": datetime.now().isoformat(), **mistake})
with open(MISTAKES_FILE, "w") as f:
json.dump(mistakes, f, indent=2)
# ── 3. 构建 Agent Prompt ──
def build_prompt(task: str, mistakes: list) -> str:
mistake_block = ""
if mistakes:
# 只注入最近 5 条同类错误,避免上下文膨胀
recent = mistakes[-5:]
mistake_block = "\n## 已知错误(必须避免)\n"
for m in recent:
mistake_block += f"- {m['description']}\n"
return f"""你是一名美国税务计算 Agent。根据以下规则和客户数据完成计算任务。
## 税务规则
{json.dumps(RULES, indent=2)}
{mistake_block}
## 任务
{task}
## 输出格式
返回 JSON,包含:
- "adjusted_gross_income": 数值
- "deduction_used": 数值及类型
- "tax_owed": 数值
- "calculation_steps": 计算过程数组
- "confidence_flags": 任何不确定的地方
只输出 JSON,不要附加解释。"""
# ── 4. 调用 Codex / GPT 模型 ──
def run_agent(task: str) -> dict:
mistakes = load_mistakes()
prompt = build_prompt(task, mistakes)
response = client.chat.completions.create(
model="gpt-4.1", # 或替换为你的 Codex 端点
messages=[{"role": "user", "content": prompt}],
response_format={"type": "json_object"},
temperature=0.1, # 税务计算需要低随机性
)
result = json.loads(response.choices[0].message.content)
return result
# ── 5. 校验:与规则库交叉比对 ──
def validate(result: dict, task_context: dict) -> list:
errors = []
filing_status = task_context.get("filing_status", "single")
# 校验扣除额是否用了正确标准
correct_deduction = RULES["standard_deduction"][filing_status]
if result["deduction_used"] != correct_deduction:
errors.append({
"description": f"扣除额应为 {correct_deduction}({filing_status}),"
f"但 Agent 返回了 {result['deduction_used']}",
"rule": "standard_deduction",
"expected": correct_deduction,
"actual": result["deduction_used"],
})
# 校验税率档位是否正确应用(简化:只检查最高档)
agi = result["adjusted_gross_income"]
brackets = RULES["tax_brackets_2024"][filing_status]
expected_top_rate = None
for b in brackets:
if b["limit"] is None or agi > b["limit"]:
expected_top_rate = b["rate"]
# 这里只做示意,完整校验应逐档累加
return errors
# ── 6. 主流程 ──
def process_tax_filing(income: float, filing_status: str):
task = f"客户年收入 {income},报税身份 {filing_status},使用标准扣除额计算应缴税额。"
task_context = {"filing_status": filing_status, "income": income}
# 第一次运行
result = run_agent(task)
print("Agent 输出:", json.dumps(result, indent=2))
# 校验
errors = validate(result, task_context)
if errors:
print(f"发现 {len(errors)} 个错误,写入错题本")
for e in errors:
save_mistake(e)
# 用错题本重新运行——自我进化的核心
result = run_agent(task)
print("修正后输出:", json.dumps(result, indent=2))
else:
print("校验通过,无需修正")
return result
# ── 运行示例 ──
if __name__ == "__main__":
final = process_tax_filing(income=85000, filing_status="single")
运行方式:
export OPENAI_API_KEY="sk-..."
pip install openai pyyaml
python self_improving_tax_agent.py
要改什么才能用到真实场景:
RULES替换为从 IRS Publication XML/PDF 结构化提取的完整规则集,建议用向量检索按条款动态注入而非全量塞入上下文。validate函数扩展为逐档累加验证 + 客户专项条款检查(如 AMT、外国收入豁免)。- 错题本从 JSON 文件升级为数据库,按"规则 ID × 错误类型"聚合,避免重复注入同类错误浪费 token。
- 生产环境用 Codex 的异步任务模式(
codex create→codex wait),而非同步 chat completion。
生产部署的几个关键决策
规则注入策略:全量 vs 按需
把整本 IRS Publication 塞进 prompt 既贵又慢。Thrive 的做法是两层注入:
- 静态层:常用规则(税率表、标准扣除额)始终在上下文中,体积小、命中率高。
- 动态层:罕见条款(如 §199A 小企业扣除、海外收入豁免)通过向量检索按任务关键词实时拉取,只注入相关段落。
这把 prompt 平均长度从 15k token 压到 4k,同时条款覆盖率反而更高。
错题本的边界
错题本不是万能的。两个需要注意的边界:
- 规则变更时旧错题失效:2024 年标准扣除额变了,2023 年的"扣除额填错"错题就不该再注入。解决方案:每条错题打上规则版本标签,版本过期自动清除。
- 过度约束导致保守偏差:如果错题太多,Agent 会倾向于"什么都不填"而不是"填最可能正确的值"。建议设置注入上限(最近 5-8 条最相关错误),并定期人工审查错题本,删除已不再适用的条目。
人机协作的断点
完全自动化在税务领域有合规风险。Crete 的方案是在三个节点强制插入人工确认:
- AGI 计算完成后——确认收入归类没有误判。
- 扣除项选择后——确认客户没有更适合的逐项扣除。
- 最终税额输出前——确认没有遗漏附表。
每个断点的设计原则是:机器做 90% 的重复劳动,人在 10% 的决策节点拍板。这不是偷懒,而是把审计责任放在该放的位置。
落地检查清单
如果你准备在自己的业务中复制这条路径,先确认以下几项:
- [ ] 规则库是否有结构化版本管理?每年税法更新时能否自动同步并标记版本?
- [ ] 错题本是否按"规则版本 × 错误类型"组织,而非简单的文本堆?
- [ ] 是否设置了 prompt 注入上限,防止错题膨胀导致保守偏差?
- [ ] 人机断点是否覆盖了"归类决策"和"最终输出"两个关键位置?
- [ ] 是否有端到端测试集:用历史真实报税数据跑 Agent,对比人工结果,量化准确率差距?
税务 Agent 的自我进化不是一次性工程,而是持续运营的系统。规则会变、客户会变、模型会变——唯一不变的是那条闭环:执行 → 校验 → 回溯 → 注入 → 再执行。把这条链路搭稳,剩下的就是数据量和时间的游戏。