金融智能体上线前必须补齐的治理工程
文章以贷款审核智能体被合规团队否决的经历,说明准确率之外还必须保留可追溯的决策依据。内容涉及审计记录架构、权限控制、人工审核节点及相关代码模式。
AI 深度解读
金融 AI Agent 能不能上线,往往取决于它能否证明自己做过什么。作者团队的贷款审核 Agent 在测试数据上表现不错,却在合规审查两小时后被否决:他们无法还原一次拒贷建议依据的确切数据和判断过程。
原文给出的路线很明确:先设计审计记录、权限边界和人工审批,再把模型接进去。对准备让 Agent 接触交易、客户资料或审批流程的开发者,这套思路值得借鉴,但示例代码距离可上线系统还有几处需要补齐。
审计要保存当时的现场,不能只留运行日志
作者把 Agent 智能与其他工程工作粗略分成 30% 和 70%。这个比例是经验判断,文章没有提供工时统计;它想强调的是,模型答对问题,只完成了交付的一部分。
普通日志主要帮助开发者排错。金融审计还要回答:系统收到什么数据,检查了哪些规则,调用了什么工具,工具返回什么,最后建议和实际动作分别是什么。
原文的 AuditRecord 因此包含输入快照、输入哈希、Agent 版本、模型版本、prompt_hash、规则列表、置信度,以及人工审核和推翻建议的理由。
这里最实用的设计是同时保存 input_data_hash 和 input_data_snapshot。业务数据库里的客户资料可能随后更新,审计需要的是决策当时的状态。哈希用于核验数据,快照用于还原现场,两者不能互相替代。
作者还用 previous_record_hash 串联记录。下面这段代码负责计算当前记录的哈希:
def __post_init__(self):
"""Compute hash for tamper detection."""
content = json.dumps({
'record_id': self.record_id,
'transaction_id': self.transaction_id,
'input_data_hash': self.input_data_hash,
'decision': self.decision.value,
'timestamp': self.timestamp.isoformat(),
'previous_hash': self.previous_record_hash
}, sort_keys=True)
self.record_hash = hashlib.sha256(content.encode()).hexdigest()
要看清 content 包含的字段:它没有覆盖 reasoning_chain、人工审核信息等内容。修改这些字段,不会改变这里计算的 record_hash。而且,普通 dataclass 加一句「不可变」注释,也不会自动禁止修改。
哈希链提供完整性校验的思路,不能单独保证审计记录不可篡改。
存储方面,原文建议 PostgreSQL 保存最近 90 天的热数据,S3 + Parquet 保存长期记录;AuditStore 的 retention_years=7,正文则提出保存七到十年。但文章没有交代适用地区和业务类型,不能把这个年限直接当成统一合规要求。
示例还有一个矛盾:作者要求只追加、禁止更新和删除,归档代码却调用了 mark_archived。归档状态与审计正文是否分开存储,原文没说清。纠错应追加新记录,这个原则成立;具体存储约束仍需另外实现。
模型可以提出建议,执行权要由规则决定
原文安排的处理顺序是:确定性检查、AI 评估、人工检查点、权限核验与执行,每一步产生审计记录。一笔交易通常对应四到六条记录。
规则先行有直接收益。已经违反明确要求的交易,没有必要继续消耗模型调用;需要解释和判断的部分,再交给 AI。
权限设计也落到了业务动作上。ap_processor 可以读取发票、采购订单等资料,写入处理状态和审批队列,但明确禁止 payments.execute、vendor_master.modify,也不能访问总账、工资和资金管理系统。underwriting_analyst 可以写风险评估和建议,却不能批准、拒绝贷款或放款。
这比给 Agent 一个宽泛的「财务系统账号」更容易审查。显式列出禁止项,也能让业务人员看懂它的操作边界。不过,权限必须在实际工具或服务入口强制执行,代码里列出 blocked 并不自动封住所有访问路径。
人工检查点则按交易条件触发:
- 金额超过
100_000,转给senior_finance,sla_hours为 4。 - 置信度低于
0.85,转给domain_specialist,时限为 8 小时。 - 交易对手历史不足 90 天,转给
risk_analyst,时限为 24 小时。 - 出现监管标记,转给
compliance_officer,时限为 4 小时。
审核人收到的应包括交易、建议、适用规则、判断依据和最近 5 步审计记录。对于前端开发者,这直接对应审批详情页的信息结构:只放「同意」「驳回」两个按钮,无法帮助人作出可靠判断。
不过,配置项还不是完整机制。示例没有实现超时后的二次升级;evaluate 命中第一条规则就返回,多条规则同时触发时如何确定审核角色和时限,也没有说明。更具体地说,贷款角色的 amount_ceiling=None 表示全部升级,但执行代码直接拿金额与该值比较,会遇到类型问题。
每次换模型和提示词,都要重新证明结果可靠
作者建议准备 300 到 500 笔已有正确结果的真实交易,由有经验的财务人员标注。Agent 更新、提示词修改、模型版本升级,都跑同一套回归测试。
下面的代码把结果不一致比例作为发布门槛:
match_rate = sum(r["match"] for r in results) / len(results)
drift = 1.0 - match_rate
return RegressionResult(
passed=drift <= self.threshold,
match_rate=match_rate,
drift=drift,
failures=[r for r in results if not r["match"]],
recommendation="BLOCK" if drift > self.threshold else "APPROVE"
)
需要关注 drift = 1.0 - match_rate:它计算的是与预期结果不一致的比例。原文称之为决策漂移,但代码没有直接比较新旧版本输出。
默认 drift_threshold=0.02,超过 2% 就阻止更新。如果测试集有 500 笔,10 笔不一致仍在门槛内,第 11 笔才会触发阻断。问题在于,错误后果并不相等:错误升级人工与错误放行交易,不适合只用一个总比例评价。
作者主张真实历史交易优于只用合成数据,这有道理:它能覆盖实际字段、业务惯例和异常情况。但文章没有展示这套测试的真实通过率,也没给出上线前后的效果对照。300 到 500 笔和 2% 都应被视为作者提出的配置,是否够用,要看业务分布和错误代价。
我的判断
这篇最值得保留的是交付顺序:把证据、权限和人工接管写进流程设计。相比靠提示词要求模型「谨慎操作」,服务端权限检查和强制审批能形成更清楚的约束。
但它是一份架构草图。完整执行代码在 _audit 方法中途截断,工具调用与返回值如何逐次落库也没展示。它使用的 reasoning_chain 更适合作为可核验的业务解释材料,不能仅凭模型生成的一段说明,就证明内部判断过程已被忠实还原。
置信度同样有前提。文章没有解释分数如何产生、是否经过校准,0.85 因而只是示例阈值。作者提到 20% 到 30% 的交易升级人工是正常设计,也没有提供相应吞吐量、审核成本或风险下降数据,不能据此估算团队的人力需求。
可以借用它的架构问题清单,不能把示例代码和几个阈值当成合规结论。
能拿来做什么
- 开始交易或审批类 Agent 项目前,先列出每个阶段要保存的输入快照、规则版本、工具结果和实际动作,再据此设计 Node 服务的数据结构与接口。
- 把读取资料、生成建议、修改状态和执行资金动作拆成明确权限,在工具服务入口逐次校验;金额上限由业务负责人确定。
- 做人工审核页面时,一并展示原始数据、判断依据、触发规则、截止时间和历史处理记录,让审核人能够核查建议。
- 为提示词和模型升级准备经业务人员确认的历史交易集,除总体一致率外,单独检查错误放行、错误拒绝和遗漏人工审核的案例。