模型 / 数据集
Jwuthri/Tracely-ai avatar
Jwuthri/Tracely-ai

Tracely-ai 把生产失败的 trace 冻成回归用例,再用 CI 拦住 PR

Trace-native CI/CD for AI agents — production failures become regression tests that block the PR. Auto-detect, cluster, freeze into hermetic cases, replay in CI for $0.

1,411 个 Star174 个 ForkPythonMIT

秒懂

它是什么?
Tracely 用 OTLP 接收 agent trace,在线评分后把失败聚成 issue,一键冻结成 hermetic 用例,并在 CI 里离线重放。它押注的是「录下来的那次运行就是测试」,代价是你得先有一批真实流量。
适合谁用?
已经在跑真实 agent 流量、并且被同一类失败反复咬过的团队,值得用 docker compose 起一套自托管实例,先接 OTLP 看聚类质量,再决定要不要把 tracely gate 放进 required check。反过来,还在原型期、没有稳定生产流量、或者无法接受把完整 trace(含用户输入和模型输出)落到自建 Postgres、ClickHouse、MinIO 里的团队,不要用它,因为它的全部价值都来自真实失败样本,没有样本时它只是一个空的 trace 浏览器。
能商用吗?
可以。MIT 是宽松许可证:你可以使用、修改并销售基于它的软件,只需保留版权和许可证声明。
还在维护吗?
在维护。仓库最近一次提交在 1 天前。
用什么语言写的?
主要是 Python(依据 GitHub 的语言统计)。

以上回答依据项目的 GitHub 数据(最近同步于 2026年9月15日)和我们的分析,不构成法律意见。

开源项目深度解析

它针对的不是「看不见」,而是「看见了也没用」

agent 出问题这件事,今天的工具链大多能让你看见:面板上有红色的 span,有延迟曲线,有 token 消耗。问题是看见之后没有下一步。修复上线,过两周同样的输入又把同一个 bug 带回来,因为没有任何东西把那一次失败固定住。

Tracely 的出发点写在 README 的第一句里:Production failures become regression tests。它要解决的环节是观测到修复之间的断层。目标读者不是做模型研究的人,而是维护一个已经上线的 agent 服务、需要为它的行为退化负责的工程团队。README 里对现有评测工具的批评很直接:每一款都要求你手工写数据集,坐下来编问题、写理想答案、随产品变化持续维护,而那份数据集只是对「什么可能坏」的猜测。

这个判断有它的道理,也有它的偏向。它默认你已经有生产流量,而且是足够多样的流量。对于刚起步、每天几十次调用的项目,Tracely 手里没有可冻结的样本,它的整条流水线是空转的。

trace 是唯一的事实来源,其余都是派生

Tracely 的数据入口是标准 OTLP。这一点值得单独说:它没有要求你接入某个私有 SDK,也没有要求你改写 agent 的调用方式,trace 按 OpenTelemetry 的格式送进来即可。

进来之后做了一件关键的事:把 agent 语义字段提升为一级索引列。README 点名了四个:agent.id、conversation.id、turn、step。这听起来像细节,实际决定了界面的形态。没有 conversation.id,一堆 span 在存储里是扁平的,你只能按时间排序看流水账;有了它,运行可以按会话线程分组,多轮对话才读得下去。瀑布图按 agent、thinking、skill、generation、hand-off 分层展示,失败的 span 标红并把输入输出摆在旁边。

评估器不是单独的标签页,而是 trace 表上的列。每个评估器可以在会话、运行或 span 三个层级上打分,结论直接写进表格。评分通过 SSE 流式返回,所以你能看到一次运行在界面上被逐条评完。token、成本、延迟、metadata 和滚动的每轮摘要同样是列。这个设计选择暗示了产品的立场:评分是 trace 的属性,不是另一份需要对齐的文档。

失败进来之后会做结构化和语义化的聚类。README 举的数字是 31 条坏运行变成一个带计数的 issue,而不是 31 行要人肉读的记录。每个聚类还能建议「哪个评估器本来能抓住它」。这一步是把噪声压成待办事项,也是后面冻结用例的入口。

