返回 AIPA 笔记
AIPA Day 102

工具网关 III — 调用审计 + 网关合龙

工具网关 III — 调用审计 + 网关合龙

2026-09-24
call-auditobservabilityappend-only

日期: 2026-09-24 阶段: Phase 4 - 自建 Agent 平台×求职冲刺 标签: #call-audit #observability #append-only

核心问题

Day 100 建了工具注册表(能发现/调用),Day 101 建了鉴权层(谁能调、用谁的凭证)。今天补第三层、也是合规系统的命脉——调用审计:每次工具调用都把 who / tool / 参数 / 结果 / 延迟落盘,让监管者能在事后重建 agent 干了什么。三件齐了,工具网关合龙。

三个问题:

  1. 一条工具调用审计记录要包含什么字段? 直觉记个「调了哪个工具」就行。但 2026 的审计 schema 要能支撑「15-30 次工具链的完整重建」,缺字段就重建不出来。
  2. 审计记录怎么存才算「监管可信」? 直觉是写进数据库。但合规要求 append-only + 哈希链——而且有一条反直觉的硬约束:写日志的 agent 不能读/删自己的日志
  3. 审计层和 P1 已建的 OTel 映射层是什么关系? 不能再造一套 trace 系统——必须复用 day74 的四段 span 与 attributeMap,工具调用是其中 execute_tool 子 span。

关键内容

A. 审计记录 schema:能重建工具链的最小字段集

WebSearch 2026 审计实践(getMaxim/buildmvpfast),事实标准是 JSONL(JSON Lines,一行一条 JSON)——「every observability tool ingests and developers can read without special decoders」。一条工具调用审计记录的字段:

字段来源为什么不能省
caseId会话(=case.id,day74 关联键)监管按案件 ID 拉全链路
runId / step编排器(day29 orchestrator)工具链可能 15-30 步,靠 step 重建顺序
agentId鉴权层(day101 caller)who——谁调的,身份归因
toolName注册表(day100)what——调了哪个工具
args调用入参(可脱敏)重建「用什么参数调的」
decision鉴权层 allow/deny/hitl哪个 guardrail 触发、放行还是拦截
result / isErrorhandler 输出(可脱敏)结果是什么、是否失败(day100 双通道)
latencyMs调用计时性能 + 异常检测(延迟突变=可疑)
tokenCost计量(day89 CostMeter)单位成本归因
timestamp调用时刻when——可重放排序
prevHash / hash哈希链(B 节)防篡改(监管可信)

反直觉洞察①(审计的字段集由「能否重建」倒推,不是由「记多少算多」决定):直觉是「日志记得越全越好」。但真正的设计原则是可重建性——buildmvpfast 2026 口径:schema 要能「reconstruct the execution path when agents chain 15-30 tool calls per run」。这倒逼出两个常被漏掉的字段:step(没有它,15 步乱序日志拼不回执行路径)和 decision(没有它,看不出「这步被 guardrail 拦了还是放行了」)。少记 stepdecision,日志再全也重建不出 agent 的真实行为链。 对 AML,监管问「为什么这笔交易没上报 SAR」,答案就藏在某一步的 decision: deny 里——这是审计的核心价值,不是「记全」。

参数/结果的内容采集要可配置:2026 实践「support disabling content capture per environment while still recording tool name, server, latency, and status」。AML 场景对 PII 更严——args/result 里的客户标识默认脱敏(呼应 day74「prompt/completion 内容 opt-out」纪律),但 toolName/decision/latencyMs 始终全量记。

B. append-only + 哈希链:让审计「可证明未被篡改」

合规审计不能是「可改的数据库行」。2026 技术标准(thebrightbyte/devjournal):append-only 架构 + SHA-256 哈希链。每条记录的 hash = SHA256(prevHash + 本条记录内容),形成链——改任何一条,其后所有 hash 全断,篡改立刻暴露。

audit chain(每条 hash 锚住前一条,改一条断全链)
─────────────────────────────────────────────────
rec[0]: { ...payload, prevHash: GENESIS,    hash: H0 = SHA256(GENESIS + payload0) }
rec[1]: { ...payload, prevHash: H0,         hash: H1 = SHA256(H0 + payload1) }
rec[2]: { ...payload, prevHash: H1,         hash: H2 = SHA256(H1 + payload2) }
                          │
   改 rec[1] 的 payload ──┘ → H1 变 → rec[2].prevHash 对不上 → 验链失败

verify(chain):
  h = GENESIS
  for rec in chain:
    if rec.prevHash != h: return TAMPERED at rec
    if rec.hash != SHA256(h + rec.payload): return TAMPERED at rec
    h = rec.hash
  return OK

