关键词:Agent 审计日志、AI 工具调用审计、Agent Trace、应用日志、业务操作追溯

假设一个企业 Agent 收到这样的任务:

把订单 SO-1001 的重复付款退回给客户。

几秒钟后,业务系统里真的出现了一笔退款。

如果结果正确,团队可能只会看到一句“执行成功”。但只要金额不对、订单不对,或者用户否认自己发起过这项操作,问题会立刻变成:

  • 谁提出了这个目标?
  • Agent 最终选择了哪项能力?
  • 它生成了什么参数?
  • 当时绑定的是哪个业务主体?
  • 为什么需要或不需要审批?
  • 审批人看到的参数和最终执行的参数是否一致?
  • 请求经过了哪些服务?
  • 业务系统最终接受还是拒绝了它?
  • 同一个动作是否因为重试执行了两次?

很多团队会回答:“这些都在日志里。”

但打开系统后,大家看到的“日志”可能是三种完全不同的东西:

应用日志:refund-service 调用失败,HTTP 500
Trace:gateway -> runtime -> approval -> refund-service
审计记录:谁以什么主体、基于什么决定,对哪个订单发起了什么动作

它们可能围绕同一次调用产生,也可能共享同一个 trace_id,但它们回答的问题不同,可信边界也不同。

应用日志帮助系统维护者解释服务发生了什么;Trace 帮助工程师还原请求经过了哪里;审计记录帮助组织回答谁以什么依据造成了什么业务后果。

如果把三者混为一谈,系统看起来“什么都记了”,真正需要追责时却可能什么都证明不了。

1. 同一次 Agent 行动,为什么需要三种记录

先看一条可能的执行链路:

用户提出退款目标
  -> Agent 选择 refund.create
  -> 运行时校验可信主体和风险
  -> 创建人工审批意图
  -> 审批系统返回通过
  -> 运行时恢复被批准的调用
  -> 退款服务执行业务授权
  -> 支付渠道返回结果

应用日志关心的是每个组件是否正常工作:

refund-service timeout after 3000ms
approval callback signature invalid
database connection pool exhausted

Trace 关心的是这次请求在分布式系统中的因果路径:

span-1 gateway          12ms
span-2 agent-runtime    34ms
span-3 approval       1842ms
span-4 refund-service  213ms

审计记录关心的是行动责任:

requester: user-1024
acting_subject: merchant-88
capability: refund.create
arguments: order_id=SO-1001, amount=1500
risk: high
approval: required, decision=approved
business_result: accepted

同一个 trace_id 可以把三类信息关联起来,但关联不等于相互替代。

2. 应用日志回答的是“系统为什么这样运行”

应用日志首先服务于开发、运维和故障诊断。

典型内容包括:

  • 服务启动、停止和配置加载;
  • 请求解析失败;
  • 依赖服务超时;
  • 数据库、缓存和队列异常;
  • 重试次数与退避时间;
  • 性能告警;
  • 未捕获异常与堆栈;
  • 业务代码为了排错输出的上下文。

它最擅长回答:

为什么这次调用失败了?
哪个组件报错?
错误发生在代码的哪一层?
服务当时是否过载?

但应用日志通常有三个天然限制。

它以组件为中心,而不是以责任为中心

退款服务可能只知道“收到一条退款请求”,不知道这个请求最初来自用户、Agent、工作流还是定时任务。

它的内容会随实现变化

一次重构可能修改日志文本、级别、字段和采样策略。适合排错的日志,不一定能成为长期稳定的责任记录。

它经常由被观察的组件自己书写

如果某个运行时同时执行治理判断、执行操作并写下“我已正确审批”,这条记录仍然是运行时的自述。它可以有用,却不自动成为独立可验证的证据。

因此,应用日志很重要,但“我们有很多日志”不能直接推出“我们有完整审计”。

3. Trace 回答的是“请求经过了哪里”

Trace 的核心价值是把分布式调用还原成一条可以观察的链路。

它通常通过 trace_idspan_id 和父子关系描述:

  • 请求从哪个入口进入;
  • 调用了哪些服务;
  • 每一段花了多久;
  • 错误在哪个 span 出现;
  • 哪些调用并行,哪些调用串行;
  • 某次重试是否产生了新的子调用。

对于 Agent 系统,Trace 尤其有价值,因为一次自然语言任务可能跨越:

模型推理
  -> 工具选择
  -> 治理判断
  -> 人工审批
  -> 队列等待
  -> 本地执行器
  -> 业务 API

没有 Trace,工程师很难判断一个任务停在了哪里,也很难区分“模型没有调用工具”“运行时阻断了调用”和“业务系统拒绝了请求”。

但 Trace 仍然主要是一种可观测性结构。

它能告诉你:

approval-service 被调用过。

却不一定能回答:

谁批准了什么参数?
批准是否发生在执行之前?
批准的调用是否就是最终执行的调用?
审批决定是否可以被第三方验证?

Trace 可以承载这些字段,也可以链接到审计记录,但仅仅存在一条 span,不等于其中描述的治理事实已经成立。

