Convex Agents Debugging について
Convex Agentsでエージェントを開発する人向けのデバッグスキルです。モデルのリクエスト、コンテキスト、メッセージ、保存データを調べ、ツール呼び出しの追跡や型の問題にも対応します。
主な機能
- 01モデルのリクエストと応答の記録
- 02コンテキストメッセージの確認
- 03エージェントのデータテーブルの照会
- 04コンテキストの手動取得
- 05ツール呼び出しと結果の追跡
- 06メッセージ順序の分析
活用シーン
- 01エージェントの予期しない動作を調べる
- 02コンテキストが使われているか確認する
- 03ツール呼び出しと結果を監査する
- 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 を参照してください
コメント
Markdown 対応