Dynamic Tools
Static tool registries break in multi-tenant agents — an admin tool visible to a free user is an auth bug. Learn when dynamic filtering is worth the middleware complexity, which of the four strategies to pick, and how LangChain's built-in LLMToolSelectorMiddleware handles the hardest case automatically.
Quick Reference
- →Dynamic tools = intercept request.tools inside @wrap_model_call before the LLM call fires
- →All tools must be registered at create_agent() time — middleware only filters, not adds (for most cases)
- →Four strategies: by State (session auth), by Store (persistent user flags), by Context (request-time role), by Stage (message count)
- →LLMToolSelectorMiddleware: LangChain's built-in — runs a fast LLM to pick semantically relevant tools
- →Runtime registration (DynamicToolMiddleware) requires BOTH wrap_model_call (inject) + wrap_tool_call (execute)
- →Filtering to zero tools causes an infinite loop — always guarantee at least one tool survives
- →Each tool schema costs ~50 tokens; filtering 15→5 saves ~500 tokens/call = $15/day at 10K calls
When NOT to Use Dynamic Tools
Dynamic tool filtering adds a middleware layer that runs on every LLM call. Before building it, verify you have an actual problem.
| Situation | Do you need dynamic filtering? |
|---|---|
| Fewer than 10 tools total | No — the model handles this fine statically |
| All users have the same permissions | No — one tool set, no filtering needed |
| Tools differ by feature (not auth) | Maybe — only if tool count causes errors or cost spikes |
| Different roles have genuinely different tool access | Yes — auth filtering prevents privilege escalation |
| 20+ tools and only 5 are relevant per call | Yes — token cost and error rate will be measurable |
| Tools loaded from MCP or a remote registry at runtime | Yes — requires DynamicToolMiddleware, the advanced pattern |
Every filtering rule is a piece of auth logic that can go wrong silently. A bug that hides a tool from users who should have it will look like a product bug, not a code bug. Build filtering only when the absence of it causes a concrete problem — auth exposure, error rate increase, or token cost spike you can measure.