mcpField
A
agent-tracing

agent-tracing

github.com/lobehubエージェントワークフロー83.6k195 回インストール今日更新
リポジトリ

agent-tracing について

agent-tracingは、LobeHubのエージェント実行と目標の軌跡を記録・確認するローカル開発ツールです。記録済みのモデル呼び出しの再実行や、コンテキストウィンドウとキャッシュの分析にも対応します。

主な機能

  1. 01実行スナップショットのローカル記録
  2. 02操作と目標のトレース確認
  3. 03固定したLLM呼び出しのモデル間再実行
  4. 04コンテキストとプレフィックスキャッシュの可視化

活用シーン

  1. 01エージェントの実行ステップのデバッグ
  2. 02固定した呼び出しでのモデル出力比較
  3. 03目標の判断と候補作業の確認
  4. 04キャッシュ再利用に影響するコンテキスト変更の特定

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/lobehub/lobehub --skill agent-tracing

インストール後、Claude Code で/agent-tracingを入力して読み込まれたか確認します。

詳細

エージェントトレース CLI ガイド

@lobechat/agent-tracing は、エージェントの実行スナップショットをディスクに記録し、CLI で調査できるゼロ設定のローカル開発ツールです。

仕組み

NODE_ENV=development の場合、AgentRuntimeService.executeStep() は各ステップを部分スナップショットとして .agent-tracing/ に自動記録します。処理が完了すると、部分スナップショットは完全な ExecutionSnapshot JSON ファイルに確定されます。

データフロー:executeStep ループ -> StepPresentationData を構築 -> 部分スナップショットをディスクに書き込み -> 完了時に .agent-tracing/{timestamp}_{traceId}.json に確定

コンテキストエンジンのキャプチャ:RuntimeExecutors.ts では、call_llm エグゼキューターが serverMessagesEngine() でメッセージを処理した後、ctx.tracingContextEngine(input, output, metadata) を呼び出します。AgentRuntimeService.executeStep はステップごとにこの呼び出しをバッファリングし、型付きの contextEngine フィールドとして OperationTraceRecorder.appendStep に渡します。CE は events 配列ではなく、このサイドチャネルを介して渡されるため、大きなペイロード(agentDocuments、systemRole、…)が Redis の状態パイプラインに入ることはありません(LOBE-9110)。metadata には、パイプラインのリクエストごとの判断記録(トリム統計、キャッシュウォーム判定、切り詰め数)が含まれます。

パッケージの場所

packages/agent-tracing/
  src/
    types.ts          # ExecutionSnapshot, StepSnapshot, SnapshotSummary
    store/
      types.ts        # ISnapshotStore interface
      file-store.ts   # FileSnapshotStore (.agent-tracing/*.json)
    recorder/
      index.ts        # appendStepToPartial(), finalizeSnapshot()
    viewer/
      index.ts        # Terminal rendering: renderSnapshot, renderStepDetail, renderMessageDetail, renderSummaryTable, renderPayload, renderPayloadTools, renderMemory
    cli/
      index.ts        # CLI entry point (#!/usr/bin/env bun)
      inspect.ts      # Inspect command (default)
      partial.ts      # Partial snapshot commands (list, inspect, clean)
    index.ts          # Barrel exports

データストレージ

  • 完了したスナップショット:.agent-tracing/{ISO-timestamp}_{traceId-short}.json
  • 最新のシンボリックリンク:.agent-tracing/latest.json
  • 処理中の部分スナップショット:.agent-tracing/_partial/{operationId}.json
  • ダウンロード済みのリモートスナップショット:.agent-tracing/_remote/{operationId}.json
  • FileSnapshotStore は process.cwd() を基準に解決します — CLI はリポジトリのルートから実行してください

リモートトレース(本番/ステージング)

サーバーのデプロイ環境では、完了したスナップショットもオブジェクトストレージにアップロードされます(zstd 圧縮。キーは agent_operations.trace_s3_key に保存されます)。

推奨:lh trace op。 サーバーがキーを解決し、呼び出し元自身のスコープに対してオブジェクトの署名を行うため、必要なのは LobeHub へのログインだけです。TRACING_BASE_URL もバケットのドメインも、トピック ID をオペレーション ID に変換するための SQL も不要です。

lh trace op list --topic tpc_xxx # operations of a topic, newest first, with a TRACE column
lh trace op inspect op_xxx_agt_xxx_tpc_xxx_xxxx
lh trace op inspect op_xxx_agt_xxx_tpc_xxx_xxxx -T # tool injection (enabledToolIds, manifests)

