
审计员要的那份证据审计员在银行里问的不是 Agent 跑没跑而是记录能不能被改。一份普通日志满足不了这个问题因为它可以随时被覆盖。SOC2 审计要的是 tamper-evident也就是动过手就看得出来。Tracelane 把自己定位成 AI Agent 的飞行记录器。它蹲在 Agent 和模型供应商之间所有流量都过它这一道。每条事件按租户串成哈希链再批量锚定到一份公开透明日志。验真可以用 tlane verify 完全离线重跑不回调 Tracelane。这正是审计员愿意签字的那一类证据。它的作者是 Sanjeev一个人做了六个多月。他之前在 BFSI 干过见过审计员要 tamper-evident 而不是日志。所以这条产品的骨头是从证据可信往回倒推工程。这一点决定了它和 LiteLLM、Portkey 这类网关的取舍不同。后者优先做路由和成本它优先做可验真。Apache 2.0 开源仓库在 github.com/tracelane/tracelane。下面拆它怎么把离线可验真做成一个能落地的工程。重点不是功能清单而是几处能看出取舍的设计。先看账本本身再看它老实写下的边界。然后是护栏的观察优先和 2 毫秒热路径。最后是一段可跑的验真代码。合规场景里日志和证据是两个词。日志告诉你发生了什么但不保证没被改。证据要求任何篡改都能被发现哪怕改的人是管理员。Tracelane 的账本设计就是冲着这条来的。它不依赖你信任它的服务器信任建立在哈希链上。这是密码学担保不是服务条款担保。所以哪怕你自托管验真逻辑也跑在你自己机器上。这一点是它和托管观测平台最硬的区别。后者要你相信它不会改后台数据这里不用信。代价是你得自己管好导出的链文件。哈希链与透明日志的咬合账本的核心是前一条的哈希喂给下一条。这样任意一处改动会让后面所有哈希对不上。这是区块链以外很老的技术叫哈希链。Tracelane 按租户分链每个租户有自己的序号序列。事件落库时算哈希存进 ClickHouse 的 audit_log 表。托管版把权威账本放在 Postgres再复制一份到 ClickHouse。这是为了兼顾事务一致性和分析查询的吞吐。但光有哈希链还不够因为它只能证明内部没断。一个能改库的管理员仍可以在重写时把整条链重算。要防这一手得把链头定期锚定到外部不可改的地方。这就是批量锚定到公开透明日志的那一步。锚定后哪怕管理员重算内部链也对不上外部锚点。这是从 Merkle tree 到 Certificate Transparency 的老套路。Tracelane 把它接到 Agent 轨迹上是工程拼装不是新密码学。验真器叫 tlane verify从导出文件就能重算整条链。它不向 Tracelane 发任何请求纯本地校验。这是审计员能把它带走、离线复核的关键。最妙的工程是验真器被实现了三遍。Rust 一份Python 一份TypeScript 一份。三份都对着同一组 8 个一致性测试向量跑。这 8 个向量里有故意伪造的也有边界数值的。CI 里跑 10 个 Rust、14 个 Python、19 个 TypeScript 测试。还有一个 round-trip 任务断言三份实现结果一致。这种多语言对照防的是单份实现的 bug 骗过审计。因为验真器是审计员唯一信任的代码它不能有暗坑。仓库 evals 目录里另有 20 个一致性评测。10 个容错、7 个网关正确性加 ingest-schema、脱敏、注入各一。作者还老实说有些内部测试针对私有 ADR没放进仓库。test 脚本会直接告诉你这一点而不是假装全绿。这种诚实本身就是审计可信度的一部分。账本的强度等于它愿意公开的弱点。下一节就看它公开了哪些边界。老实写下的边界自托管的人最该先读的一段是账本的边界。自托管不带 Postgres 控制面只有 ClickHouse 里的链。它能在一次网关生命周期内验真这是测过的。作者实测四次聊天请求产出八条链接行零断链。但重启之后链头本来是从 Postgres 控制面恢复的。自托管没有 Postgres所以重启后序号从 genesis 重新开始。结果会出现重复的 seq 值离线验真器跨不过这个边界。换句话说自托管的账本是按段可验真不是跨重启连续可验真。要跨重启一条连续可验真的链今天只能上 Tracelane Cloud。作者把这条写成正文而不是等你自己在验真器输出里发现。这是这种产品最值钱的态度。还有几条同样写在前面的边界。它没有 SOC2 报告没有可配置的数据驻留。没有 HIPAA 或 BAA没有文档化的 SAML 单点登录。没有合同级 SLA也没有文档化的 Slack、PagerDuty 告警集成。这些都列为还没有不是被你挖出来的缺口。预测层的几个能力也老实标了今天不开火。浏览器卡死循环预测、A2UI 目录一致性门禁都还没触发。因为它们要的字段/v1/chat/completions 请求里根本不带。蒸馏出来的 SLM 判官也没启用因为没有训练好的模型随仓库发。所以这些预测护栏今天对 LLM 流量零影响。作者把没开火和为什么没开火一起讲清楚。这避免了你把它当防御层用结果发现它根本没拦。crates/policy 里有个 Cedar 策略引擎的脚手架V1 没接上。这也是写明的不是藏着的。仓库本身有个透明声明它是从另一棵开发树发布出来的。main 上的提交是压缩发布没有分支保护没有可审查的评审历史。作者的忠告是判代码和发版别判提交图。对一个要审计可信的产品这种坦白反而加分。护栏为什么先观察再说话Tracelane 的护栏默认是观察优先不是拦截优先。成本、schema、提示注入这三条护栏都在请求里跑。但它们的默认动作是记录加标记而不是把请求挡回去。原因是误报拦截会直接打断一次合法的 Agent 运行。对一个跑长任务的 Agent一次误杀可能毁掉几十步。所以先观察、积累、回头复盘比先拦更稳。这是和安全网关必须拦很不一样的设计观。它的潜台词是护栏是给运维看的信号不是死锁。需要拦的时候你自己加规则它把数据备好。两条最有意思的护栏是 MCP 工具定义锁定和致命三角检测。这两条免费给所有档位包括 OSS 自托管。工具定义锁定把你批准过的工具定义算一个哈希存下。运行时拿实时定义和这个哈希比不一致就标记。防的是工具定义被悄悄改了Agent 还在用旧授权跑。这种漂移在 MCP 生态里是真实风险不是理论风险。致命三角检测盯的是三个条件同时出现。非可信输入加上私有数据再加上外传路径。三个凑齐才标记为高风险组合。单看任何一个都不一定有问题凑齐才是问题。这比单条规则拦更准因为它看的是组合。这两条护栏也都遵守观察优先先标不先拦。ML 集成在路线图上今天跑的是启发式。启发式的好处是可解释、可审计、没有模型幻觉。坏处是抓不到复杂模式所以才要补 ML。但作者没把没训好的模型塞进来充数。这和上一节的没开火就说没开火是一致的态度。PII 脱敏器接在审计和护栏两条路径上。所以落库的轨迹里敏感字段在写盘前就脱了。这降低了账本本身成为合规负债的风险。crates/policy 里还有个 Cedar 策略引擎脚手架。V1 没接留给你按自己的策略补。2 毫秒热路径是怎么省出来的可验真和护栏都得过一道关网关本身不能慢。加一层代理就意味着每条请求多一段延迟。Tracelane 把热路径用 Rust 写框架是 Axum 加 tokio。它做 BYOK 路由把请求转发到你带 key 的191家供应商。0% 加价你的 key 就是你的成本。在 LiteLLM 的 AIGatewayBench 上实测加了2 毫秒 p50。p95 是 4 毫秒p99 是 5 毫秒采集开着。测试条件是 4 vCPU跑了两轮公平对比。同场测的 LiteLLM Python 代理是 14 到 15 毫秒。Portkey 同场是 3 到 4 毫秒。Langfuse 和 LangSmith 没有网关不进这张表。Rust 热路径是它压低延迟的主因不是魔法。采集默认全保真不需要你去关采样。这是它和很多观测平台不一样的地方。后者默认采样你得手动调高才看得到全貌。它反过来默认全收再加单条轨迹上限兜底。上限是一万 spans 或 64 兆环境变量可调。超出只裁这一条轨迹不伤你其余的轨迹。这防的是一个失控 Agent 撑爆你的存储。采集后走 NATS JetStream 传给 ingest worker。worker 批量写 ClickHouse 热层。冷层是 Cloudflare R2还在路线图上。托管的权威账本在 Postgres再复制到 ClickHouse。自托管只有 ClickHouse 链上一节讲过它的边界。架构图很直白Agent 到网关网关到 NATSNATS 到 ingest。ingest 分两路写 ClickHouse 和将来的 R2。没有仪表盘容器自托管是 headless 的。Web UI 今天只有托管版有。这是它在自托管完整度上最显眼的一刀。对照表能看出它和同类各自的取舍维度TracelaneLiteLLMPortkeyLangfuse网关 p50 开销2 ms部分(14-15 ms)3-4 ms无网关Rust 热路径有无无无BYOK 零加价有有有无防篡改账本离线验真有无无无MCP traces 服务有无无无自托管单 compose有有有有许可证Apache 2.0MITMITMIT这张表里 Tracelane 唯一独占的是离线可验真的账本。LiteLLM 路由和成本更强它可验真更强。选哪个取决于你要解决的是哪一头的问题。它不是要替掉谁而是补上一块别人没有的板。一段可跑的验真说再多不如跑一次给一段能直接跑的。先是托管的接法三行就能让 Agent 发 spans。init 指定网关地址和 keykey 要有 ingest 权限。然后包一下你的 Anthropic 客户端就行。它不 monkey-patch得显式包每个客户端。这点有人嫌烦但它换来了没有隐式副作用。TypeScript 端是对称的 instrumentOpenAI。# 托管三行让 Agent 发 OTel spans export TRACELANE_API_KEYtlane_... export TRACELANE_GATEWAY_URLhttps://gateway.tracelane.devfrom tracelane import init, instrument_anthropic from anthropic import Anthropic init(endpointhttps://gateway.tracelane.dev, api_keytlane_...) client Anthropic() instrument_anthropic(client) # 现在 messages.create() 会向网关发出 spans# 自托管一把起整套再离线验真 docker compose -f infra/self-host/docker-compose.yml up -d set -a; source infra/self-host/.env; set a export TRACELANE_GATEWAY_URLhttp://localhost:8080 export TRACELANE_API_KEY$TRACELANE_MASTER_KEY tlane verify # 从导出的链文件本地重算不回调任何远端自托管的话compose 一把起整套。infra/self-host/docker-compose.yml up 就行。两个 key 必须在 .env 里设好。一个是 TRACELANE_MASTER_KEY用 openssl rand 生成。一个是供应商 key比如 ANTHROPIC_API_KEY。不设供应商 key网关能起但每个请求都 401。还有个坑.env 里设的变量不会自动进 shell。得 set -a 加 source 加 set a 才能带进去。否则你以为设了其实 shell 里是空第一个请求就 401。这是文档里专门写出来的坑照抄能少踩。网关在 :8080把 TRACELANE_GATEWAY_URL 指过去。验真用 tlane verify喂它导出的链文件。它本地重算不回调任何远端。网关是 OpenAI 路径兼容的打 /v1/chat/completions。请求体用 Anthropic 的工具 schema。两种工具形状它都接归一成一个内部表示不改写请求。从 LiteLLM 迁移有现成导入器一行转配置。从 Helicone 迁移改 base URL 和 auth 头不用重导轨迹。发版是 cosign 签的keyless OIDC可验 provenance。每个版本带 CycloneDX SBOMCI 用 Grype 加 Syft 加 OSV-Scanner。作者说判这东西看代码和发版别看提交图。这是给审计员的最后一句忠告。