agentbay_memory_recall
Search project memory using hybrid search (alias, tags, full-text, vector) with RRF fusion. Filter by memory tier, type, tags, limit, or token budget. Fast mode skips vectors for quicker results.
Instructions
Search project memory using hybrid search (alias + tag + full-text + vector) with RRF fusion. Use tokenBudget to control context size. Use fast=true to skip vectors.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| projectId | Yes | Project ID | |
| query | Yes | What you need to remember / search for | |
| tier | No | Filter by memory tier | |
| type | No | ||
| tags | No | ||
| limit | No | Max entries (default 5) | |
| tokenBudget | No | Max tokens to return | |
| fast | No | Skip vector search for speed | |
| format | No | "context" returns compact text for LLM injection |
Implementation Reference
- src/index.ts:611-651 (registration)Registration and schema definition for the 'agentbay_memory_recall' tool using McpServer.server.tool(), defining the Zod schema for projectId, query, tier, type, tags, limit, tokenBudget, fast, and format parameters.
server.tool( 'agentbay_memory_recall', 'Search project memory using hybrid search (alias + tag + full-text + vector) with RRF fusion. Use tokenBudget to control context size. Use fast=true to skip vectors.', { projectId: z.string().describe('Project ID'), query: z.string().describe('What you need to remember / search for'), tier: z.enum(['working', 'episodic', 'semantic', 'procedural']).optional().describe('Filter by memory tier'), type: z.enum(['PATTERN', 'PITFALL', 'ARCHITECTURE', 'DEPENDENCY', 'TEST_INSIGHT', 'PERFORMANCE', 'DECISION', 'CONTEXT']).optional(), tags: z.array(z.string()).optional(), limit: z.number().min(1).max(20).optional().describe('Max entries (default 5)'), tokenBudget: z.number().optional().describe('Max tokens to return'), fast: z.boolean().optional().describe('Skip vector search for speed'), format: z.enum(['json', 'context']).optional().describe('"context" returns compact text for LLM injection'), }, async ({ projectId, query, tier, type, tags, limit, tokenBudget, fast, format }) => { const params = new URLSearchParams({ q: query }); if (tier) params.set('tier', tier); if (type) params.set('type', type); if (tags?.length) params.set('tags', tags.join(',')); if (limit) params.set('limit', String(limit)); if (tokenBudget) params.set('tokenBudget', String(tokenBudget)); if (fast) params.set('fast', 'true'); if (format) params.set('format', format); const data = await apiGet(`/api/v1/projects/${projectId}/memory?${params.toString()}`); if (data.error) return { content: [{ type: 'text' as const, text: `Error: ${data.error}` }] }; if (format === 'context' && typeof data === 'string') { return { content: [{ type: 'text' as const, text: data }] }; } const entries = data.entries || []; if (!entries.length) return { content: [{ type: 'text' as const, text: 'No relevant memories found.' }] }; const text = entries.map((e: any) => `## ${e.title} [${e.type}/${e.tier}]\nID: ${e.id} | Confidence: ${(e.confidence * 100).toFixed(0)}% | Score: ${e.score.toFixed(4)}${e.truncated ? ' | [SUMMARIZED]' : ''}\n${e.content}${e.tags?.length ? `\nTags: ${e.tags.join(', ')}` : ''}` ).join('\n\n---\n\n'); return { content: [{ type: 'text' as const, text: `Found ${entries.length} memories (${data.totalTokens} tokens, mode: ${data.searchMode}):\n\n${text}` }] }; } ); - src/index.ts:625-651 (handler)Handler function that builds query params, calls the API endpoint /api/v1/projects/{projectId}/memory with hybrid search, and formats results as formatted text with title, type, tier, confidence, score, truncated flag, content, and tags.
async ({ projectId, query, tier, type, tags, limit, tokenBudget, fast, format }) => { const params = new URLSearchParams({ q: query }); if (tier) params.set('tier', tier); if (type) params.set('type', type); if (tags?.length) params.set('tags', tags.join(',')); if (limit) params.set('limit', String(limit)); if (tokenBudget) params.set('tokenBudget', String(tokenBudget)); if (fast) params.set('fast', 'true'); if (format) params.set('format', format); const data = await apiGet(`/api/v1/projects/${projectId}/memory?${params.toString()}`); if (data.error) return { content: [{ type: 'text' as const, text: `Error: ${data.error}` }] }; if (format === 'context' && typeof data === 'string') { return { content: [{ type: 'text' as const, text: data }] }; } const entries = data.entries || []; if (!entries.length) return { content: [{ type: 'text' as const, text: 'No relevant memories found.' }] }; const text = entries.map((e: any) => `## ${e.title} [${e.type}/${e.tier}]\nID: ${e.id} | Confidence: ${(e.confidence * 100).toFixed(0)}% | Score: ${e.score.toFixed(4)}${e.truncated ? ' | [SUMMARIZED]' : ''}\n${e.content}${e.tags?.length ? `\nTags: ${e.tags.join(', ')}` : ''}` ).join('\n\n---\n\n'); return { content: [{ type: 'text' as const, text: `Found ${entries.length} memories (${data.totalTokens} tokens, mode: ${data.searchMode}):\n\n${text}` }] }; } ); - src/index.ts:163-166 (helper)Helper function apiGet used by the handler to make authenticated GET requests to the AgentBay API.
async function apiGet(path: string) { const res = await fetch(`${API_BASE}${path}`, { headers: getHeaders() }); return res.json(); }