主题
0. 方案总览
1. 要解决什么问题?
Claude Code 在本地编程时,你和 AI 的每一轮对话、每一次工具调用、每一个子代理任务,都发生在终端里。默认情况下:
- 你看得到终端输出,但无法结构化回溯
- 出了问题不知道哪次 LLM 调用、哪个 Tool 出了错
- 无法统计 token 用量和成本
- 子代理(Task/Agent)内部的执行过程对主会话不可见
Langfuse 是 LLM 可观测平台,能把这些过程变成可搜索、可分析的 Trace 树。
难点:Claude Code 官方没有内置 Langfuse 集成。
本方案的思路:Claude Code 本来就会把全过程写到 jsonl transcript 文件里——我们旁路读取这个文件,翻译成 Langfuse 能理解的结构再上报。
2. 生活类比:餐厅后厨录像
| 真实世界 | 本方案 |
|---|---|
| 顾客点菜(你输入 prompt) | jsonl 里的 user 行 |
| 厨师做菜(AI 推理) | jsonl 里的 assistant 行 |
| 去冷库取食材(Tool 调用) | tool_use + tool_result |
| 外包帮厨(子代理 Task/Agent) | subagents/agent-*.jsonl |
| 手写流水账(transcript) | ~/.claude/projects/.../xxx.jsonl |
| 会计录入 ERP(Langfuse) | emit_main_turn() |
| 一整单外卖(Trace) | 一轮用户问答 = 1 条 Trace |
核心原则:不改厨房运作方式,只读流水账。
3. 端到端数据流
┌──────────────────────────────────────────────────────────────────┐
│ 1. 数据源:Claude Code session jsonl │
│ ~/.claude/projects/<hash>/<sessionId>.jsonl │
│ + 可选 subagents/agent-<id>.jsonl │
└────────────────────────────┬─────────────────────────────────────┘
▼
┌──────────────────────────────────────────────────────────────────┐
│ 2. 触发:Hook(Stop 事件)或 Watcher(轮询) │
└────────────────────────────┬─────────────────────────────────────┘
▼
┌──────────────────────────────────────────────────────────────────┐
│ 3. 增量读取:read_new_jsonl() │
│ - 基于文件 offset,只读新增行 │
│ - 半行缓冲,处理写入中的不完整 JSON 行 │
└────────────────────────────┬─────────────────────────────────────┘
▼
┌──────────────────────────────────────────────────────────────────┐
│ 4. Turn 切分:build_turns() │
│ user(真人) → 新 Turn │
│ assistant → 追加当前 Turn │
│ tool_result → 归档到当前 Turn,不新开 Turn │
└────────────────────────────┬─────────────────────────────────────┘
▼
┌──────────────────────────────────────────────────────────────────┐
│ 5. 子代理发现:discover_subagent_files() + match_subagent() │
│ Task/Agent 工具调用 → 匹配 agent-*.jsonl → 嵌套上报 │
└────────────────────────────┬─────────────────────────────────────┘
▼
┌──────────────────────────────────────────────────────────────────┐
│ 6. Langfuse 上报:emit_main_turn() / process_turn_streaming() │
│ Trace → Generation(s) + Tool Span(s) + 嵌套 Subagent │
└────────────────────────────┬─────────────────────────────────────┘
▼
┌──────────────────────────────────────────────────────────────────┐
│ 7. 可靠投递:langfuse.flush() 成功后才推进 turn_count/offset │
└──────────────────────────────────────────────────────────────────┘4. Langfuse 概念映射
| Claude Code 概念 | Langfuse 概念 | 说明 |
|---|---|---|
| 整个 coding session | Session | session_id 聚合多轮 Trace |
| 一轮用户问答 | Trace | 名称 Claude Code - Turn N |
| 模型回复(assistant) | Generation | 含 model、token、真实时间戳 |
| 工具调用(Bash/Read/...) | Span | 名称 Tool: <name> |
| 子代理 Task/Agent | 嵌套 Span | 父 Span 下挂 Subagent Turn |
| 子代理内部对话 | 子 Generation/Span | 递归 _emit_turn() |
5. 两种方案怎么选
| 维度 | Hook(langfuse_transcript.py) | Watcher(claude_langfuse_watcher.py) |
|---|---|---|
| 触发方式 | Claude Code Stop 事件 | 独立进程每 1s 轮询 |
| 侵入性 | 需配置 settings.json hooks | 零配置 Claude Code |
| 实时性 | 每轮结束上报 | 默认流式:Turn 开始就建 Trace |
| 适用场景 | 与 CC 深度集成 | CI、旁路监听、不便改 Hook |
| 状态文件 | langfuse_hook_all_agents_state.json | langfuse_watcher_state.json |
默认推荐 Watcher + 流式模式(run_watcher.sh),体验最接近「实时看到 AI 在干什么」。
6. 关键设计原则
6.1 fail-open(绝不影响 Claude Code)
python
# SDK 导入失败 → 静默退出
except Exception:
sys.exit(0)
# 任何未预期异常 → return 0
except Exception:
return 0追踪挂了可以忍,编程助手挂了不行。
6.2 可靠投递(at-least-once)
flush() 成功后才推进 turn_count 和 offset。失败则下次重读、重报,保证顺序不丢 Turn。
6.3 真实时间戳
所有 observation 的 start_time / end_time 来自 jsonl 的 timestamp 字段,UI 不再显示 Latency 0.00s。
6.4 SDK 版本锁定
使用 Langfuse Python SDK v2(langfuse>=2,<3)有状态 API:trace() → generation() → span(),原生支持显式时间戳。
7. 下一步
- 数据源格式 → 1_data_source.md
- 解析流水线 → 2_parse_pipeline.md
- Langfuse 映射细节 → 3_langfuse_emit.md