反直觉洞察②(写审计的 agent 不能读/删自己的审计——审计系统对它自己也是零信任):直觉是「agent 写日志,自然能读日志」。但合规审计的硬约束恰恰相反——devjournal 2026 口径:「logs... should be restricted so the agent that writes them cannot read or delete them.」原因:如果被 prompt injection 攻陷的 agent 能读/删自己的审计,它第一件事就是抹掉作案记录。审计系统必须假设「被审计者会试图篡改审计」——所以写权限和读/删权限物理分离(append-only:agent 只有 append,没有 read/update/delete)。这和 day101 「per-agent 最小权限」是同一个零信任原则的延伸:连「记录 agent 行为」这件事,都不能信任 agent 本身。 day75 的 immutable trail 已立此规,本日把它落到工具调用粒度。

延迟预算:审计会不会拖慢 agent?2026 基准(Bifrost)「only 11 microseconds of overhead per request at 5,000 RPS」——审计开销可忽略。但本项目跑前端,审计是同步内存追加(无网络),延迟更不是问题。

C. 网关三件合龙:注册 + 鉴权 + 审计的调用流水线

三天的成果在 call() 这一个入口合龙,形成确定性流水线:

PlatformToolRegistry.call(callerAgent, toolName, args, ctx)
   │
   ① [鉴权] auth.resolveCredential(callerAgent, toolName, ctx.userId)   ← day101
   │     deny → 记 audit(decision=deny) → throw FORBIDDEN(不进 handler)
   │     hitl → 挂起等人审(day83)→ 记 audit(decision=hitl)
   │     allow → 拿到 JIT 凭证,继续
   ▼
   ② [入参校验] validate(spec.inputSchema, args)                        ← day100
   │     fail → 记 audit(isError, INVALID_PARAMS) → throw(协议错通道)
   ▼
   ③ [执行] t0=now; raw = handler(args, credential); latency=now-t0
   ▼
   ④ [出参校验] validate(spec.outputSchema, raw)                        ← day100
   │     fail → result.isError=true(业务错通道,不接地坏数据)
   ▼
   ⑤ [审计] audit.append({ caseId, runId, step, agentId=callerAgent,
   │           toolName, args(脱敏), decision, result(脱敏), isError,
   │           latencyMs, tokenCost, timestamp, prevHash, hash })       ← 本日
   │     → 同步映射为 OTel execute_tool 子 span(复用 P1 attributeMap)
   ▼
   返回 ToolResult

审计层不自己造 trace 系统,而是把每条审计记录映射成 day74 四段 span 里的 execute_tool 子 span:

审计字段OTel 映射(复用 attributeMap)命名空间
toolNamegen_ai.tool.nameOTel GenAI semconv
latencyMsspan durationOTel 核心
tokenCostgen_ai.usage.*OTel GenAI semconv
agentIdgen_ai.agent.idOTel GenAI semconv
caseIdgen_ai.conversation.idOTel GenAI semconv
decision / hashaml.tool.decision / aml.audit.hashaml. 私有*(OTel 无对应,自管稳定性)

这正是 day74 反直觉洞察②的应用:最该稳定的合规字段(decision/hash)恰恰是 OTel 没标准化的,放进自管的 aml.* 命名空间,比依赖实验态的 OTel 更稳。AgentCore Observability 的对照:它把工具调用记为 execute_tool span,emit「OpenTelemetry (OTEL)-compatible format」,built-in metrics 含「latency, duration, token usage, error rates」——我的审计字段与之一一对得上,但 decision/hash 是 AML 私有扩展。

各方案对照:

维度本项目审计层AgentCore Observability通用 JSONL 审计
格式内存 JSONL + OTel 映射OTEL → CloudWatchJSONL
防篡改SHA-256 哈希链CloudWatch(不可改存储)append-only + 哈希链
工具调用execute_tool 映射execute_tool span自定义
合规字段aml.* 私有(decision/hash)metadata tagging自定义
写读分离append-only(agent 不可读删)IAM 控制基础设施级 immutable

设计要点/决策表

要点决策理由
schema 设计原则由「能否重建 15-30 步工具链」倒推字段缺 step/decision 则重建不出行为链
内容采集toolName/decision/latency 全量;args/result 默认脱敏PII 合规(呼应 day74 内容 opt-out)
防篡改append-only + SHA-256 哈希链改一条断全链,监管可证明未篡改
写读分离agent 只能 append,不能 read/update/delete假设被审计者会试图篡改审计(零信任)
trace 复用审计映射为 execute_tool span,复用 P1 attributeMap不造第二套 trace;合规字段走 aml.* 私有
网关合龙鉴权→入参校验→执行→出参校验→审计 五步流水线三天成果在 call() 一个入口收口

