惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

小众软件
小众软件
博客园 - Franky
罗磊的独立博客
G
Google Developers Blog
The GitHub Blog
The GitHub Blog
P
Proofpoint News Feed
Recent Announcements
Recent Announcements
V
V2EX
F
Fortinet All Blogs
阮一峰的网络日志
阮一峰的网络日志
Blog — PlanetScale
Blog — PlanetScale
月光博客
月光博客
U
Unit 42
GbyAI
GbyAI
A
About on SuperTechFans
WordPress大学
WordPress大学
Engineering at Meta
Engineering at Meta
雷峰网
雷峰网
Microsoft Azure Blog
Microsoft Azure Blog
Martin Fowler
Martin Fowler
D
DataBreaches.Net
The Cloudflare Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
MongoDB | Blog
MongoDB | Blog

TanStack Blog

TanStack + Vercel Partnership | TanStack Blog TanStack AI Enters the RC Phase | TanStack Blog Inside a TanStack Router Navigation | TanStack Blog Form v2 is here: All you need to know about the alpha | TanStack Blog Announcing TanStack Table V9 | TanStack Blog TanStack Has a New Look | TanStack Blog Introducing TanStack Markdown and TanStack Highlight | TanStack Blog We Removed React Server Components from TanStack.com | TanStack Blog We Stopped Using RSC on TanStack.com | TanStack Blog Inside TanStack Table V9 Reactivity | TanStack Blog Run Any Coding Agent in a Sandbox, With One chat() Call | TanStack Blog TanStack Start and TanStack AI Win 2026 Open Source Awards | TanStack Blog How an Underrated Refactor Saved 90% Memory Usage | TanStack Blog TypeScript Performance in TanStack Table V9 | TanStack Blog TanStack AI Beta: The Switzerland of AI Tooling Grows Up | TanStack Blog TanStack Table V9: Taking Form | TanStack Blog TanStack AI: Your MCP, your way | TanStack Blog TanStack Start Adds First-Class Rsbuild Support | TanStack Blog Introducing Experimental Workflows and Orchestrators in TanStack AI | TanStack Blog Chat UIs Are Lists Until They Aren't | TanStack Blog Structured Output That Remembers Across Turns | TanStack Blog TanStack Virtual just got a lot faster, and finally handles iOS | TanStack Blog TanStack AI now fully speaks AG-UI | TanStack Blog Stop Waiting on JSON: Stream Structured Output with One Schema | TanStack Blog Hardening TanStack After the npm Compromise | TanStack Blog Postmortem: TanStack npm supply-chain compromise | TanStack Blog Who Owns the Tree? RSC as a Protocol, Not an Architecture | TanStack Blog TanStack AI Just Learned to Compose Music | TanStack Blog Your AI Tool Calls Should Fail at Compile Time, Not in Production | TanStack Blog One Flag, Every Chunk: Debug Logging Lands in TanStack AI | TanStack Blog
Lazy Tool Discovery: Scaling AI Tool Systems Without Drow...
Alem Tuzlak · 2026-03-12 · via TanStack Blog

by Alem Tuzlak on Mar 12, 2026.

Lazy Tool Discovery

If you've built an AI-powered application with more than a handful of tools, you've probably hit the wall: every tool definition you send to the LLM costs tokens, eats into the context window, and — past a certain point — actually makes the model worse at picking the right tool. More tools means more noise, slower responses, and higher bills.

Today we're shipping lazy tool discovery in TanStack AI, a mechanism that lets the LLM discover tools on demand instead of receiving all of them upfront.

Consider a customer support agent with 30 tools: ticket lookup, order management, refund processing, knowledge base search, escalation workflows, analytics queries, and more. On any given request, the user probably needs 2–3 of these. But the LLM sees all 30 tool definitions on every single call.

This creates three problems:

  1. Token waste. Tool definitions with descriptions and JSON schemas add up fast. Thirty detailed tools can easily burn 3,000–5,000 tokens before the conversation even starts.
  2. Decision fatigue. LLMs perform better with fewer, more relevant options. Research consistently shows that tool selection accuracy degrades as the number of available tools grows.
  3. Inflexibility. You either send everything or build your own routing layer to pre-filter tools. Neither option is great.