list の TRACE = — は、その実行でスナップショットが記録されなかったことを示します(トレースのアップロード導入前に実行されたか、アップロードが無効になっていた場合です)。記録済みのスナップショットでも、保持期間を過ぎるとストレージ上で 404 になることがあります。

バックエンド:agentTrace ラムダルーター(getSnapshotUrl / listOperations)。制限付き API キーでは blocked になるため、これらのコマンドにはスコープ付きキーではなく、実際のセッションが必要です。

代替手段:スタンドアロンの agent-tracing CLI。 LobeHub セッションがないため、オブジェクト URL を自身で組み立てる必要があり、バケットのパブリックドメインを設定する必要があります。

  • 環境変数:TRACING_BASE_URL=https://<bucket-public-domain>/agent-traces
  • または、リポジトリのルートにある .agent-tracing/.env に同じ TRACING_BASE_URL=... の行を記述します

デプロイ環境固有の値は各環境で非公開であり、意図的にこのリポジトリには記録していません。まず手動でオペレーション ID を調べてください。

SELECT id, trace_s3_key FROM agent_operations WHERE topic_id = 'tpc_xxx';

どちらの場合も、スナップショットは .agent-tracing/_remote/<opId>.json にキャッシュされ、すべての inspect フラグはローカルトレースと同様に機能します。

実装:packages/agent-tracing/src/store/loadSnapshot.ts(解決順序:ローカルストア → _remote/ キャッシュ → 注入された resolveDownloadUrl → TRACING_BASE_URL)および store/remote-store.ts(URL は {base}/{agentId}/{topicId}/{opId}.json.zst として構築されます)。圧縮されたスナップショットの読み込みには Node >= 22.15 が必要です。

ゴールの軌跡

ゴールは、オペレーションがエージェントの実行を一度完了するのと同じように、_ゴール_の実行を一度完了したものです。そのため、1 つ上の階層で同じトレース形式を使用します。GoalTrajectory : AdvanceSnapshot は ExecutionSnapshot : StepSnapshot に対応します。advance のテーブルはありません。agent_steps テーブルがないのと同じです。goal_traces には、ゴールごとにロールアップ行とオブジェクトキーが 1 つ格納され、詳細はオブジェクト内にあります。

末端から下位のトレースにたどれます。advance は、実行を開始した operationId を記録するため(tick.effects[].operationId)、ゴールのトレースが終わるところから lh trace op inspect <opId> で続けて調査できます。

agent-tracing goal               # list local goal trajectories
agent-tracing goal goal_xxx      # the run: triggers, outcomes, graph, gates, ops
agent-tracing goal goal_xxx -a 3 # one advance in full, with the frontier it ranked
agent-tracing goal goal_xxx -j   # raw JSON

各 tick が記録するのは、単なる結果ではなく判断の入力です。読み取ったグラフ(前の tick との差分)、評価した予算、担当タスクの状態、そして候補になり得るすべての作業ノード(選ばれなかったノードも含む)が記録されます。選ばれなかった候補がなければ、トレースから「なぜあのノードではなかったのか」に答えられません。

ストレージはオペレーションの切り替えに従うため、一方を保持するデプロイでは、もう一方も保持されます。

  • 完了済み:goal-traces/{goalId}.json.zst
  • 進行中:goal-traces/_partial/{goalId}.json.zst(長期ゴールが未完了なのは、調査するうえで一般的なケースです)
  • 開発環境:.goal-tracing/{goalId}.json

リプレイ。 replayGoalAgainstCurrentCoordinator(trajectory) は、記録された入力に対して実際の decideNextMove を再実行し、現在のコーディネーターが異なる選択をする箇所について {advanceSeq, tickIndex, field, recorded, replayed} を報告します。これにより、コーディネーターの_判断_を正確に再現できますが、ディスパッチされた作業が同じ結果になったかどうかは分かりません。

実装:packages/agent-tracing/src/goal/。GoalService.tick の onDecision サイドチャネルを介して、すべての advance が通る単一の経路である apps/server/src/services/goal/advanceGoal.ts に記録されます。

CLI コマンド

すべてのコマンドはリポジトリのルートから実行します。

# View latest trace (tree overview, `inspect` is the default command)
agent-tracing
agent-tracing inspect
agent-tracing inspect <traceId>
agent-tracing inspect latest

# List recent snapshots
agent-tracing list
agent-tracing list -l 20

# Inspect specific step (-s is short for --step)
agent-tracing inspect <traceId> -s 0

# View messages (-m is short for --messages)
agent-tracing inspect <traceId> -s 0 -m