对本项目的落地

  • 新建 src/agent/platform/gateway/callAudit.ts:导出 AuditRecord(A 节字段)、AuditChainappend(record)hash=SHA256(prevHash+payload)verify() 验链、无 read/delete 方法——写读分离落到 API 层面)、redact(args)(PII 脱敏)。哈希用确定性纯函数(复用或仿 semanticCache.ts 的 djb2 风格,诚实标注「教学用非加密级 hash,生产用真 SHA-256」)。
  • PlatformToolRegistry.call 合龙:把 day100 的注册表 call 改造成 C 节五步流水线——调用 day101 的 auth.resolveCredential(①)、validate 入/出参(②④)、callAudit.append(⑤)。这是 day99 工具网关「注册+鉴权+审计三合一」的最终落地入口。
  • 接 P1 OTel 映射层callAudit 的每条记录经 src/aml/observability/attributeMap.tstoAuditAttributes 映射为 execute_tool span 属性(gen_ai.tool.name + aml.tool.decision/aml.audit.hash)。扩展而非新建 attributeMap——AML_ATTRTOOL_DECISION/AUDIT_HASH 两个常量。与 day74 四段 span 的 execute_tool 子 span 对齐。
  • 诚实标注:v1 审计链是进程内内存数组(无持久化后端、无真实 KMS/CloudWatch);hash 是教学用确定性 hash,非加密级;写读分离体现为「AuditChain 类只暴露 append/verify,不暴露 get/delete」——真实部署需基础设施级 append-only 存储(WORM/对象锁)+ IAM 写读分离。retention(EU AI Act Article 12 ≥6 月)是运营策略,v1 仅记字段不实现归档。

参考资料

  1. AWS — Observe your agent applications on Amazon Bedrock AgentCore Observability(官方文档):trace/debug/monitor,invoke_agentchat/execute_tool span 树;emit「OpenTelemetry (OTEL)-compatible format」→ CloudWatch;built-in metrics「session count, latency, duration, token usage, error rates」;metadata tagging (2026)
  2. buildmvpfast — AI Agent Logging & Audit Trails (2026):JSONL 一行一条;schema 含 run_id/step/tool/input/output/latency_ms/token_cost/timestamp;「reconstruct execution path when agents chain 15-30 tool calls」 (2026)
  3. thebrightbyte — AI Agent Audit Trail Architecture: HIPAA, GDPR, DORA:append-only + SHA-256 哈希链是技术标准;基础设施级 immutability;EU AI Act Article 12 ≥6 月留存 (2026)
  4. devjournal — Security Audit Logging for AI Agents: Making What Your Agent Did Provable:日志须 immutable;「the agent that writes them cannot read or delete them」;写读分离 (2026-05)
  5. getMaxim — AI Agent Audit Logs / MCP Audit Logs:每次工具调用记 timestamp/input/output;guardrail 触发记 allowed/blocked;内容采集 per-environment 可关 (2026)
  6. 本仓库 src/aml/observability/attributeMap.ts(P1 OTel 映射层,AML_ATTR 扩展点)、docs/aipa/day74-audit-trail-otel.md(四段 span + execute_tool 子 span)、docs/aipa/day75-immutable-trail.md(immutable trail)、docs/aipa/day100-tool-registry.md/day101-gateway-auth.md(网关前两件)、src/agent/orchestrator(runId/step 来源) (2026-06)

SOTA 检查 (2026-06-11)

  • 「OTEL execute_tool span + append-only 哈希链」是 2026-06 agent 审计的事实标准:AgentCore Observability、Datadog LLM Observability、Langfuse 都以 OTel GenAI semconv(截至 v1.41 定义 agent/workflow/tool/model span + latency/token 指标)为基础;合规侧 append-only + SHA-256 链是 HIPAA/GDPR/DORA 通用要求。本笔记复用 P1 映射层对齐之。
  • EU AI Act Article 12 的留存与可重建是 2026 的硬约束:高风险系统 ≥6 月留存、2026-08-02 起强制——AML Copilot 正是高风险场景,审计可重建性(反直觉洞察①)直接服务于此。
  • 「写审计的 agent 不能读删审计」是 2026 升温的零信任共识:多家 2026 文章把它列为审计架构铁律,正因为 prompt injection 攻陷的 agent 会试图抹除作案记录(反直觉洞察②)。本项目用 AuditChain 只暴露 append/verify 落地此原则。
  • 过时认知警示:「审计记个 tool name 就够」过时——缺 step/decision 重建不出工具链;「日志写进可改数据库」过时——合规要求 append-only + 哈希链 + 写读分离。
  • 待跟踪:OTel GenAI semconv 从 Development 转 Stable 后 gen_ai.tool.* 属性名是否变(届时只改 attributeMap 一处);EU AI Act Article 12 实施细则对「工具调用审计」的具体字段/格式要求;AgentCore Observability 是否公布其 execute_tool span 的完整属性 schema 以对标 aml.* 私有扩展;P4 后续是否把内存审计链替换为可复刻的 WORM 存储装置。