关于 Convex Agents Debugging
用于调试基于 Convex Agents 构建的 Agent 应用,帮助开发者检查模型请求、上下文、消息和数据存储。还涵盖工具调用追踪及常见类型问题排查。
主要功能
- 01记录模型请求与响应
- 02检查模型上下文消息
- 03查询 Agent 数据表
- 04手动获取上下文
- 05追踪工具调用与结果
- 06分析消息顺序
适用场景
- 01排查 Agent 行为异常
- 02检查上下文是否被使用
- 03审计工具调用及结果
- 04分析消息顺序和令牌用量
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ sstobo/ convex-skills --skill convex-agents-debugging安装后在 Claude Code 中输入/convex-agents-debugging确认已加载。
详细介绍
目的
调试工具有助于了解 Agent 内部发生了什么、大模型接收到了什么,以及存储了什么。对于开发可靠的 Agent 应用而言必不可少。
何时使用本技能
- Agent 行为不符合预期
- 大模型响应偏离目标
- 排查为何某些上下文未被使用
- 理解消息顺序
- 检查文件存储与引用
- 审计工具调用及结果
- 分析 token 用量
记录原始大模型请求与响应
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(),
});
},
});
记录上下文消息
准确查看大模型接收到的上下文:
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;
},
});
检查数据库表
直接查询 Agent 数据:
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,
}));
},
});
核心原则
- 尽早记录:在开发过程中就捕获数据
- 使用 console 快速检查:便于快速迭代
- 保存重要事件:归档大模型调用以供分析
- 显式返回类型:防止循环引用
- 仪表盘检查:查看数据库状态最简单的方式
后续步骤
- 参见 playground 进行交互式调试
- 参见 fundamentals 了解 Agent 设置
- 参见 context 了解上下文感知调试
评论
支持 Markdown