# View full content of a specific message (by index shown in -m output)
agent-tracing inspect <traceId> -s 0 --msg 2
agent-tracing inspect <traceId> -s 0 --msg-input 1

# View tool call/result details (-t is short for --tools)
agent-tracing inspect <traceId> -s 1 -t

# View raw events (-e is short for --events)
agent-tracing inspect <traceId> -s 0 -e

# View runtime context (-c is short for --context)
agent-tracing inspect <traceId> -s 0 -c

# View context engine input overview (-p is short for --payload)
agent-tracing inspect <traceId> -p
agent-tracing inspect <traceId> -s 0 -p

# View available tools in payload (-T is short for --payload-tools)
agent-tracing inspect <traceId> -T
agent-tracing inspect <traceId> -s 0 -T

# View user memory (-M is short for --memory)
agent-tracing inspect <traceId> -M
agent-tracing inspect <traceId> -s 0 -M

# Raw JSON output (-j is short for --json)
agent-tracing inspect <traceId> -j
agent-tracing inspect <traceId> -s 0 -j

# List in-progress partial snapshots
agent-tracing partial list

# Inspect a partial (use `inspect` directly — all flags work with partial IDs)
agent-tracing inspect <partialOperationId>
agent-tracing inspect <partialOperationId> -T
agent-tracing inspect <partialOperationId> -p

# Clean up stale partial snapshots
agent-tracing partial clean

# Map the context window composition of every LLM call (cm / map are aliases)
agent-tracing ctx-map
agent-tracing ctx-map <operationId|traceId|path.json>
agent-tracing ctx-map --html            # standalone report under .agent-tracing/_reports/
agent-tracing ctx-map --html out.html

# Re-issue a recorded LLM call against other models (see "replay" below)
agent-tracing replay <operationId|traceId|path.json>
agent-tracing replay <target> -s 4 -m openai/gpt-5,anthropic/claude-sonnet-5
agent-tracing replay <target> --all-steps

replay — 凍結された呼び出しを再実行する

スナップショットには、LLM 呼び出しで認識されたすべての情報がすでに保存されています。steps[].contextEngine.output はモデルに送信された正確なメッセージ配列で、context.payload.tools はモデルが利用できたツールセットです。replay はモデルだけを入れ替えて、この凍結されたペイロードを再度送信します。そのため、出力の違いはコンテキストの組み立て方ではなく、モデルに起因すると判断できます。どのモデルでも同じペイロードで失敗するなら、問題はコンテキストにあります。一部のモデルが成功するなら、問題はモデルの選択にあります。

どちらの CLI からも利用できます。agent-tracing replay(LOBEHUB_JWT を読み込みます)と lh trace op replay(lh login セッションを使用します)です。どちらも、呼び出しが LobeHub のチャットルート経由で送信されるため、認証情報が必要です。

# One call: defaults to the last call_llm step and the model the op ran on
lh trace op replay <operationId>
lh trace op replay <operationId> -s 4 -m openai/gpt-5,anthropic/claude-sonnet-5
lh trace op replay <operationId> --judge "answers with a concrete file path"

# Every call of the operation
lh trace op replay <operationId> --all-steps
lh trace op replay <operationId> --all-steps --concurrency 8

--all-steps は、この機能全体の目的に答えるオプションです。成功した実行に別のモデルを適用し、そのモデルも同じタスクを達成できるか確認します。 再実行した結果と記録済みの結果を比較する llm-rubric 判定による PASS/FAIL の結果が得られます。既定のルーブリックの代わりに成功条件を自分で定義するには、--judge "<criteria>" を渡してください。

判定対象は実行経路ではなく結果です。異なるツールを呼び出して同じ問題を解決したモデルは合格です。各呼び出しのツール比較(toolSignature)は、実行が別の経路をたどった場合の補足情報として下に表示され、合否の判定には使われません。モデルに到達しなかった最終呼び出しは、判定なしではなく FAIL になります。

各呼び出しは、ハーネスが実際に構築したペイロードを使って個別に再実行されます。そのため、呼び出し 2 で異なる回答になっても呼び出し 4 に影響せず、プロバイダーに到達できなかった呼び出しの影響はその呼び出しだけに限られます。また、呼び出しは並行して送信されます(既定では一度に 4 件)。

ノードをつないで、再実行した出力を次のノードに渡す方式は、いったん実装された後に削除されました。トレースからツールの出力を再生成することはできず、記録済みの内容を返すことしかできません。そのため、モデルが記録から外れた時点で正解となる根拠がなくなり、実行は成功したように見える一方で、何も測定できなくなります。独立して再実行する方式は設計上の選択であり、代替手段ではありません。

