Claude Code の動きを Hooks で Langfuse に送り、ツール呼び出しやサブエージェントを追う
Claude Code の OpenTelemetry 出力はメトリクスとログだけで、トレース(span)は出さない。一方 Langfuse はトレースしか受けない。そこで全 hook イベントに同じシェルスクリプトを登録し、Langfuse の Ingestion API に直接送ると、1つの指示ごとのツール呼び出し・サブエージェント・LLM の応答までを1画面で追える。
どんな場面で使う?
- どの指示でどのツールが何回呼ばれ、どこで失敗したかを振り返りたいとき
- 自作エージェントの設計の参考に、Claude Code の内部の動き(サブエージェントの入出力など)を観察したいとき
手順
- Langfuse を用意する(OSS なのでセルフホストも可)
settings.jsonの hooks で、SessionStart・UserPromptSubmit・PreToolUse・PostToolUse・PostToolUseFailure・SubagentStart・SubagentStop・Stop・PreCompact・Notificationなどに、同じスクリプトを登録する
json
{ "hooks": {
"PreToolUse": [{ "matcher": "", "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/scripts/langfuse-logger.sh", "timeout": 10 }] }],
"PostToolUse": [{ "matcher": "", "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/scripts/langfuse-logger.sh", "timeout": 10 }] }],
"Stop": [{ "matcher": "", "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/scripts/langfuse-logger.sh", "timeout": 10 }] }]
} }- スクリプト側で Claude Code の概念を Langfuse の型に対応させる
| Claude Code | Langfuse |
|---|---|
|session_id| Session |
| ユーザーの1指示(UserPromptSubmit) | Trace({session_id}-turn-{n}) |
| ツール実行(Pre→Post、tool_use_idで対応付け) | Tool |
| サブエージェント(SubagentStart→Stop) | 親 Span(中のツールの親にする) |
| LLM 呼び出し | Generation(後述) |
| 通知・圧縮 | Event | - LLM の応答は Stop のときに transcript から拾う。hooks には LLM の入出力が来ないので、
transcript_pathの JSONL のうち、その指示以降に増えた行からtype: "assistant"を読み、stop_reason(null=途中経過、tool_use、end_turn=最終回答)ごとに Generation にする - 状態(今のトレースID、ターン番号など)は
/tmp/claude-langfuse/{session_id}/にファイルで持ち、イベント間で共有する
注意点
- 並列でツールが呼ばれるので、Pre と Post はツール名ではなく
tool_use_idで対応付ける PostToolUseFailureでレベルを ERROR にしておくと、失敗箇所がすぐ見つかる- プロンプトやツール出力の全文が外部(Langfuse)に送られる。秘密情報が混じる前提で、送り先とアクセス権を管理する
- 作者のスクリプト(記事の結論): github.com
- 関連: AIコーディング: Claude Code / Codex / Copilot CLI の利用状況を OpenTelemetry でエクスポートする、過去のエージェントとの会話ログを検索・可視化する
出典
- いいね: @minorun365 · 2026-04-24
- tubone「Claude CodeのHooksとLangfuseで、コーディングエージェントの動きを丸裸にする」: tubone-project24.xyz