{"_id":"toolpick","_rev":"5-7a6dd787982481069e21f697095ac19c","name":"toolpick","dist-tags":{"latest":"0.4.0"},"versions":{"0.1.0":{"name":"toolpick","version":"0.1.0","keywords":["ai","ai-sdk","tools","tool-selection","activeTools","vercel","llm","agent"],"license":"MIT","_id":"toolpick@0.1.0","maintainers":[{"name":"pontus-midday","email":"pontus@midday.ai"}],"homepage":"https://github.com/pontusab/directories#readme","bugs":{"url":"https://github.com/pontusab/directories/issues"},"dist":{"shasum":"0b32dd738ccbf81fa1f9cdd30643bb3f4f2c57bb","tarball":"https://registry.npmjs.org/toolpick/-/toolpick-0.1.0.tgz","fileCount":32,"integrity":"sha512-FbmYwmphXah80/A/7LQxq1MlFOPSZ/ksfAd/0aAUPNOyvE/HKR02WMLAIdmwRcgbHxJk55hhRsdPycVG5csxoQ==","signatures":[{"sig":"MEUCIQD4g1Im2btJMcb6LwPhz9hOYuxK7hbCXdo8VxB1/EEmcAIgaiP0aT7Pp8CMUfPf8qdgoqAVj3pOEnjBB+3G5jixzkA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":46601},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./eval":{"types":"./dist/eval/index.d.ts","import":"./dist/eval/index.js"}},"gitHead":"59a4d91c6dea758bd315363bb7001ff78def613a","scripts":{"dev":"tsc --watch","test":"bun test src/test","build":"tsc"},"_npmUser":{"name":"pontus-midday","email":"pontus@midday.ai"},"repository":{"url":"git+https://github.com/pontusab/directories.git","type":"git"},"_npmVersion":"11.8.0","description":"Dynamic tool selection for the Vercel AI SDK. Automatically picks the right tools per step.","directories":{},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"ai":"^6.0.134","typescript":"^5.9.3","@types/node":"^25.5.0","@ai-sdk/openai":"^3.0.47"},"peerDependencies":{"ai":">=4.0","zod":">=3.25 || >=4.0"},"peerDependenciesMeta":{"ai":{"optional":false},"zod":{"optional":false}},"_npmOperationalInternal":{"tmp":"tmp/toolpick_0.1.0_1774094482255_0.857366998826399","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"toolpick","version":"0.2.0","keywords":["ai","ai-sdk","tools","tool-selection","activeTools","vercel","llm","agent"],"license":"MIT","_id":"toolpick@0.2.0","maintainers":[{"name":"pontus-midday","email":"pontus@midday.ai"}],"homepage":"https://github.com/pontusab/toolpick#readme","bugs":{"url":"https://github.com/pontusab/toolpick/issues"},"dist":{"shasum":"e15df3389a7d2f58bf710be6521471ca5f2ff0cd","tarball":"https://registry.npmjs.org/toolpick/-/toolpick-0.2.0.tgz","fileCount":32,"integrity":"sha512-DcmBwufXeQEJ1mgdnJfPVsvcwo8XxrCkofG5EyiVxH8PazapBsoLVz7UkKnvxTvIeG+60FDvFD2rMbdMJGpreQ==","signatures":[{"sig":"MEUCIQCGRCSxAtac2+fDKJGQNb+yUEBPlidWvDQJe+N4W63+4QIgQpX4+gLyBkwWXKcE/4pA1iOsrB3v2w3h6Kh8dPafNiU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":46733},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./eval":{"types":"./dist/eval/index.d.ts","import":"./dist/eval/index.js"}},"gitHead":"59a4d91c6dea758bd315363bb7001ff78def613a","scripts":{"dev":"tsc --watch","test":"bun test src/test","build":"tsc"},"_npmUser":{"name":"pontus-midday","email":"pontus@midday.ai"},"repository":{"url":"git+https://github.com/pontusab/toolpick.git","type":"git"},"_npmVersion":"11.8.0","description":"Dynamic tool selection for the Vercel AI SDK. Automatically picks the right tools per step.","directories":{},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"ai":"^6.0.134","typescript":"^5.9.3","@types/node":"^25.5.0","@ai-sdk/openai":"^3.0.47"},"peerDependencies":{"ai":">=4.0","zod":">=3.25 || >=4.0"},"peerDependenciesMeta":{"ai":{"optional":false},"zod":{"optional":false}},"_npmOperationalInternal":{"tmp":"tmp/toolpick_0.2.0_1774094594424_0.21269750688402822","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"toolpick","version":"0.3.0","keywords":["ai","ai-sdk","tools","tool-selection","activeTools","vercel","llm","agent"],"license":"MIT","_id":"toolpick@0.3.0","maintainers":[{"name":"pontus-midday","email":"pontus@midday.ai"}],"homepage":"https://github.com/pontusab/toolpick#readme","bugs":{"url":"https://github.com/pontusab/toolpick/issues"},"dist":{"shasum":"84a66043f0485702abeffc79c60dadd4f77fa5aa","tarball":"https://registry.npmjs.org/toolpick/-/toolpick-0.3.0.tgz","fileCount":32,"integrity":"sha512-oNc2yucI/9UfQ9XZjDz67ecHXdzvExcCnex3JuhojP5cGAj0wBdRvshf5dgUL0eJ7lox5lFh4A81a0TuRyjyZw==","signatures":[{"sig":"MEQCIGc+GRTyCtN0n7fvxbZMfTo2YwmQNHnD/VwLf35qKFamAiAZVtSYfL5B0NsT/qvc8ut59oyF9HVkjAFnCA/OUsdcmQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":48068},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./eval":{"types":"./dist/eval/index.d.ts","import":"./dist/eval/index.js"}},"gitHead":"cbeff3490c793f68b87776976ed391ee9fcb0e62","scripts":{"dev":"tsc --watch","test":"bun test src/test","build":"tsc"},"_npmUser":{"name":"pontus-midday","email":"pontus@midday.ai"},"repository":{"url":"git+https://github.com/pontusab/toolpick.git","type":"git"},"_npmVersion":"11.8.0","description":"Dynamic tool selection for the Vercel AI SDK. Automatically picks the right tools per step.","directories":{},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"ai":"^6.0.141","typescript":"^6.0.2","@types/node":"^25.5.0","@ai-sdk/openai":"^3.0.49"},"peerDependencies":{"ai":">=4.0","zod":">=3.25 || >=4.0"},"peerDependenciesMeta":{"ai":{"optional":false},"zod":{"optional":false}},"_npmOperationalInternal":{"tmp":"tmp/toolpick_0.3.0_1774947427844_0.08794041384894835","host":"s3://npm-registry-packages-npm-production"}},"0.3.1":{"name":"toolpick","version":"0.3.1","keywords":["ai","ai-sdk","tools","tool-selection","activeTools","vercel","llm","agent"],"license":"MIT","_id":"toolpick@0.3.1","maintainers":[{"name":"pontus-midday","email":"pontus@midday.ai"}],"homepage":"https://github.com/pontusab/toolpick#readme","bugs":{"url":"https://github.com/pontusab/toolpick/issues"},"dist":{"shasum":"f35f35d0497ec0799c6e578b087a9f2d82c657c9","tarball":"https://registry.npmjs.org/toolpick/-/toolpick-0.3.1.tgz","fileCount":7,"integrity":"sha512-TLJBFrTN7Va9zr5PN9bKdUQnfsqQXgMlExIkRKXPwJ6BM8ECDC2cZjhMUFknRXdSIhD6nKF5DTymfXm9v1b4sg==","signatures":[{"sig":"MEYCIQD7B5bgNkDqR4jqwCxFwnLtdnJ62NiTOegLL7trkMyK7AIhALSMYGTEEZ1FgKY+ngiQeU+0QLDVLuIWTcLUB2mkFzN8","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":35728},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./eval":{"types":"./dist/eval/index.d.ts","import":"./dist/eval/index.js"}},"gitHead":"0d220bac2687a660d548e2ca40033e73fc45cb27","scripts":{"dev":"tsup --watch","test":"bun test src/test","build":"tsup","typecheck":"tsc --noEmit"},"_npmUser":{"name":"pontus-midday","email":"pontus@midday.ai"},"repository":{"url":"git+https://github.com/pontusab/toolpick.git","type":"git"},"_npmVersion":"11.8.0","description":"Dynamic tool selection for the Vercel AI SDK. Automatically picks the right tools per step.","directories":{},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"ai":"^6.0.141","tsup":"^8.5.1","typescript":"^6.0.2","@types/node":"^25.5.0","@ai-sdk/openai":"^3.0.49"},"peerDependencies":{"ai":">=4.0","zod":">=3.25 || >=4.0"},"peerDependenciesMeta":{"ai":{"optional":false},"zod":{"optional":false}},"_npmOperationalInternal":{"tmp":"tmp/toolpick_0.3.1_1774948730251_0.6433839558119272","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"toolpick","version":"0.4.0","description":"Dynamic tool selection for the Vercel AI SDK. Automatically picks the right tools per step.","type":"module","license":"MIT","repository":{"type":"git","url":"git+https://github.com/pontusab/toolpick.git"},"homepage":"https://github.com/pontusab/toolpick#readme","bugs":{"url":"https://github.com/pontusab/toolpick/issues"},"keywords":["ai","ai-sdk","tools","tool-selection","activeTools","vercel","llm","agent"],"main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./eval":{"types":"./dist/eval/index.d.ts","import":"./dist/eval/index.js"}},"engines":{"node":">=18"},"scripts":{"build":"tsup","dev":"tsup --watch","typecheck":"tsc --noEmit","test":"bun test src/test"},"peerDependencies":{"ai":">=4.0","zod":">=3.25 || >=4.0"},"peerDependenciesMeta":{"ai":{"optional":false},"zod":{"optional":false}},"devDependencies":{"@ai-sdk/openai":"^3.0.49","@types/node":"^25.5.0","ai":"^6.0.141","tsup":"^8.5.1","typescript":"^6.0.2"},"gitHead":"870a53cb22b6d001f5eedfc189c323171d839255","_id":"toolpick@0.4.0","_nodeVersion":"22.14.0","_npmVersion":"11.8.0","dist":{"integrity":"sha512-oJVyIWkfZvIRB9vWE/iCHw7v+TxXzDRasty5L31mhA7b4BhYsQ3Tjg3gEgAPmviUKmI6SKpP4EbsIk/JUmkXGQ==","shasum":"645dc614bebdb9613ebb3eb950996ec528d95cf6","tarball":"https://registry.npmjs.org/toolpick/-/toolpick-0.4.0.tgz","fileCount":7,"unpackedSize":37013,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCPlv1CPqsjK2l5iniN7xjaJNoiewQuUP68eZSCukb5kAIhAMAhnu3DXjL9dAawIiiesdvbHoT575fUkhqIEQ8zuL5w"}]},"_npmUser":{"name":"pontus-midday","email":"pontus@midday.ai"},"directories":{},"maintainers":[{"name":"pontus-midday","email":"pontus@midday.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/toolpick_0.4.0_1774950171319_0.3230371095979532"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-21T12:01:22.254Z","modified":"2026-03-31T09:42:51.600Z","0.1.0":"2026-03-21T12:01:22.385Z","0.2.0":"2026-03-21T12:03:14.573Z","0.3.0":"2026-03-31T08:57:07.971Z","0.3.1":"2026-03-31T09:18:50.419Z","0.4.0":"2026-03-31T09:42:51.482Z"},"bugs":{"url":"https://github.com/pontusab/toolpick/issues"},"license":"MIT","homepage":"https://github.com/pontusab/toolpick#readme","keywords":["ai","ai-sdk","tools","tool-selection","activeTools","vercel","llm","agent"],"repository":{"type":"git","url":"git+https://github.com/pontusab/toolpick.git"},"description":"Dynamic tool selection for the Vercel AI SDK. Automatically picks the right tools per step.","maintainers":[{"name":"pontus-midday","email":"pontus@midday.ai"}],"readme":"# toolpick\n\nYour agent has 30 tools. The model sees all of them on every step — tool definitions eat thousands of tokens, the model picks the wrong one, and you're paying for context it doesn't need.\n\ntoolpick fixes this. It picks the right 5 tools per step so the model only sees what matters.\n\n## Install\n\n```bash\nnpm install toolpick\n```\n\n## Usage\n\n```ts\nimport { generateText } from \"ai\";\nimport { openai } from \"@ai-sdk/openai\";\nimport { createToolIndex } from \"toolpick\";\n\nconst index = createToolIndex(allTools, {\n  embeddingModel: openai.embeddingModel(\"text-embedding-3-small\"),\n});\n\nconst result = await generateText({\n  model: openai(\"gpt-4o\"),\n  tools: allTools,\n  prepareStep: index.prepareStep(),\n  prompt: \"ship it to prod\",\n});\n```\n\nEvery step, toolpick selects the most relevant tools and sets `activeTools` automatically. The model only sees what it needs. All tools remain available for execution.\n\nWorks with `generateText`, `streamText`, and `Experimental_Agent`.\n\n## How it works\n\nPass an embedding model and toolpick indexes your tool names, descriptions, and parameters. On each step it runs a combined search — fast keyword matching plus semantic embeddings — and returns the best matches.\n\nIf the model can't find a useful tool, the next step automatically pages to a fresh set it hasn't seen yet. Two misses in a row? All tools get exposed as a fallback. Your agent never gets stuck.\n\nIf the embedding API goes down, it silently falls back to keyword-only search. No crashes.\n\n## LLM re-ranking\n\nFor maximum accuracy, add a `rerankerModel`. The combined search fetches candidates, then a cheap LLM picks the best ones using reasoning — handling slang, abbreviations, and context that embeddings alone miss.\n\n```ts\nconst index = createToolIndex(allTools, {\n  embeddingModel: openai.embeddingModel(\"text-embedding-3-small\"),\n  rerankerModel: openai(\"gpt-4o-mini\"),\n});\n```\n\nThis takes accuracy from 84% to 100% on blind user queries. Cost: ~$0.0001 per step (gpt-4o-mini).\n\n### Description enrichment\n\nFor an extra boost, `enrichDescriptions` expands your tool descriptions with synonyms and alternative phrasings at startup. This is a one-time LLM call during `warmUp()`:\n\n```ts\nconst index = createToolIndex(allTools, {\n  embeddingModel: openai.embeddingModel(\"text-embedding-3-small\"),\n  rerankerModel: openai(\"gpt-4o-mini\"),\n  enrichDescriptions: true,\n});\n\nawait index.warmUp();\n```\n\n## Model-driven discovery\n\nFor agents that need to discover tools outside the current selection, expose the built-in search tool:\n\n```ts\nconst result = await generateText({\n  model: openai(\"gpt-4o\"),\n  tools: {\n    ...allTools,\n    search_tools: index.searchTool(),\n  },\n  prepareStep: index.prepareStep({ alwaysActive: [\"search_tools\"] }),\n  prompt: \"find and use the right tool\",\n});\n```\n\nThe model can call `search_tools` to browse the full catalog and request specific tools be activated. This mirrors how Anthropic's tool search works — but for any model.\n\n## Caching\n\nTool description embeddings are computed once at startup. Cache them to skip the API call on restarts:\n\n```ts\nimport { createToolIndex, fileCache } from \"toolpick\";\n\nconst index = createToolIndex(allTools, {\n  embeddingModel: openai.embeddingModel(\"text-embedding-3-small\"),\n  embeddingCache: fileCache(\".toolpick-cache.json\"),\n});\n\nawait index.warmUp();\n```\n\n## Accuracy\n\nTested with 19 blind user queries — slang, vague language, no keyword overlap — against 30 real SaaS tools:\n\n| Strategy | Top-5 accuracy | Cost per query |\n|---|---|---|\n| Keyword only | 31% | Free |\n| Embeddings only | 79% | ~$0.00002 |\n| Combined (default) | 84% | ~$0.00002 |\n| **Combined + LLM re-ranking** | **100%** | **~$0.0001** |\n\nQueries like \"ship it\", \"ping the team\", \"file a bug\", \"get the CI running\", and \"compress this photo\" all resolve to the correct tool.\n\n## Options\n\n```ts\nconst index = createToolIndex(tools, {\n  embeddingModel: model,          // enables combined search (recommended)\n  rerankerModel: model,           // LLM re-ranking for max accuracy\n  enrichDescriptions: true,       // expand descriptions with synonyms at warmUp\n  embeddingCache: fileCache(path), // persist embeddings to disk\n  strategy: \"hybrid\",             // force keyword-only (free, no API calls)\n});\n\nawait index.select(query, {\n  maxTools: 5,                    // ceiling, not fixed count\n  adaptive: true,                 // cut early when scores drop off\n  alwaysActive: [\"search_tools\"], // always include these\n  threshold: 0.3,                 // minimum relevance score\n});\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md"}