Lazy tool discovery adds a single flag to tool definitions:

That's it. Tools marked lazy: true are withheld from the LLM. In their place, the LLM sees a single synthetic tool called __lazy__tool__discovery__ whose description lists the names of all available lazy tools.

When the LLM decides it needs a tool, the flow looks like this:

  1. The LLM sees the discovery tool: "You have access to additional tools: [searchProducts, compareProducts, calculateFinancing]"
  2. The LLM calls the discovery tool: { toolNames: ["searchProducts"] }
  3. The discovery tool returns the full description and JSON schema for searchProducts
  4. searchProducts is injected as a normal tool in the next iteration
  5. The LLM calls searchProducts directly with actual arguments

From the LLM's perspective, it asked about a tool, learned what it does, and then used it. From your perspective, you saved tokens on every request where that tool wasn't needed.

When you pass tools to chat(), the engine separates them into eager tools (the default) and lazy tools. A LazyToolManager class handles the rest:

  • Separation: Eager tools are sent to the LLM immediately. Lazy tools are held back.
  • Discovery tool: If any lazy tools exist, a synthetic discovery tool is created and included in the tool set. Its description contains the names of all lazy tools so the LLM knows what's available.
  • Dynamic injection: When the LLM discovers a tool, it's added to the active tool set for the next agent loop iteration. The LLM then sees it as a regular tool with full schema — no proxy, no indirection.
  • Multi-turn memory: On each chat() call, the manager scans the message history for previous discovery results. Tools discovered in earlier turns are automatically pre-populated — the LLM doesn't need to re-discover them.
  • Self-correction: If the LLM tries to call a lazy tool it hasn't discovered yet (LLMs sometimes skip steps), it gets a helpful error: "Tool 'searchProducts' must be discovered first. Call lazytooldiscovery with toolNames: ['searchProducts'] to discover it." The LLM self-corrects on the next iteration.
  • Auto-cleanup: When all lazy tools have been discovered, the discovery tool removes itself from the active set. No unnecessary clutter.

If none of your tools have lazy: true, the behavior is identical to before. No discovery tool is created, no extra processing happens, no code paths change. The feature is entirely opt-in.

Here's a guitar store chat application with a mix of eager and lazy tools:

When a user asks "recommend me a guitar", the LLM sees getGuitars, recommendGuitar, and __lazy__tool__discovery__. It calls the first two and never touches discovery. Tokens saved.

When a user asks "compare the Motherboard Guitar and the Racing Guitar", the LLM sees the discovery tool, discovers compareGuitars, and calls it. One extra round-trip, but only when the feature is actually needed.

When a user follows up with "how much would the cheaper one cost per month?", the LLM has compareGuitars already available (from the earlier discovery) and discovers calculateFinancing. The conversation builds naturally without re-discovering tools.

Lazy discovery makes sense when:

  • You have many tools and most aren't needed in every conversation
  • Some tools are niche — advanced search, analytics, admin functions, reporting
  • Tool descriptions are verbose — detailed schemas with many properties
  • You're cost-conscious — fewer tokens per request means lower bills

Keep tools eager (the default) when:

  • They're called in most conversations
  • The total tool count is small (under ~10)
  • Latency is critical and the extra discovery round-trip matters

A good rule of thumb: if a tool is used in less than 30% of conversations, it's a strong candidate for lazy: true.

Lazy tool discovery is available now in @tanstack/ai. Add lazy: true to any tool definition and you're done.

We're exploring a few follow-on improvements:

  • Grouped discovery: Discover related tools together (e.g., all analytics tools at once)
  • Cost tracking: Surface token savings from lazy tools in DevTools
  • Smarter descriptions: Let the discovery tool description include one-line summaries per lazy tool, not just names

Check out the full documentation for details, or try it out in the ts-react-chat example which includes three lazy tools with test prompts.


TanStack AI is an open-source, provider-agnostic AI SDK for building type-safe AI applications. Get started here.