@stackline/tool-router

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.

18tools indexed
Maximum tools
Always loaded
Selected0
Catalog estimate0
Selected estimate0
Estimated reduction0%

Selected definitions

Ready
ToolEvidenceScoreTokens

Request code

Many capability modules passing through a router and emerging as five selected tools

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-router
import { 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.

FormatInput schema keyEnvelope
MCPinputSchematool array
OpenAI Responsesparameters{ tools }
OpenAI Chatfunction.parameters{ tools }
Anthropicinput_schematool array
GeminiparametersfunctionDeclarations

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

100%recall@1
100%recall@5
85.28%average estimated reduction
10,000synthetic catalog tools

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 policy

Machine-readable docs

Documentation resources

#Stackline #ToolRouting #MCP #AIAgents #OpenSource #NPM #AIReadyDocs