agentbay_analytics
Retrieve project analytics including attempt success rates, agent performance, token usage, and trends by providing a project ID.
Instructions
Get project analytics: attempt success rates, agent performance, token usage, and trends
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| projectId | Yes | Project ID |
Implementation Reference
- src/index.ts:864-915 (registration)Registration of the 'agentbay_analytics' tool via server.tool() with name 'agentbay_analytics' and description 'Get project analytics: attempt success rates, agent performance, token usage, and trends'. Accepts a projectId parameter with Zod schema validation.
// Tool 33: Analytics server.tool( 'agentbay_analytics', 'Get project analytics: attempt success rates, agent performance, token usage, and trends', { projectId: z.string().describe('Project ID'), }, async ({ projectId }) => { const data = await apiGet(`/api/v1/projects/${projectId}/analytics`); if (data.error) return { content: [{ type: 'text' as const, text: `Error: ${data.error}` }] }; let text = `# Project Analytics\n\n`; if (data.tasks) { text += `## Tasks\n`; text += `Total: ${data.tasks.total || 0} | Completion rate: ${data.tasks.completionRate || 0}%\n`; if (data.tasks.statusBreakdown && Object.keys(data.tasks.statusBreakdown).length) { text += `Status: ${Object.entries(data.tasks.statusBreakdown).map(([s, c]) => `${s}: ${c}`).join(', ')}\n`; } } if (data.knowledge) { text += `\n## Knowledge\n`; text += `Total entries: ${data.knowledge.total || 0} | Handoffs: ${data.knowledge.handoffs || 0}\n`; if (data.knowledge.typeBreakdown && Object.keys(data.knowledge.typeBreakdown).length) { text += `Types: ${Object.entries(data.knowledge.typeBreakdown).map(([t, c]) => `${t}: ${c}`).join(', ')}\n`; } } text += `\n## Attempts (Code Submissions)\n`; text += `Total: ${data.overview?.totalAttempts || 0} | Merged: ${data.overview?.mergedAttempts || 0} (${data.overview?.mergeRate || 0}%)\n`; if (data.overview?.totalAttempts > 0) { text += `Avg tokens/attempt: ${data.overview?.avgTokens || 'N/A'}\n`; text += `Avg duration: ${data.overview?.avgDurationMs ? `${Math.round(data.overview.avgDurationMs / 1000)}s` : 'N/A'}\n`; text += `Total files changed: ${data.overview?.totalFilesChanged || 0} | +${data.overview?.totalLinesAdded || 0} / -${data.overview?.totalLinesRemoved || 0}\n`; } if (data.agents?.length) { text += `\n## Agent Leaderboard\n`; text += data.agents.map((a: any) => `- ${a.authorName || a.authorId}: ${a.totalAttempts} attempts, ${a.mergeRate || 0}% merged, avg ${a.avgTokens || 'N/A'} tokens` ).join('\n'); } if (data.dailyTrend?.length) { text += `\n\n## 7-Day Trend\n`; text += data.dailyTrend.map((d: any) => `${d.date}: ${d.count} attempts (${d.merged} merged)`).join('\n'); } return { content: [{ type: 'text' as const, text }] }; } ); - src/index.ts:868-870 (schema)Input schema for the agentbay_analytics tool: a single required `projectId` field of type string with description 'Project ID'. No output schema is defined separately since the handler returns formatted text content.
{ projectId: z.string().describe('Project ID'), }, - src/index.ts:871-915 (handler)Handler function for agentbay_analytics. Calls GET /api/v1/projects/${projectId}/analytics, then formats the response into a structured text report including tasks (completion rate, status breakdown), knowledge (entries, handoffs, type breakdown), attempts/code submissions (total, merged, merge rate, avg tokens, duration, files changed), agent leaderboard (per-agent stats), and 7-day daily trends.
async ({ projectId }) => { const data = await apiGet(`/api/v1/projects/${projectId}/analytics`); if (data.error) return { content: [{ type: 'text' as const, text: `Error: ${data.error}` }] }; let text = `# Project Analytics\n\n`; if (data.tasks) { text += `## Tasks\n`; text += `Total: ${data.tasks.total || 0} | Completion rate: ${data.tasks.completionRate || 0}%\n`; if (data.tasks.statusBreakdown && Object.keys(data.tasks.statusBreakdown).length) { text += `Status: ${Object.entries(data.tasks.statusBreakdown).map(([s, c]) => `${s}: ${c}`).join(', ')}\n`; } } if (data.knowledge) { text += `\n## Knowledge\n`; text += `Total entries: ${data.knowledge.total || 0} | Handoffs: ${data.knowledge.handoffs || 0}\n`; if (data.knowledge.typeBreakdown && Object.keys(data.knowledge.typeBreakdown).length) { text += `Types: ${Object.entries(data.knowledge.typeBreakdown).map(([t, c]) => `${t}: ${c}`).join(', ')}\n`; } } text += `\n## Attempts (Code Submissions)\n`; text += `Total: ${data.overview?.totalAttempts || 0} | Merged: ${data.overview?.mergedAttempts || 0} (${data.overview?.mergeRate || 0}%)\n`; if (data.overview?.totalAttempts > 0) { text += `Avg tokens/attempt: ${data.overview?.avgTokens || 'N/A'}\n`; text += `Avg duration: ${data.overview?.avgDurationMs ? `${Math.round(data.overview.avgDurationMs / 1000)}s` : 'N/A'}\n`; text += `Total files changed: ${data.overview?.totalFilesChanged || 0} | +${data.overview?.totalLinesAdded || 0} / -${data.overview?.totalLinesRemoved || 0}\n`; } if (data.agents?.length) { text += `\n## Agent Leaderboard\n`; text += data.agents.map((a: any) => `- ${a.authorName || a.authorId}: ${a.totalAttempts} attempts, ${a.mergeRate || 0}% merged, avg ${a.avgTokens || 'N/A'} tokens` ).join('\n'); } if (data.dailyTrend?.length) { text += `\n\n## 7-Day Trend\n`; text += data.dailyTrend.map((d: any) => `${d.date}: ${d.count} attempts (${d.merged} merged)`).join('\n'); } return { content: [{ type: 'text' as const, text }] }; } ); - src/index.ts:163-166 (helper)Helper function `apiGet` used by the handler to make authenticated GET requests to the AgentBay API. Takes a path and returns the parsed JSON response.
async function apiGet(path: string) { const res = await fetch(`${API_BASE}${path}`, { headers: getHeaders() }); return res.json(); }