用 Litefuse 追踪 Pi

Pi 是一个极简的终端编码 Agent。本集成是一个 Pi 扩展,安装在 ~/.pi/agent/extensions/litefuse/ —— 单个 TypeScript 文件,零 npm 依赖。Pi 在进程内加载它,扩展订阅生命周期事件(agent_startbefore_provider_requestmessage_endtool_execution_start/endagent_end),为每个用户回合生成一条 Litefuse trace,使用真实的逐事件时间戳。

Span 以裸 OTLP/HTTP JSON 形式、用 Node 内置 fetch 直接发送 —— 没有 SDK、没有 node_modules、不需要构建步骤(Pi 直接加载 TypeScript)。

给 AI —— 自动安装

如果你正在和 Pi 对话,把下面这段 prompt 粘贴过去,Agent 会端到端完成整个安装:

Read https://litefuse.ai/SKILL.md and follow the instructions to install and configure Litefuse for Pi.

skill 会向你索取 Litefuse 的 API Key(如果还没有账号,会引导你注册),然后在本地完成全部配置。如果你想手工一步步配置,请继续往下看。

会捕获哪些数据

数据捕获方式备注
用户 prompttrace input图片 block 数量记入 metadata
每次 LLM API 调用generation observationplan (n tools) #N / response / think #N,按模型这一步做了什么命名
thinking / text / toolCall blockgeneration output保留块结构,包含 reasoning 文本
首 token 时间generation 的 completion_start_time来自第一个流式 delta —— 驱动 Litefuse 的 TTFT 指标
采样参数generation 的 model_parameterstemperature / max_tokens / top_p,provider payload 携带时采集
token 用量(inputoutputcache_read_input_tokenscache_creation_input_tokensgeneration 的 usage_detailsAnthropic 风格 key,Litefuse 成本映射可用
模型名 + provider 成本generation 的 model + cost_details有 Pi 自带成本数据就用,否则 Litefuse 按价格表计算
工具执行tool observationtool: bash (grep) #Ntool: read (index.ts) #N —— 名字带关键信息,完整参数在 input
子 agent(single / parallel / chain)子树tool (n subagents) #Nsubagent 容器 → 子 agent 自己的 plan/tool/response 步骤;子成本汇入父 trace
工具错误tool observation,level=ERROR带 status_message 预览
LLM 错误 / 中止generation level=ERROR / WARNING来自 stopReason,metadata 带 HTTP 状态码与 request id
上下文压缩event observation解释下一次调用 input token 骤降
上下文窗口水位trace metadata agent_context_usage回合结束时的 tokens / window / percent
会话分组trace 的 session_idPi 会话 UUID;续接会话 Turn 编号接着数
用户身份trace 的 user_id$LITEFUSE_USER_ID,回退到系统用户名
标签trace 的 tagspi-agent + model:<name>

Trace 结构

一个委派了子 agent 的典型回合产生的 trace 形如:

Pi Agent — Turn 1                        (AGENT root —— 真实回合时长)
├── plan (1 tool) #1                     (generation,usage_details,真实延迟)
├── tool: bash (grep) #2                 (tool)
├── plan (1 tool) #3                     (generation)
├── tool (1 subagent) #4                 (tool —— 父进程视角的委派)
│   └── subagent                         (AGENT 容器 —— 子 pi 进程)
│       ├── plan (1 tool) #1             (容器内局部编号)
│       ├── tool: ls (demo-src) #2
│       └── subagent response            (generation —— 子 agent 的最终回答)
└── response                             (generation —— 最终回答,带自己的 usage)

设计说明:

  • Generation 按”模型这一步做了什么”命名,而不是用哪个模型(plan (2 tools)responsethink)—— 模型名是 generation 的 model 属性,换模型不会破坏看板。名字在消息完整后一次定型,绝不中途改名。
  • response 就是最后一次 LLM 调用本身。 Pi 的 agent 循环在 assistant 消息不含工具调用时结束 —— 那条消息就是最终回答,因此它携带真实的 token 用量与延迟,不再额外发一条收尾 observation。
  • 每个 agent 容器一个步骤计数器#N 由 generation 和 tool 按时间顺序共用。tool 的 metadata agent_plan_step 指向发起它的 plan 的 agent_step_index —— join 条件是 tool.agent_plan_step == generation.agent_step_index。每个子 agent 容器从 #1 重新计数,层级由树结构表达。
  • 子 agent 上下文经环境变量传播subagent 工具开始执行时,扩展导出 LITEFUSE_TRACEPARENT=00-<traceId>-<toolSpanId>-01。spawn 出的子 Pi 进程继承该变量,启动时检测到即加入父 trace 形成子树,而不是各开各的 trace —— 嵌套委派递归成立。工具 span 与容器的时长差还顺带暴露了委派的真实开销(进程启动、运行时加载)。
  • 每个 span 恰好发送一次、在它结束时 —— OTel 的 span 不可变;没有临时发送、没有 upsert。trace header(name / session / user / input / tags)随每个 span 携带,所以第一个 observation(通常是几秒内完成的 plan #1)一完成,trace 就出现在 Litefuse 里 —— 长回合执行中即可见。
  • 真实 wall-clock 时间戳,来自每个事件触发的时刻 —— 时间线反映真实的 LLM 延迟、工具耗时与间隔。
  • 打平的 agent_* metadata:所有 Pi 专属字段都是带统一前缀的顶层 metadata key(agent_step_indexagent_plan_stepagent_duration_ms……)—— 同一个看板过滤条件对所有 Litefuse agent 集成通用。稀疏存储:没有值的字段完全不出现,不用 null 占位。
  • Fail-open:任何意外错误写入 ~/.pi/agent/litefuse.log 后静默吞掉 —— 扩展永不阻塞 Pi 的主循环。不可达的目标直接跳过。

快速开始

前置条件

  • 已安装 Pi —— 用 pi --version 检查。
  • https://litefuse.cloud 创建一个 Litefuse 项目,拿到 public + secret key。

没有其他依赖:扩展是只用 Node 内置模块的单文件,Pi 直接加载 TypeScript。

下载扩展

mkdir -p ~/.pi/agent/extensions/litefuse
curl -fsSL https://litefuse.ai/integrations/pi/index.ts \
  -o ~/.pi/agent/extensions/litefuse/index.ts

源码也在同一 URL 上 —— 部署前可以先读一遍。

配置凭据

创建 ~/.pi/agent/litefuse-targets.json(不需要改 shell 配置文件):

cat > ~/.pi/agent/litefuse-targets.json <<'EOF'
[
  {
    "publicKey": "pk-lf-xxx",
    "secretKey": "sk-lf-xxx",
    "baseUrl": "https://litefuse.cloud",
    "environment": "production"
  }
]
EOF
chmod 600 ~/.pi/agent/litefuse-targets.json

把占位值替换成真实值。也可以改用环境变量 LITEFUSE_PUBLIC_KEY / LITEFUSE_SECRET_KEY / LITEFUSE_BASE_URL(同名 LANGFUSE_* 作为 fallback 也接受)。targets 文件支持多个目标 —— 同一份 trace 会写入每一个 Litefuse 实例,各目标可配置独立的 environment

验证

PI_LITEFUSE_DEBUG=true pi --no-session -p "Reply with exactly: ok"
tail -3 ~/.pi/agent/litefuse.log
# 期望: "extension loaded, 1 target(s): https://litefuse.cloud"
#     + "turn complete session=... turn=1 api_calls=1 tool_calls=0"

打开 https://litefuse.cloud —— 最新一条 trace 名为 Pi Agent — Turn 1,结构如上所示。

正在运行的 Pi 交互会话在启动时加载扩展:在 Pi 里执行 /reload(或新开会话)才会生效。

环境变量

LITEFUSE_* 变量优先;同名 LANGFUSE_* 变量作为生态兼容的 fallback 也接受。

变量必填说明
LITEFUSE_PUBLIC_KEY是*Litefuse 项目 public key(pk-lf-...)。
LITEFUSE_SECRET_KEY是*Litefuse 项目 secret key(sk-lf-...)。
LITEFUSE_BASE_URL默认 https://litefuse.cloud。别名 LITEFUSE_HOST
LITEFUSE_TRACING_ENVIRONMENTenv 配置目标的 trace environment。默认 production
LITEFUSE_USER_ID覆盖 trace 的 user_id。回退到系统用户名。
LITEFUSE_EXTRA_TARGETS额外目标的 JSON 数组(与 targets 文件同构)。
PI_LITEFUSE_DEBUG设为 "true" 启用 ~/.pi/agent/litefuse.log 的详细日志。
PI_LITEFUSE_MAX_CHARSspan 输入/输出的截断阈值(字符数)。默认 1000000(约 1MB 文本)。
LITEFUSE_TRACEPARENT扩展为子 agent 进程自动设置(W3C 格式)。不要手工设置。

* 仅在不使用 ~/.pi/agent/litefuse-targets.json 时必填。targets 文件里的凭据无需任何环境变量即可工作。

Trace metadata 参考

所有 Pi 专属字段都是agent_ 前缀的打平顶层 metadata key —— 所有 Litefuse agent 集成共用同一套 key,同样的过滤器和看板处处可用。Litefuse 标准字段(sessionIduserIdtags)通过 OTel 属性保持在 trace 级。稀疏存储:没有值的字段完全不出现,绝不用 null

Trace 级:

  • agent_turn_numberagent_session_idagent_cwdagent_modelagent_provider
  • agent_api_callsagent_tool_callsagent_stepsagent_message_countagent_duration_ms —— 回合统计
  • agent_context_usage —— 回合结束时的 {tokens, contextWindow, percent}
  • agent_thinking_level —— 用户调整过时出现
  • agent_image_blocksagent_prompt_truncatedagent_prompt_orig_len —— 适用时出现

Generation observation:

  • agent_step_index —— 名字里的 #N
  • agent_provideragent_apiagent_stop_reason
  • agent_api_duration_msagent_time_to_first_token_ms
  • agent_http_statusagent_request_idagent_retry_after —— 来自 provider 的 HTTP 响应
  • agent_tool_call_countagent_thinking_chars
  • agent_input_truncatedagent_output_truncatedagent_output_orig_len —— 仅截断时出现

Tool observation:

  • agent_tool_nameagent_tool_call_id
  • agent_step_index —— 工具自己的 #N
  • agent_plan_step —— 发起本工具的 plan generation 的 agent_step_index
  • agent_duration_msagent_is_error
  • agent_details —— Pi 的结构化工具结果细节,≤ 2 KB 时以对象内嵌;过大则整体省略并记 agent_details_omitted_len(subagent 的 details 内嵌完整子历史,子树已完整保存)

Subagent 容器:

  • agent_subagent: true,外加与 trace 级相同的单次运行统计(agent_api_callsagent_tool_callsagent_stepsagent_duration_ms

工作原理

扩展订阅 Pi 的进程内扩展事件:

事件用途
session_start会话 id;从已有 user 消息数恢复 Turn 编号
before_agent_start捕获用户 prompt
agent_start开启回合:新 traceId、root span id、步骤计数器
before_provider_requestgeneration 开始时间、模型、请求 messages、采样参数
message_update首个流式 token → completion_start_time(TTFT)
after_provider_responseHTTP 状态码、request id、retry-after 头
message_end发出 generation span:按内容命名,带 usage + 成本
tool_execution_start / tool_execution_endtool span;导出 subagent traceparent
session_compact上下文压缩 event observation
agent_end发出 root span:trace output、回合统计、上下文水位;flush
session_shutdown防御性关闭被中断的回合;最终 flush

每个完成的 span 立即以 OTLP/HTTP JSON POST 到 <baseUrl>/api/public/otel/v1/traces(Basic auth)—— fire-and-forget 加超时,回合结束时 flush。每个 span 只发送一次;执行中的步骤在完成时变为可见。

对于子 agent,Pi 的 subagent 扩展会 spawn 子 pi 进程。父进程的 Litefuse 扩展在 subagent 工具运行期间导出 LITEFUSE_TRACEPARENT;子进程的扩展(同一个文件,由子进程加载)检测到它后,抑制自己的 trace header,并把容器 span 挂在 subagent 工具 span 下。嵌套委派按同样方式递归。一个已知暂态:live 视图中子 agent 的步骤可能先于其容器出现(容器在子进程结束时才发送)—— 回合结束后树完整且嵌套正确。

故障排查

Litefuse 中没有出现 trace。 查看扩展日志:

tail -20 ~/.pi/agent/litefuse.log

日志为空说明扩展没加载 —— 确认文件在 ~/.pi/agent/extensions/litefuse/index.ts,且启动 Pi 时没有加 --no-extensions。文件存在但没有 extension loaded 行?扩展没找到凭据:检查 ~/.pi/agent/litefuse-targets.jsonLITEFUSE_* 环境变量。

改完凭据后 trace 停了。 Pi 交互会话在启动时加载扩展 —— 在 Pi 里执行 /reload 或新开会话。

工具调用有了但 subagent 子树缺失。 子进程连不上 Litefuse,或没有运行本扩展。确认 subagent spawn 的是普通 pi(默认即是),并在 ~/.pi/agent/litefuse.log 里找子进程的日志行(session=ephemeral)。

totalCost 是 0。 你的 Litefuse 项目没有该模型的价格条目(Pi 的自定义模型 id 不会匹配默认价格表)。在 Litefuse UI 的 Settings → Models 里添加,或依赖 Pi 自带的成本数据 —— 模型在 Pi 注册表中时扩展会以 cost_details 转发。

启用调试日志:

PI_LITEFUSE_DEBUG=true pi
# 每次发送 / 跳过 / 错误都会写入 ~/.pi/agent/litefuse.log

本地 + 云端双写:litefuse-targets.json 里加第二个条目(例如本地自托管实例配 "environment": "test")。不可达的目标会被静默跳过,永不阻塞 Pi。

资源

这个页面对你有帮助吗?