fail-to-pass 契约是这套东西里最硬的一环

从失败 trace 到回归用例,中间隔着一个容易被忽略的校验。README 的措辞是:一次点击把失败的 trace 提升为 hermetic 用例,录下的输入、工具调用和 LLM 输出打包成 fixture,并附上一份 fail-to-pass 契约,用例必须在旧代码上失败、在修复后通过,否则这次提升不被信任。

这句话是整个项目里最值得认真对待的部分。它的意思是 Tracely 不接受「随便挑一条 trace 当测试」,因为随机挑出来的用例很可能在修复前后都通过,那种用例放进 CI 只会拖慢流水线并制造虚假的安全感。要求先失败再通过,等于强制这条用例具备区分能力。

代价也随之而来。这个校验必须真的跑一次旧代码和一次新代码,也就是说提升用例这个动作本身需要能执行两版代码,或者至少能对比两次判定。README 没有展开这一步在自托管环境里具体怎么落地,这是文档偏薄的地方,也是你在评估时应该优先去仓库里确认的实现细节。

多轮行为走的是另一条路,README 称之为 scenario:可以是一段脚本化的对话,也可以是一个由红队模型即兴发挥的对抗目标。这里引入了模型调用的不确定性,和 hermetic 用例的确定性是两种性质的东西,README 把它们并列放在同一节里,但没有说明 scenario 在 CI 中是否同样离线重放。

CI 里重放不花模型钱,因为跑的是录下来的 fixture

这是 Tracely 最有说服力的一条:套件在 CI 中针对录制的 fixture 重放,确定性、离线、不需要 API key、没有模型开销。README 在对比表里把成本写成 $0。

机制上说得通。既然一条用例冻结了当时的输入、工具返回和模型输出,重放时就不需要再调用真实模型或真实工具,只需要按记录喂给被测代码,然后检查断言。这也解释了为什么它敢在 PR 上跑:如果每条用例都要打真实 API,成本和抖动都会让 CI 门禁变成没人愿意开的东西。

命令层面,README 给出的入口是 tracely gate。它退出码非零、写一个 commit status、并 upsert 一条 PR 评论。三个动作对应三种读者:退出码给 CI runner,commit status 给仓库的 required check,PR 评论给正在 review 的人。

需要留意的是「$0」的边界。它指的是重放阶段不产生模型费用,不代表整套系统免费。自托管要跑 API、worker、UI、Postgres、ClickHouse、Redis 和 MinIO,这些是实打实的机器成本,只是从按 token 计费变成了按实例计费。对于调用量大的团队这可能是好事,对于调用量小的团队则是固定开销。

自托管的实际形态与许可

README 提供了一键部署到 Railway 的按钮,并写明会起 API、worker、UI、Postgres、ClickHouse、Redis 和 MinIO 七个组件。Python 版本要求是 3.10 及以上,包发布在 PyPI 上,名字是 tracely-ai。

七个组件这个数字本身就是一条信息。ClickHouse 负责 trace 这类高写入量的分析型数据,Postgres 承担业务状态,Redis 做队列或缓存,MinIO 存 fixture 和附件。这是一套典型的重型自托管栈,不是一个 pip install 就能跑起来的库。如果你只想在本地试试,用 Railway 模板最省事;如果你要在自己的 VPC 里跑,得先确认团队里有人愿意维护 ClickHouse 和 MinIO。

许可方面,仓库标注的是 MIT。这意味着修改、商用、闭源分发在许可层面都不设障碍,但 MIT 只处理版权许可,不涉及数据合规。Tracely 存储的是完整的生产 trace,包含用户输入、工具调用参数和模型输出,这些内容落在你自己的 Postgres、ClickHouse 和 MinIO 里,是否允许留存、留存多久、谁能查,取决于你的业务场景和所在地区,这不是许可文本能回答的问题。

维护成本方面,材料里没有给出发布记录(recent releases 为空),也没有版本兼容性说明。这意味着升级路径和破坏性变更的节奏目前无法从前述信息判断,自托管之前应当把这一点当作未知项。

