Overview
DynamicToolLoader keeps tools deferred: registered and executable, but absent from the schema list sent to the model. One extra tool is always present — tool_search — which matches the catalog by name and description and loads what it finds. Loaded tools stay loaded for the rest of the run and become callable on the next request.
Tool definitions live in the prompt’s cached prefix, so a large tool set is paid for on every call. Selection accuracy also degrades as the list grows: a model choosing among 80 tools chooses worse than one choosing among 8.
Import
Agent(dynamic_tools=True) builds it and exposes it as agent.tool_loader. See Dynamic Tool Loading for the agent-level guide.
Constructor
Iterable[Callable]
default:"()"
Callables to defer. Each is converted to an OpenAI function schema once, at registration.
Iterable[Dict[str, Any]]
default:"()"
Pre-built schemas to defer, for tools that have no local callable — MCP tools, for instance.
Iterable[Dict[str, Any]]
default:"()"
Schemas that are never deferred. Control-flow tools belong here: an agent that has to search for its own
complete_task cannot finish.Module Constants
str
default:"tool_search"
The reserved name of the search tool. Registering a tool under this name is refused with a warning.
Dict[str, Any]
The OpenAI function schema for
tool_search. Takes a required query string and an optional max_results integer. Its description instructs the model to load everything it expects to need in a single call.str
The system-prompt block appended once when deferral activates, headed
## MOST TOOLS ARE NOT LOADED. Tells the model that its visible tool list describes what exists, not what it can call right now.Methods
register
Defer one or more Python callables. Chainable;None entries are filtered out.
Callable
required
One or more callables. Each is converted to an OpenAI function schema at registration time.
DynamicToolLoader
The same loader, for chaining.
register_schema
Defer a pre-built OpenAI function schema, optionally binding a local callable to it.Dict[str, Any]
required
An OpenAI function schema. A schema with no
function.name is ignored.Optional[Callable]
default:"None"
The callable that executes this tool. Leave as
None for remotely-dispatched tools such as MCP.DynamicToolLoader
The same loader, for chaining.
search
Rank catalog entries against a query. Does not load anything.str
required
Keywords, or
select:name1,name2 for exact names.int
default:"5"
Maximum results returned.
float
default:"0.0"
Drop results scoring below this fraction of the best score.
0.0 keeps every match, which suits an explicit search where the model said what it wanted. Speculative callers should raise it — a long query contains enough common words to give weak matches a nonzero score.List[DeferredTool]
Matching catalog entries, best first. Empty when nothing matches.
load
Mark tools as loaded by name.Iterable[str]
required
Catalog names to load. Unknown names are ignored.
List[DeferredTool]
Only the tools that were newly loaded by this call.
run_search
Thetool_search handler: search, load, and report. This is what the model’s tool call invokes.
str
required
Keywords, or
select:name1,name2 for exact names.int
default:"5"
Maximum tools to load. A falsy value (
0 or None) silently becomes 5.float
default:"0.0"
Relative score cutoff, as in
search.str
A compact listing — one
name: description line per match, then a blank line, then either Loaded N: a, b. They are callable from your next turn. or All already loaded - call them directly. On a miss, the available tool names plus a hint to retry with select:.The result deliberately returns summaries rather than full schemas. The schemas are already going out in the request’s tool array — repeating them here would pay for them twice.
schemas
The tool list to send with the next request.List[Dict[str, Any]]
always_loaded first, then SEARCH_TOOL_SCHEMA, then every loaded tool sorted by name.handlers
Name-to-callable mapping for dispatch.Dict[str, Callable]
Every loaded tool that has a local callable. Schema-only entries such as MCP tools are excluded by design — they are dispatched through the MCP manager.
catalog_listing
Every deferred tool, one per line. Useful for prompts and debugging.str
Name-sorted
name: first line of description lines for the whole catalog.Properties
List[str]
Sorted names of tools that have been loaded.
List[str]
Sorted names of tools still deferred.
List[Dict[str, Any]]
The never-deferred schemas passed to the constructor. A public mutable list.
Dunder Methods
The Search Algorithm
Matching is deliberately simple: token overlap, with a name match worth more than a description match. That is enough for the catalog sizes this targets, has no dependencies, and is deterministic — so it can be tested. Swap in embeddings only when this measurably fails.1
Handle select:
A query starting with
select: splits the remainder on commas and returns those exact catalog entries immediately — unranked, ignoring both limit and min_score_ratio. If none of the names match, the loader falls through to a keyword search over the guessed names rather than returning nothing.2
Tokenize
Non-alphanumeric characters become spaces, so
get_weather yields get and weather. Everything is lowercased, then single characters and stopwords are dropped.3
Score
Each catalog entry scores 3 points for a name-token match and 1 point for a description or parameter-name match, summed across the query’s terms. Entries scoring zero are dropped.
4
Sort and cut
Sort by descending score, then by name for stability. If
min_score_ratio > 0, drop anything below best_score * min_score_ratio. Return the first limit results.Searchable Surface
An entry matches on its name, its description, and its parameter property names. Searching"recipient subject" finds a send_email(recipient, subject, body) tool even if neither word appears in its description.
Stopwords
Common words and single characters are filtered before matching:"weather in a city" would match every tool whose description contains "a" — loading the whole catalog and defeating the point.
DeferredTool
One catalog entry: what it is, how to call it, and how to run it.str
Property.
"name: first line of description", or just the name when the description is empty. This is the line shown in search results.List[str]
Property. The lowercased tokens this entry can be matched on — drawn from its name, description, and parameter property names.
Usage Example
Wiring It to a Custom Loop
Two steps: passloader.schemas() as the tool list, and re-read it after each tool_search call so newly loaded tools are sent with the next request.
Related Pages
- Dynamic Tool Loading — the agent-level guide
- Dynamic Tool Usage examples — runnable end-to-end scripts
- Agent API reference —
dynamic_tools,setup_dynamic_tools,defer_tool_schemas,defer_mcp_tools - Tools API reference — schema conversion and execution
Source
swarms/tools/dynamic_tool_loader.py on GitHub