How Tool Retrieval Works
Agent-CoreX exposes two retrieval endpoints: a V1 basic semantic search and a V2 hybrid ranker. Understanding how they work helps you write better queries and tune the system for your use case.
Last updated: April 2026
Overview
When your agent calls retrieve_tools(query, top_k), Agent-CoreX:
- 1Authenticates the request (API key hash checked via Redis cache, then Supabase)
- 2Selects the retrieval path: V2 if available, falls back to V1
- 3Computes an embedding of your query text
- 4Searches the vector index for the nearest tool embeddings
- 5Applies hybrid scoring to re-rank results (V2 only)
- 6Filters to tools in your enabled packs (V2 only)
- 7Returns the top_k tools as a ranked list
- 8Logs the query asynchronously (fire-and-forget background task)
V1 — FAISS semantic search
The V1 endpoint (GET /retrieve_tools) uses a FAISS in-memory index for pure vector similarity search. It:
- •Encodes the query into a dense vector embedding
- •Performs an approximate nearest-neighbour search against all tool embeddings in the FAISS index
- •Returns the top
top_ktools ranked by cosine similarity - •Does not apply user-scoped filtering
GET /retrieve_tools?query=read+files+from+disk&top_k=5
Authorization: Bearer acx_your_keyV2 — Hybrid scoring
The V2 endpoint (GET /v2/retrieve_tools) uses Qdrant as the vector database and applies a hybrid scoring formula:
Vector score (70% weight)
Cosine similarity between the query embedding and the tool description embedding in the Qdrant collection. Captures semantic meaning — "fetch webpage" matches "retrieve URL content" even without shared keywords.
Keyword score (30% weight)
BM25-style lexical match on the tool name and description. Boosts tools that contain exact terms from the query. Prevents semantic drift where a high-scoring but unrelated tool floats to the top.
The 70/30 split prioritises semantic understanding while still rewarding exact keyword matches. If you're seeing poor results, try making your query more literal — adding the exact tool keyword (e.g. "postgres", "puppeteer") boosts the keyword component.
GET /v2/retrieve_tools?query=read+files+from+disk&top_k=5
Authorization: Bearer acx_your_keyUser-scoped filtering
V2 retrieval filters the candidate tools to those in the authenticated user's enabled packs. The workflow is:
- 1User installs a pack or MCP server — tracked via POST /v2/track_installation
- 2The tool is indexed into the Qdrant collection with the user_id as a filter field
- 3On each V2 query, Qdrant filters the search to tools matching the user_id
- 4Only enabled tools (is_active = true in user_mcp_servers or user_packs) are returned
When using the MCP server (agent-corex serve) with the AGENT_COREX_USER_ID environment variable set, V2 is used automatically with user scoping. If the variable is unset, V1 (no scoping) is used as a fallback.
Redis caching
Auth key cache
Valid API keys are cached in Redis after the first Supabase lookup. Subsequent requests hit the cache — reducing auth latency to sub-millisecond.
Invalid key cache (negative cache)
Invalid or revoked keys are negatively cached for 60 seconds. This prevents brute-force scanning from hammering Supabase with repeated lookups.
Tool retrieval results
Retrieval results for a given (query, user_id, top_k) combination are cached. Identical queries within 5 minutes return instantly without hitting Qdrant.
Quota / plan info
User quota data (plan, queries_limit, current_month_usage) is cached for 10 seconds to reduce per-request Supabase load.
API reference
/retrieve_toolsV1 semantic search. Params: query (string), top_k (int, default 5). No user scoping.
/v2/retrieve_toolsV2 hybrid search. Params: query (string), top_k (int, default 5). User-scoped when authenticated with API key.
/v2/track_installationRecord a tool or pack installation for a user. Updates the Qdrant index with user_id filtering.
/v2/index_toolsAdd or update tools in the Qdrant index. Used internally when the tool registry is updated.
All endpoints require Authorization: Bearer acx_... or a Supabase session JWT. See Create an API Key.