什么时候它是错的工具,以及一个真正的替代路线

Tracely 有一个前提条件:你得有真实的生产失败。没有流量就没有 trace,没有 trace 就没有可冻结的用例,整条流水线保持空转。原型期、内部试用期、或者失败率极低且失败模式单一的 agent,用它得到的收益不足以抵消七个组件的运维负担。

第二个边界是数据。它的核心卖点是把失败的那次运行原样录下来,这必然意味着完整的输入输出要落到你自己的存储里。对于处理敏感数据的 agent,这不是配置问题而是合规问题,需要在上线前想清楚。

第三个边界是评估质量本身。在线评估靠 LLM-as-judge 加结构化检查,聚类也依赖语义相似度。如果评估器判错,错误会一路传导:错误的失败被聚成 issue,被冻结成用例,最后在 CI 里拦住一个本来没问题的 PR。README 提到聚类可以建议「哪个评估器本来能抓住它」,但没有描述评估器本身如何校准。这是需要自己验证的环节。

作为对比,另一条路线是 LangSmith 这类以数据集为中心的评测平台。两者的差别不在功能多少,而在测试的来源。数据集路线要求你先定义「什么算对」,写问题、写期望答案、维护版本;好处是可以在没有生产流量时就开始,期望值由人明确写出,评审时能说清标准。Tracely 的路线反过来:测试从真实失败里长出来,保真度高,但你能测的范围被实际发生过的失败所限定。一个从没在生产里出现过的失败模式,Tracely 不会替你想到。

所以两者不是替代关系。数据集路线覆盖你预见到的边界,trace 路线覆盖你实际撞到的边界。已经有生产流量的团队可以两条都走,但不要指望 Tracely 替你补上「还没发生过的问题」这一类覆盖。

接入顺序与需要先验证的几件事

如果要试,顺序应该是先观测,再门禁。第一步是让 trace 进来,确认 agent.id 和 conversation.id 这两个字段被正确填充,然后在界面上看会话是否按线程分组。如果会话散成扁平 span,说明语义字段没带上,后面的聚类和冻结都会受影响。

第二步是看聚类质量。让在线评估器跑一段时间,检查聚出来的 issue 是不是真的同类问题,以及计数是否符合你的直觉。这一步决定了后面所有环节的信噪比。

第三步才是提升用例,并且一定要确认 fail-to-pass 契约真的被执行了,而不是被跳过。一条在修复前后都通过的用例进了 CI,只会增加流水线时长。

最后才把 tracely gate 接进 CI 并设为 required check。README 说它会退出非零、写 commit status、upsert PR 评论,这三件事在第一次接入时都应该在真实 PR 上看到,而不是只在文档里读到。

告警部分 README 描述得比较简略:一条规则由「何时」和「发生什么」两半组成,条件包括门禁失败、实时会话被评估器判定为坏、出现没人见过的新失败模式、或某个比率越过阈值,动作画在画布上,支持 Slack、邮件和自定义 webhook。画布式的流程编排在小规模下是清晰的,规则变多之后的可读性如何,材料里没有说明。

编辑结论

已经在跑真实 agent 流量、并且被同一类失败反复咬过的团队,值得用 docker compose 起一套自托管实例,先接 OTLP 看聚类质量,再决定要不要把 tracely gate 放进 required check。反过来,还在原型期、没有稳定生产流量、或者无法接受把完整 trace(含用户输入和模型输出)落到自建 Postgres、ClickHouse、MinIO 里的团队,不要用它,因为它的全部价值都来自真实失败样本,没有样本时它只是一个空的 trace 浏览器。上线前必须验证三件事:你的 OTLP 导出器是否带 agent.id 与 conversation.id,否则会话会散成扁平 span;promote 出来的用例是否真的通过 fail-to-pass 契约;以及 CI 里重放时是否完全不需要 API key。

官方来源

  1. Issues
  2. Jwuthri/Tracely-ai on GitHub
  3. License: MIT
  4. Project website
  5. README
社区笔记

社区笔记