既知の制限事項:サンプリングパラメーターは記録されません。 レコーダーはプロバイダーへのリクエスト本文ではなく、context.payload に実行時のステップコンテキストを保存するため、これまでに書き込まれたすべてのトレースで、temperature、top_p、max_tokens、ペナルティ、推論設定が欠落しています。再実行では、サーバーの現在の既定値が使用されます。モデル間の比較は、どの対象モデルにも同じリクエストが送信されるため、引き続き有効です。ただし、既定値以外の設定で実行された操作では、記録済みの出力との比較は有効ではありません。--temperature/--max-tokens で明示的に上書きできます。記録済みのパラメーターなしで再実行する場合、CLI は note 行を表示します。

ctx-map — コンテキストウィンドウの構成

ctx-map は、call_llm ステップごとに 1 行を表示します。各行には、その呼び出しでモデルに送信されたメッセージが、型別のセグメント(system/注入ブロック/user/reasoning/tool call/tool result)に分けて表示されます。幅はトークン数に比例し、モデルのコンテキストウィンドウ上に配置されます。

2 つ目の軸で示すのは、ctx-lint では確認できない情報です。各行は直前の呼び出しとの差分を取り、最も長く一致するメッセージのプレフィックス(プロバイダーのプレフィックスキャッシュで再利用できる部分)を示します。また、変更された最初のメッセージと、その後に再処理されたトークン数も表示します。相対タイムスタンプ(1m ago → now)を含む小さな注入ブロックでも、その後のすべてのトークンが無効になるため、行の早い位置に区切りマーカーが表示されます。

行の見方:

  • ブロックの色はロールを直接表します。system はオレンジ、user は緑、assistant は青、tool はグレーです。assistant の reasoning、content、tool call には、同じ青系色の異なる段階が使われます。フレームワークが注入したブロックには、system プロンプトより明るいオレンジが使われます。各値は、viewer/contextMapScales.ts に同梱された LobeHub のカラースケールにおける段階のインデックスで、割り当ては viewer/contextMapPalette.ts にあります。HTML レポートには両方のテーマが含まれ、システムのテーマに従います。
  • 中立色のメッセージ枠は、同じペイロードメッセージに属するセグメントをまとめます。すべてのロールで枠の色は共通です。枠線は構造のみを示し、ブロックの塗りつぶしがロールとサブタイプの意味を示します。元の枠付きレイアウトでは、各メッセージの内側にパディングを設け、メッセージ間に小さなトラック間隔を空けることで、各ペイロードメッセージを視覚的に区別しやすくしています。
  • 塗りつぶしは、プロバイダーが再利用したかどうかを示します。網掛けの ▓(HTML では不透明度 60% の網掛け)はプレフィックスキャッシュから提供された部分で、塗りつぶしの █(HTML では均一な塗りつぶし)はモデルによって再処理された部分です。
  • トラックの下の線はキャッシュの記録です。キャッシュされたプレフィックスの範囲に正確に沿う括弧/緑色の帯に続いて、再利用が止まった位置に区切りマーカー(ターミナルでは ▲、HTML ではトラックを横切る赤い線)が表示され、その理由と再処理されたトークン数が示されます。
フラグ短縮形説明
--html [path]スタンドアロンの HTML レポート(セグメントにカーソルを合わせると内容を表示)
--width <n>-wターミナルの列数で指定するトラック幅
--window <n>トラックに使用するモデルのコンテキストウィンドウを上書き
--full-window最大の呼び出しではなく、常にウィンドウ全体に合わせてスケーリング
--json-j呼び出しごとのセグメントとキャッシュ統計

トラックはコンテキストウィンドウに合わせてスケーリングされます。ウィンドウがペイロードに比べて非常に大きい場合(たとえば、1M のウィンドウに対してペイロードが 50k の場合)は、構成を読みやすく保つため、最大の呼び出しに合わせたスケーリングに切り替わります。ヘッダーには、どちらを基準にしているかが表示されます。分析コードは analysis/contextMap.ts にあり、下流のコーパス処理向けに buildContextMap() としてエクスポートされています。

Inspect フラグリファレンス

