安装
埋点
每个作用域实际发出的事件:
内部的所有内容都可以省略
session_id 和 agent_id。作用域将身份信息绑定在上下文变量上,每次事件调用都会自动读取,无需在函数间手动传递 id。
三者均支持 async with 和普通 with。
嵌套 agent 会构建树形结构。parent_id 和深度由调用栈自动计算:
作用域如何关闭
agent() 会自动处理异常:
error 事件在
agent_end 之前发出,因为 dashboard 在收到 agent_end 时关闭 span,之后的事件将无法归属。取消不是失败,因此已取消的运行不会污染错误面板。异常始终会被重新抛出——作用域永远不会吞掉异常。
事件方法
六个类别,共十五个方法。大多数成对出现——你发出开启事件,再发出关闭事件,SDK 会测量两者之间的时间跨度。两组人工事件的方向相反。
没有任何框架会发出第二对事件,因此始终需要你自己发出。
示例
一个基于 OpenAI API 的工具调用循环,不使用任何 agent 框架:docs/manual/examples/ 目录下。
线程与异步
上下文变量会自动传播到 asyncio 任务中,但不会传播到新线程——线程启动时上下文为空。propagate() 时,worker 的事件会抛出 TypeError 并提示修复方法,而不是静默地落到没有 session 的状态。这是有意为之:没有 session 的事件在摄入时会被跳过并返回 200,这正是身份层要防止的静默失败。
为没有适配器的框架添加埋点
每个 agent 框架都提供相同的三个切入点。映射它们即可获得完整的追踪——四个内置适配器也仅此而已。1
包裹运行
2
包裹每次工具调用
在框架的工具包装器或中间件中添加。
3
配对每次模型调用
手动埋点与自动埋点可以组合使用。 在手动编写的作用域内运行的适配器会加入该 session 并以该 agent 为父节点,从而形成一棵树而非两棵——当你同时对一个框架手动埋点和使用受支持的框架时非常有用。
为什么没有 AutoGen 适配器
为什么没有 AutoGen 适配器
原因有两点,而上述三个切入点正是对这两点的解答:
autogen-core自 2025 年 9 月起已停止维护。- AG2 没有提供等同于其他框架 hook 的全局注册点,因此要对其埋点就意味着在每个构建位置包裹每个 agent。
深入了解
记录机制的工作原理。入门时无需了解这些内容。各框架的记录内容示例
各框架的记录内容示例
每次记录的结构相同:一个 span 开启,工作嵌套在其中,每个开启事件都有对应的关闭事件。事件对是基本单元。每个关闭事件携带 SDK 从对应开启事件起测量的持续时间。以下是每个框架各一次真实运行的记录——来自 SDK 附带的示例,模型名称已统一。注意单次调用能带回多少信息。节点转换为 hook 对,因此你可以获得每节点的延迟,而不会使 agent 列表过于拥挤。
- LangGraph
- CrewAI
- LlamaIndex
- Pydantic AI
- Custom agents
14 events
session 如何开始和结束
session 如何开始和结束
没有 session 结束事件。 session 不是你去关闭的东西——它是一组共享同一
session_id 的事件。状态由追踪的形态推导:因此,当所有事件对都关闭时,session 即结束。适配器会为你发出
agent_end,并在拆卸时关闭所有仍打开的 span 并标记为未完成——崩溃的运行会以 done 状态结算,留下一个可见的缺口,而不是永久挂起。这就是为什么一个 session 可以跨两次调用。LangGraph 的
interrupt() 会暂停运行,根 span 故意保持打开状态,由后续恢复调用来关闭它。两次调用属于同一个 session。身份标识:session_id、agent_id 及其生成者
身份标识:session_id、agent_id 及其生成者
session_id 和 agent_id 在每个事件方法中都是可选的。省略时,它们从外层作用域解析:TypeError 并提示修复方法,而不是发出一个没有 session 的事件(这类事件在摄入时会被跳过并返回 200)。作用域将身份信息绑定在上下文变量上。这些变量会自动传播到 asyncio 任务中,但不会传播到新线程——需要将 worker 包裹在 failproofai_sdk.propagate() 中。各 id 的生成者
适配器如何解析 session_id
按优先级,第一个匹配生效:- 显式传入的
session_id选项 - 每次调用的元数据
- 外层的
session()作用域 - 框架元数据
- 框架自身的运行 id
保持 agent_id 的低基数
它是每个 dashboard 界面的主要维度,对应一个 LowCardinality(String) 列。每次运行一个值会降低该列的效能,并使过滤下拉菜单中充斥着每次运行的单独条目。适配器会为你维护这个列:真实 id 保存在
fw_agent_id / fw_run_id 上,在那里仍可查询,但不作为维度。事件类型分组——以及各框架记录哪些事件
事件类型分组——以及各框架记录哪些事件
基于上述运行数据,各框架记录的事件:
横线表示该框架没有此概念。
human_pause 和 human_interrupt 描述的是人对 agent 采取操作,没有任何框架会发出这类信号——需要你自己发出。事件对、关联与持续时间
事件对、关联与持续时间
事件从不单独出现。一个开启,一个关闭,关闭事件携带 SDK 从开启事件起测量的持续时间。
关联规则
- 在匹配的完成事件中复用相同的
tool_call_id、hook_id、pause_id或input_id。 - SDK 为
tool_result、hook_completed、agent_resume和human_input计算duration_ms。向这些方法传入duration_ms会抛出ValueError。 duration_ms可以传给model_response,因为只有调用方才知道真实的提供商延迟。它必须是整数——浮点数会在调用处抛出ValueError,因为服务端将该列读取为无符号 32 位整数,其他类型会存储为 NULL。- 关联键按类型和 session 作用域,因此工具调用和 hook 可以安全地共享 id,两个并发 session 也可以复用相同的 id 而不冲突。关联键不按 agent 作用域:在一个 agent 下开启、在另一个 agent 下关闭的事件对仍然能正确关联,这在多 agent 框架中是常见情况。
request_id将model_request与model_response配对。若不传,模型事件按每个 agent 的顺序配对,并发调用会错配。- 跨进程拆分的事件对在下游仍能关联,但 SDK 无法计算其进程内持续时间。
- 待匹配映射最多保存 10,000 个开启事件,满后会驱逐最旧的条目。
包内容,以及 instrument() 如何发现你的框架
包内容,以及 instrument() 如何发现你的框架
安装 如果出错,进程会在 SDK 已导入、适配器看似已安装的情况下运行,但不会发出任何事件。它会记录一条明确说明此情况的警告——因此当某次运行没有记录任何内容时,请先检查日志。
failproofai-sdk 会安装全部内容,包含四个适配器。extras 拉取的是框架,而不是适配器。import failproofai_sdk 承诺零依赖,通过以下测试强制保证:一个在不带 --no-deps 的情况下安装构建 wheel 的测试,以及另一个证明没有框架进入 sys.modules 的测试。自动检测读取
sys.modules 而不是已安装的包列表,因此已安装但从未导入的框架不会被埋点,也不会被代为导入。查看已连接的内容:在没有安装 CrewAI 的机器上调用 设置
instrument("crewai") 不会抛出异常。 它会记录一条警告并返回 (),因此一个缺失的框架不会拖垮同时埋点其他框架的进程。警告中包含底层的 ImportError,该消息会指出确切的安装命令——修复方法在你的日志里,不会被隐藏。FAILPROOFAI_SDK_STRICT=1 可改为抛出异常。该标志只读取一次并缓存,因此请在进程启动前导出它,而不是在运行途中设置。事件如何到达 Cloud
事件如何到达 Cloud
spool 是确保安全的关键:你的 agent 永远不会因网络而阻塞,Cloud 故障只会导致目录增大,而不是事件丢失。每次刷新写入一个批次文件,先写
.tmp,然后 fsync,再原子重命名:.jsonl 文件,因此永远不会读到写入一半的文件。文件名包含时间戳、进程 id 和序列号,因此两个进程在同一毫秒内刷新也不会冲突。队列最多容纳 10,000 个事件,超出后会丢弃最旧的并记录日志。守护进程发送你的批次。它不打开也不重写这些批次。脱敏在守护进程写入自身事件的地方运行——而不是在批次发送的地方。因此,包含 API 密钥的 prompt 或工具参数在到达时仍然包含该密钥。这是有意为之。这些是你自己的埋点调用,在传输过程中改写它们意味着你收到的事件与你发出的不一致。守护进程在发送批次后的毫秒内就会将其删除,因此
ls 命令会与收集器产生竞争,只能看到你实际发出内容的一小部分——与 SDK 什么都没记录的情况无法区分。要确认事件已成功落地,请检查 dashboard。要观察 spool 的填充过程,请先停止守护进程。埋点失败时的处理
埋点失败时的处理
每个回调都运行在一个包装器内,其唯一职责是重新抛出异常,因此你的调用恰好位于一个
try 中,SDK 的所有操作都在其外部进行。默认行为在生产环境中是正确的,在调试时是错误的,因为它只能证明”没有崩溃”。设置
FAILPROOFAI_SDK_STRICT=1 可让被吞掉的失败变得明显。常见问题
span 永远不结束
span 永远不结束
某个开启事件没有对应的关闭事件:
model_request 没有 model_response,或 tool_use 没有 tool_result。请使用作用域,它们能保证即使函数体抛出异常也会发出事件对。如果直接调用事件方法,请使用 try 和 finally。传入 duration_ms 抛出 ValueError
传入 duration_ms 抛出 ValueError
持续时间由对应的开启事件测量,因此在
tool_result、hook_completed、agent_resume 和 human_input 上传入 duration_ms 会被拒绝。在 model_response 上可以接受,因为只有你知道真实的提供商延迟,且必须是整数。来自 worker 线程的事件抛出 TypeError
来自 worker 线程的事件抛出 TypeError
该线程从未继承上下文。请将可调用对象包裹在
failproofai_sdk.propagate() 中。参见线程与异步。额外字段消失或覆盖了其他字段
额外字段消失或覆盖了其他字段
额外字段最后合并,因此与真实字段(如
model 或 outcome)同名的字段会覆盖它,改变存储的列值。请为你的字段加命名空间前缀;适配器使用 fw_ 前缀。agent 过滤器中有数千个条目
agent 过滤器中有数千个条目
agent_id 是低基数维度,而你在其中放入了运行 id。请使用角色或节点名称,将真实 id 放入载荷字段。下一步
工作原理
事件对、id、session 生命周期与事件投递。
读取追踪记录
在刚捕获的 session 中沿因果链路追溯。
框架适配器
LangGraph、CrewAI、LlamaIndex 和 Pydantic AI。

