mcpField
C
Convex Agents Debugging

Convex Agents Debugging

github.com/sstoboテスト・品質24196 回インストール40 週間前に更新
リポジトリ

Convex Agents Debugging について

Convex Agentsでエージェントを開発する人向けのデバッグスキルです。モデルのリクエスト、コンテキスト、メッセージ、保存データを調べ、ツール呼び出しの追跡や型の問題にも対応します。

主な機能

  1. 01モデルのリクエストと応答の記録
  2. 02コンテキストメッセージの確認
  3. 03エージェントのデータテーブルの照会
  4. 04コンテキストの手動取得
  5. 05ツール呼び出しと結果の追跡
  6. 06メッセージ順序の分析

活用シーン

  1. 01エージェントの予期しない動作を調べる
  2. 02コンテキストが使われているか確認する
  3. 03ツール呼び出しと結果を監査する
  4. 04メッセージ順序やトークン使用量を分析する

インストール

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

$npx skills add https://github.com/sstobo/convex-skills --skill convex-agents-debugging

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

詳細

目的

デバッグツールを使うと、エージェント内部で何が起きているか、LLM が何を受け取っているか、何が保存されているかを把握できます。信頼性の高いエージェントアプリケーションを開発するうえで不可欠です。

このスキルを使う場面

  • エージェントの動作が予想外である
  • LLM の応答が意図したものと異なる
  • 特定のコンテキストが使用されない理由を調査する
  • メッセージの順序を把握する
  • ファイルの保存場所と参照を確認する
  • ツールの呼び出しと結果を監査する
  • トークンの使用量をプロファイリングする

LLM のリクエストとレスポンスを生のまま記録する

const myAgent = new Agent(components.agent, {
  name: "My Agent",
  languageModel: openai.chat("gpt-4o-mini"),
  rawRequestResponseHandler: async (ctx, { request, response }) => {
    console.log("LLM Request:", JSON.stringify(request, null, 2));
    console.log("LLM Response:", JSON.stringify(response, null, 2));

    await ctx.runMutation(internal.logging.saveLLMCall, {
      request,
      response,
      timestamp: Date.now(),
    });
  },
});

コンテキストメッセージを記録する

LLM が受け取るコンテキストを正確に確認します。

const myAgent = new Agent(components.agent, {
  name: "My Agent",
  languageModel: openai.chat("gpt-4o-mini"),
  contextHandler: async (ctx, args) => {
    console.log("Context Messages:", {
      recent: args.recent.length,
      search: args.search.length,
      input: args.inputMessages.length,
    });

    args.allMessages.forEach((msg, i) => {
      console.log(`Message ${i}:`, {
        role: msg.role,
        contentLength: typeof msg.content === "string"
          ? msg.content.length
          : JSON.stringify(msg.content).length,
      });
    });

    return args.allMessages;
  },
});

データベースのテーブルを調べる

エージェントのデータを直接クエリします。

export const getThreadMessages = query({
  args: { threadId: v.string() },
  handler: async (ctx, { threadId }) => {
    return await ctx.db
      .query(components.agent.tables.messages)
      .filter((msg) => msg.threadId === threadId)
      .collect();
  },
});

コンテキストを手動で取得する

使用されるコンテキストを確認します。

import { fetchContextWithPrompt } from "@convex-dev/agent";

export const inspectContext = action({
  args: { threadId: v.string(), prompt: v.string() },
  handler: async (ctx, { threadId, prompt }) => {
    const { messages } = await fetchContextWithPrompt(ctx, components.agent, {
      threadId,
      prompt,
    });

    return {
      contextMessages: messages.length,
      messages: messages.map((msg) => ({
        role: msg.role,
        contentType: typeof msg.content,
      })),
    };
  },
});

ツール呼び出しを追跡する

すべてのツール呼び出しを記録します。

export const myTool = createTool({
  description: "My tool",
  args: z.object({ query: z.string() }),
  handler: async (ctx, { query }): Promise<string> => {
    console.log("[TOOL] myTool called with:", query);
    const result = await someOperation(query);
    console.log("[TOOL] myTool returned:", result);
    return result;
  },
});

型エラーを修正する

よくある循環参照の問題:

// WRONG - no return type
export const myFunction = action({
  args: { prompt: v.string() },
  handler: async (ctx, { prompt }) => {
    return await someLogic();
  },
});

// CORRECT - explicit return type
export const myFunction = action({
  args: { prompt: v.string() },
  returns: v.string(),
  handler: async (ctx, { prompt }): Promise<string> => {
    return await someLogic();
  },
});

メッセージ構造を分析する

メッセージの順序をデバッグします。

export const analyzeMessages = query({
  args: { threadId: v.string() },
  handler: async (ctx, { threadId }) => {
    const messages = await listMessages(ctx, components.agent, {
      threadId,
      paginationOpts: { cursor: null, numItems: 100 },
    });

    return messages.results.map((msg) => ({
      order: msg.order,
      stepOrder: msg.stepOrder,
      role: msg.message.role,
      status: msg.status,
    }));
  },
});

主な原則

  • 早めに記録する:開発中にデータを取得します
  • 手早い確認にはコンソールを使う:素早く反復できます
  • 重要なイベントを保存する:分析用に LLM 呼び出しをアーカイブします
  • 戻り値の型を明示する:循環参照を防ぎます
  • ダッシュボードで調べる:データベースの状態を確認する最も簡単な方法です

次のステップ

  • 対話的なデバッグについては、playground を参照してください
  • エージェントのセットアップについては、fundamentals を参照してください
  • コンテキストを考慮したデバッグについては、context を参照してください

コメント