当你开始在生产环境运行 Agent 工作流,最怕遇到什么?不是它回答错了,而是你完全不知道它为什么错。没有审计日志,Agent 就像一个黑盒:它调了哪个工具、传了什么参数、中间状态如何、最终决策依据是什么——全都不透明。
审计日志(Audit Log)就是为了解决这个黑盒问题。它记录 Agent 工作流中每一次关键动作:包括工具调用、LLM 输入输出、状态跃迁、异常事件等。有了它,你才能事后复盘、调试异常、满足合规审计要求。
审计日志应该记录什么?
不是所有数据都值得记。核心记录项分为五类:
- 请求与响应:每次 LLM 调用的完整 prompt 和 completion,包括 temperature、max_tokens 等参数。丢失这个,你就无法复现任何一次推理。
- 工具调用轨迹:Agent 调用的函数名、传入参数、返回结果、耗时。很多错误发生在工具返回的数据格式不符预期时。
- 状态变更:工作流中关键变量的值变化,例如用户意图、已收集信息、中间决策结果。
- 异常与重试:网络超时、LLM 返回格式错误、工具抛出异常——这些是调试的重头戏。
- 元数据:请求 ID、时间戳、版本号、Agent 实例 ID。用于关联多次交互和横向排查。
实际项目中,我见过团队只记录 LLM 对话,完全忽略工具调用,结果一次 API 限流导致整条工作流中断,查了两天才定位到——就是因为工具调用日志缺失。

搭建步骤:从日志结构到检索
1. 定义日志结构
采用扁平化的 JSON 格式,每个事件一条记录。关键字段:event_id, trace_id(用于关联同一工作流)、agent_id, event_type(如 llm_call、tool_call、state_change、error)、timestamp、payload。
避免嵌套过深,否则查询性能会急剧下降。推荐使用列式存储(如 ClickHouse)或结构化日志服务(如 Seq、Loki)。
2. 埋点策略
不要试图记录所有变量——这会击穿存储成本,也难以分析。优先记录:
- 每次 LLM 调用的输入输出(可开启 truncation 限制大文本)
- 每次工具调用的参数和返回结果
- 工作流开始与结束(记录最终输出和耗时)
- 任何异常或重试事件
埋点代码通常用装饰器模式或 AOP 插入 Agent 框架。以 LangChain 为例,可以在 CallbackHandler 中 on_llm_start、on_tool_start 等钩子里写入日志。
3. 存储与保留策略
审计日志不能只存在内存里,停机就丢了。至少写入本地磁盘(每天轮转压缩),可选同步到 S3 或 ES。保留期限根据合规要求(一般 90-180 天),老旧数据归档至冷存储。
4. 检索与可视化
日志只有能查才有意义。搭建一个简单的查询界面,支持按 trace_id、时间范围、事件类型、agent_id 过滤。如果能用自然语言查询(如“上周三工作流 X 为什么失败”)就更好了。

最容易踩的坑
我见过最多的问题是 日志阻塞工作流。很多人同步写入远程数据库,网络拥堵时 Agent 响应变慢甚至超时。解决方法是异步写入:本地先写内存缓冲队列,由后台线程批量 flush。如果队列写满,宁可丢日志也不要影响主流程——丢日志至少还能跑,工作流挂掉什么都查不到。
第二个坑是 日志过多导致存储爆炸。特别是每条 LLM 调用都记录完整对话,一天就能上 GB。解决方案:只保留最近 X 天的原始日志,老旧数据聚合摘要后丢弃。另外,只记录关键 payload,去掉冗长的系统 prompt。
第三个坑是 日志没有 trace_id。如果没有关联上下文,几千条日志散落在文件里,你根本不知道哪些属于同一次工作流。Trace ID 必须在工作流启动时生成,并贯穿所有子调用。
真实场景:一次失败的 Tool 调用
假设有一个 Agent 负责查询用户订单。它调用了 get_order(id) 工具,但服务端返回了 500 错误。审计日志应该记录:
- 事件类型:
tool_call_start,参数:{order_id: "123"} - 事件类型:
tool_call_error,返回:{status: 500, error: "Internal Server Error"} - 然后 Agent 进行重试(或换策略),再记录
tool_call_retry和tool_call_end。
没有审计日志,这个 500 错误只会被 LLM 悄无声息地吞掉,用户看到的是“查询失败”,而你作为开发者完全不知道是 Agent 代码问题还是后端接口问题。
备用方案:当标准方案失败时
如果团队资源有限,无法搭建独立日志系统,可以降级利用 LLM 本身来“审计”。具体做法是:在每一步 action 后,让 Agent 自己以自然语言总结当前状态,写入一个临时变量。工作流结束时,要求 Agent 输出完整日志。虽然不可靠(Agent 可能遗漏或编造),但聊胜于无。
另一个更成熟的降级方案是复用已有的业务日志 + 请求 ID:将每次 Agent 交互的 trace_id 写入业务数据库的请求日志表,由后端服务自己记录调用链路。缺点是侵入性强,但不需要额外基建。
最后
审计日志不是可选项。当你的 Agent 工作流开始处理真实用户请求时,它就是唯一的排障窗口。先搭好日志再上线,否则迟早要花几倍时间去返工。

暂无评论,快来发表你的见解吧