4. 审计记录回答的是“谁以什么依据造成了什么后果”

审计的对象不是某段代码,也不只是某次网络请求,而是一项具有责任意义的行动。

对 Agent 发起的业务操作,一份有用的审计记录至少应该能够帮助组织还原:

  1. 请求来源:谁或哪个系统提出了目标;
  2. 行动主体:这次操作最终代表谁执行;
  3. 能力边界:Agent 使用了哪项 capability 或 scope;
  4. 调用内容:被提交、审阅和最终执行的参数是什么;
  5. 治理判断:风险、审批意图和运行时决策是什么;
  6. 外部决定:是否存在审批,以及决定绑定了哪次调用;
  7. 最终结果:业务系统接受、拒绝、失败还是部分完成;
  8. 时序关系:决定和执行分别何时发生,是否存在重试或重复消费;
  9. 关联标识:如何从审计事件找到对应 Trace、任务和业务对象。

这并不意味着每份审计日志都必须复制完整请求、响应和模型上下文。

恰恰相反,审计越接近真实业务数据,越需要考虑:

  • 敏感字段脱敏;
  • 最小必要记录;
  • 访问控制;
  • 保留期限;
  • 法律留置;
  • 完整性保护;
  • 跨系统时钟和事件顺序;
  • 谁可以写入、修改和删除记录。

审计不是“把所有内容永久保存下来”,而是以可承担的方式保存足以解释责任的事实。

5. 为什么应用日志不能直接充当审计记录

最常见的替代方案,是在普通日志中增加几行:

refund approved
refund executed

这对排错有帮助,却留下了大量歧义:

  • 哪一笔退款?
  • 哪组参数?
  • 谁批准的?
  • 代表哪个主体?
  • “approved” 是审批系统返回,还是运行时自行判断?
  • 执行结果来自业务系统,还是运行时把请求发送出去后就记为成功?
  • 日志是否因为采样、滚动或级别调整而缺失?

应用日志可以包含审计字段,但它需要先具备明确、稳定的审计事件模型,而不是因为文件名里写了 log 就自然成为审计。

更稳妥的做法是:

应用日志负责诊断
审计事件负责责任事实
二者通过 job_id / trace_id / business_object_id 关联

存储系统可以相同,逻辑语义不能含糊。

6. 为什么 Trace 也不能自动成为审计证据

Trace 比普通日志更结构化,所以很容易让人产生另一个误解:

既然所有 span 都记录了,审计已经完成。

问题在于,Trace 的完整性目标通常是可观测,而不是责任证明。

例如,下面这条 span:

{
  "name": "approval.check",
  "status": "approved"
}

仍然没有说明:

  • approved 由谁声明;
  • 审批者是否看到了精确参数;
  • 参数在审批后是否变化;
  • 决定是否过期;
  • 是否可以被重放;
  • span 是否由受益于该结论的运行时自己生成。

在更高保证场景中,可能还需要规范化序列化、签名、发行者密钥、时效锚点和重放保护。这些都不是一个 trace_id 自动提供的。

所以更准确的关系是:

Trace 提供行动链路的可观察骨架
审计记录提供责任事实
独立证据协议在需要时提供可验证性

三者可以组合,但不能偷换概念。

7. 敏感数据让“多记一点”变成新的风险

Agent 工具的参数和结果经常包含:

  • 客户手机号和地址;
  • 身份证件;
  • 支付信息;
  • 员工资料;
  • 医疗或合同内容;
  • API Token、Cookie 和会话凭证;
  • 模型上下文中的其他业务数据。

如果团队为了“完整审计”直接记录原始请求和响应,审计系统可能反过来成为新的高价值泄露面。

因此,敏感性声明的价值不在于规定一种全球统一的掩码样式,而在于提前告诉运行时:

这项能力的参数或响应可能包含敏感数据,日志与审计处理必须采用更保守的策略。

具体策略仍可能因组织而异:

  • 只保留摘要或哈希;
  • 对部分字段脱敏;
  • 把原文放入访问更严格的证据存储;
  • 普通 Trace 只保留业务对象 ID;
  • 诊断日志禁止输出原始响应;
  • 按法规和组织制度设置保留期限。

字段级路径、数组、引用、请求与响应的统一表示,以及旧运行时忽略新脱敏字段时的安全回退,都需要独立、完整的设计。不能因为“字段级脱敏很有用”,就草率地把一套不稳定路径语言塞进通用契约。

8. ACC v1 的 audit 到底声明了什么

ACC v1 有意只保留一个很薄的审计声明:

audit:
  sensitive: true

它表示:

该 operation 的参数或响应可能包含敏感数据,运行时在日志中应进行脱敏或摘要处理。

同时,兼容运行时应当为调用尝试、风险判断、审批意图和最终结果保留审计记录。

这是一项治理意图,不是一套完整审计产品规范。