フラグ短縮形説明デフォルトのステップ
--step <n>-s特定のステップを対象にします—
--messages-mメッセージのコンテキスト(CE 入力 → パラメーター → LLM ペイロード)—
--tools-tツール呼び出しと結果(エージェントが呼び出したもの)—
--events-e生イベント(llm_start、llm_result など)—
--context-cランタイムコンテキストとペイロード(生データ)—
--system-role-rsystem role の全内容0
--env環境コンテキスト0
--payload-pコンテキストエンジン入力の概要(モデル、ナレッジ、ツールの概要、メモリの概要、プラットフォームコンテキスト)0
--payload-tools-T利用可能なツールの詳細(プラグインマニフェスト + LLM 関数定義)0
--memory-Mユーザーメモリ全体(ペルソナ、アイデンティティ、コンテキスト、設定、経験)0
--diff <n>-dステップ N との差分(-r または --env と併用)—
--msg <n>Final LLM Payload のメッセージ N の全内容—
--msg-input <n>Context Engine Input のメッセージ N の全内容—
--json-jJSON として出力します(上記の任意のフラグと組み合わせ可能)—

「デフォルトのステップ: 0」と記載されたフラグは、--step が指定されていない場合にステップ 0 を自動選択します。すべてのフラグで latest または省略した traceId を使用できます。

典型的なデバッグワークフロー

# 1. Trigger an agent operation in the dev UI

# 2. See the overview
agent-tracing inspect

# 3. List all traces, get traceId
agent-tracing list

# 4. Quick overview of what was fed into context engine
agent-tracing inspect -p

# 5. Inspect a specific step's messages to see what was sent to the LLM
agent-tracing inspect TRACE_ID -s 0 -m

# 6. Drill into a truncated message for full content
agent-tracing inspect TRACE_ID -s 0 --msg 2

# 7. Check available tools vs actual tool calls
agent-tracing inspect -T      # available tools
agent-tracing inspect -s 1 -t # actual tool calls & results

# 8. Inspect user memory injected into the conversation
agent-tracing inspect -M

# 9. Diff system role between steps (multi-step agents)
agent-tracing inspect TRACE_ID -r -d 2

主な型

interface ExecutionSnapshot {
  traceId: string;
  operationId: string;
  model?: string;
  provider?: string;
  startedAt: number;
  completedAt?: number;
  completionReason?:
    'done' | 'error' | 'interrupted' | 'max_steps' | 'cost_limit' | 'waiting_for_human';
  totalSteps: number;
  totalTokens: number;
  totalCost: number;
  error?: { type: string; message: string };
  steps: StepSnapshot[];
}

interface StepSnapshot {
  stepIndex: number;
  stepType: 'call_llm' | 'call_tool';
  executionTimeMs: number;
  content?: string; // LLM output
  reasoning?: string; // Reasoning/thinking
  inputTokens?: number;
  outputTokens?: number;
  toolsCalling?: Array<{ apiName: string; identifier: string; arguments?: string }>;
  toolsResult?: Array<{
    apiName: string;
    identifier: string;
    isSuccess?: boolean;
    output?: string;
  }>;
  messages?: any[]; // DB messages before step
  context?: { phase: string; payload?: unknown; stepContext?: unknown };
  events?: Array<{ type: string; [key: string]: unknown }>;
  contextEngine?: {
    input?: unknown; // contextEngineInput minus messages + toolsConfig (reconstructible from baseline)
    output?: unknown; // processed messages array (final LLM payload)
    metadata?: unknown; // pipeline decision records (trim stats, cache gates, truncation counts)
  };
}

--messages の出力構造

--messages を使用すると、出力には 3 つのセクションが表示されます(コンテキストエンジンのデータが利用可能な場合)。

  1. Context Engine Input — エンジンに渡された DB メッセージ。[0]、[1]、... のインデックスが付きます。全内容を表示するには --msg-input N を使用します。
  2. Context Engine Params — systemRole、model、provider、knowledge、tools、userMemory など。
  3. Final LLM Payload — コンテキストエンジン処理後のメッセージ(日付のシステム注入、ユーザーメモリ、履歴の切り詰めなど)。[0]、[1]、... のインデックスが付きます。全内容を表示するには --msg N を使用します。

統合ポイント

  • 記録:apps/server/src/services/agentRuntime/AgentRuntimeService/executeStep/index.ts — executeStep() 内で、saveAndPublishStep が stepPresentationData を構築した後、開発モードで部分スナップショットを書き込みます
  • コンテキストエンジンのキャプチャ:apps/server/src/modules/AgentRuntime/RuntimeExecutors.ts — call_llm エグゼキューター内で、serverMessagesEngine() の戻り後に ctx.tracingContextEngine(input, output, metadata) を呼び出します。AgentRuntimeService.executeStep はステップごとにこれをバッファリングし、型付きの contextEngine フィールドとして traceRecorder.appendStep に渡します(Redis の状態に含めないよう、events 配列からは分離されています)。
  • 保存先:FileSnapshotStore は process.cwd() を基準とする .agent-tracing/ に対して読み書きします

コメント