Local tool discovery
Route the catalog before the model sees it.
Search names, descriptions, tags, and JSON Schema across provider formats. No model call, vector store, or runtime dependency.
Routing workbench
Change the request or provider format. Results are produced by the published browser bundle.
Selected definitions
Ready| Tool | Evidence | Score | Tokens |
|---|
Request code
One index, bounded context
Keep the capability. Remove the catalog overhead.
The router preserves original provider definitions and returns only the strongest local matches. Explicitly pinned tools remain available for policy-critical operations.
Start here
Install and route
npm install @stackline/tool-routerimport { createToolRouter } from '@stackline/tool-router';
const router = createToolRouter(tools);
const routed = router.route(userMessage, {
maxTools: 5,
maxEstimatedTokens: 4_000,
pinned: ['auth_get_current_user']
});
await client.responses.create({
model: 'your-model',
input: userMessage,
tools: routed.tools
});
Interoperability
Use the definitions you already own
The adapters locate retrieval fields and preserve each original object. Schema dialects are never silently converted.
| Format | Input schema key | Envelope |
|---|---|---|
| MCP | inputSchema | tool array |
| OpenAI Responses | parameters | { tools } |
| OpenAI Chat | function.parameters | { tools } |
| Anthropic | input_schema | tool array |
| Gemini | parameters | functionDeclarations |
Control
Count, budget, filter, pin
Tool count and token estimates are independent controls. Namespace, format, ID, tag, and custom predicates can narrow eligible definitions before scoring.
router.route(query, {
maxTools: 6,
maxEstimatedTokens: 4000,
namespaces: ['github', 'slack'],
tags: ['write'],
pinned: ['auth_current_user'],
fallback: 'none'
});
Live systems
Update without rebuilding
Document frequencies, field lengths, token estimates, prefixes, and fuzzy lexicon entries are maintained incrementally.
const router = createToolRouter([], {
onDuplicate: 'replace'
});
router.add(tool);
router.remove(toolId);
router.replace(currentCatalog);
router.clear();
Transparent baseline
Evaluation, not a magic number
The included 30-intent corpus covers twelve product domains. Run npm run benchmark against the source and replace it with representative production queries before setting limits.
Reference
Small public surface
createToolRouter- Build a mutable provider-neutral retrieval index.
search- Return ranked matches, score, fields, terms, and original definitions.
select- Return only original definitions.
route- Apply count, budget, filter, fallback, and pinning controls.
createToolSearch- Create a compact provider-shaped discovery function.
normalizeTool- Inspect the immutable retrieval record for one definition.
Read the full package reference or inspect the architecture.
Untrusted definitions
Bounded by default
Own data properties only. No getter execution. Dangerous prototype keys are skipped. Catalog, schema, text, query, expansion, and edit-distance limits are enforced. The runtime has no dependencies and makes no network requests.
Security policyMachine-readable docs