它没有定义:

  • 日志存在哪里;
  • 保存多少天;
  • 哪个字段采用哪种脱敏算法;
  • 是否使用不可变账本;
  • 审计事件由谁签名;
  • 如何证明主体和审批跨多跳保持真实;
  • 如何满足某一行业的全部合规要求;
  • 如何在不同组织之间交换法律证据。

这种克制不是忽略审计,而是承认这些问题依赖部署环境、组织政策、身份系统和证据协议,无法仅凭一个 API 作者的声明跨企业统一兑现。

ACC 声明“这里需要敏感审计处理”;运行时和组织负责把这项意图兑现成真正可用的记录与控制。

9. 三类记录应该怎样协作

一个清晰的实现可以为同一次调用建立三个相互关联、职责不同的视图。

应用日志

面向维护者:

组件、错误、性能、重试、依赖和调试上下文

Trace

面向链路观察:

入口、span、耗时、调用关系、队列与执行器路径

审计记录

面向责任还原:

请求者、可信主体、能力、参数摘要、治理决定、审批引用、业务结果

三者最好共享稳定关联键:

job_id
trace_id
invocation_id
business_object_id

但敏感数据不应为了方便查询而在三个系统中重复复制。更合理的是让索引和摘要可关联,让原始敏感证据留在具有正确访问边界的位置。

10. 谁应该对哪一层负责

层次 主要责任
能力契约 声明审计敏感性等可移植治理意图
Agent 运行时 记录调用尝试、治理判断、审批意图、执行状态和关联标识
审批或证据系统 保存外部决定及其与能力、主体、参数的绑定
可观测平台 汇聚日志、指标和 Trace,帮助定位链路故障
组织合规策略 决定脱敏、访问、保留、删除和法律留置
业务系统 记录最终授权判断和真实业务结果

这里仍然遵循同一条边界:

ACC 声明可移植的 Agent-facing 治理意图
运行时兑现过程控制与记录
组织制度决定合规策略
业务系统保留最终 Authority

任何一个组件都不应该因为自己写下了一条“成功”记录,就获得解释整条责任链的垄断地位。

11. 七个常见误区

误区一:有控制台日志就等于有审计

控制台日志可能被轮转、采样或关闭,也通常缺少稳定责任字段。

误区二:有 trace_id 就能证明审批发生过

Trace 能关联调用,不能自动证明其中声明的事实来自可信独立主体。

误区三:审计就是保存完整 Prompt、参数和响应

无边界记录会制造敏感数据副本和新的攻击面。

误区四:运行时记了一条“已审批”就等于审批证据成立

如果运行时同时受益于这条断言,记录仍可能只是自述。

误区五:审计日志可以替代业务授权

事后记录不能让一个本来无权执行的主体获得权限。

误区六:一次业务动作只会产生一条记录

一个 Agent 任务可能经历多轮推理、审批等待、重试、执行和异步回调,需要稳定关联而不是强行压成一行。

误区七:通用契约应该规定所有企业的保留期

保留、删除和法律留置是组织级合规策略,不应由单个 API 作者替整个企业决定。

12. 一份最小审计检查表

在把业务 API 开放给 Agent 前,可以先检查:

  • 能否区分请求者、运行时、可信行动主体、审批者和执行者?
  • 能否识别具体 capability、scope 和业务对象?
  • 能否还原被提交、被审批和最终执行的参数是否一致?
  • 能否区分调用尝试、治理阻断、审批拒绝、业务拒绝和执行失败?
  • 是否有稳定的 job_idtrace_id 关联应用日志、Trace 与审计记录?
  • 敏感参数和响应是否采用最小必要记录与保守脱敏?
  • 审批发生在执行之前这一时序是否可还原?
  • 重试、重复消费和幂等命中是否可区分?
  • 谁能读取、修改和删除审计数据是否有明确控制?
  • 业务系统的最终授权与结果是否被单独记录?
  • 是否明确区分“运行时自述”和“独立可验证证据”?

如果这些问题只能靠临时搜索普通日志回答,系统拥有的是排错材料,还不是稳定的行动责任链。

13. 结语:真正的审计不是“记得很多”,而是“责任能够被还原”

Agent 进入业务系统后,日志数量一定会增加。

模型调用有日志,工具调用有日志,网关有日志,审批有日志,业务系统也有日志。问题从来不是有没有记录,而是这些记录是否在回答同一个责任问题时具有清晰、稳定、可信的语义。

  • 应用日志解释组件为什么这样运行;
  • Trace 还原请求经过了哪些节点;
  • 审计记录说明谁以什么依据造成了什么业务后果;
  • 在高保证场景中,独立证据协议进一步证明关键断言没有被单方伪造。

把它们区分开,并不是增加系统复杂度。

恰恰相反,这是避免团队在事故发生后,拿着海量日志却无法回答最基本问题的前提。

对 Agent 系统而言,最重要的审计能力不是保存每一个 Token。

而是在一个真实后果已经形成之后,组织仍然能够准确回答:

这件事是谁提出、代表谁、经过什么决定、以哪组参数执行,又由谁承担最终授权责任?

这才是审计与普通“留痕”之间真正的边界。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