Tool Execution
The ToolRegistry discovers your tools, generates schemas for the LLM, and executes tool calls when the LLM requests them.
Setup
Call ToolRegistry().discover(self) in __init__ to register all @function_tool methods.
discover(self) scans the agent for methods decorated with @function_tool().
Calling the LLM with Tools
Pass tool_registry.get_schemas() to give the LLM your tool definitions.
The LLM may respond with text, tool calls, or both.
Handling Tool Calls
A turn may take multiple LLM calls: the model may call a tool, then — once it sees the result — decide to call another tool before producing the final spoken response. Wrap the LLM call in a loop and exit when the model stops requesting tools.
Key points:
tc.to_dict()returns the canonical OpenAI-format tool-call dict — no need to construct it field by field.result.contentis a string. The registry runs your@function_toolreturn value throughjson.dumps(for dicts, lists) orstr()(for everything else) before populating it.MAX_TOOL_ROUNDScaps the loop so a misbehaving LLM can’t run away calling tools forever. Four rounds covers every realistic conversation; raise it only if you have a concrete reason.
ToolRegistry API
Parallel Execution
By default, tools run in parallel when the LLM requests multiple:
[!WARNING] If your tools have dependencies—e.g.,
get_user_id()returns a value needed byget_user_orders(user_id)—usingparallel=Truewill break because both tools run simultaneously. Useparallel=Falsefor dependent tools.
Tips
Always use parallel=True
Unless your tools have dependencies on each other, parallel execution is faster.
Check for tool_calls before executing
The LLM doesn’t always call tools. Only run the execution code if tool_calls is non-empty.
Log tool calls for debugging
Print tc.name and tc.arguments before execution to debug unexpected behavior.

