Registering dynamic tools via Middleware which are not dict or functions throws error because of this logic. It suggests to assign tools via middleware.tools attribute. However it is a class level attribute and makes the middleware stateful.
If this logic is ignored for dict/functions as tools, does it need to be applied for BaseTool? Should this validation be configurable to support dynamic tools?
# Check if any requested tools are unknown CLIENT-SIDE tools
unknown_tool_names = []
for t in request.tools:
# Only validate BaseTool instances (skip built-in dict tools)
if isinstance(t, dict):
continue
if isinstance(t, BaseTool) and t.name not in available_tools_by_name:
unknown_tool_names.append(t.name)
if unknown_tool_names:
available_tool_names = sorted(available_tools_by_name.keys())
msg = (
f"Middleware returned unknown tool names: {unknown_tool_names}\n\n"
f"Available client-side tools: {available_tool_names}\n\n"
"To fix this issue:\n"
"1. Ensure the tools are passed to create_agent() via "
"the 'tools' parameter\n"
"2. If using custom middleware with tools, ensure "
"they're registered via middleware.tools attribute\n"
"3. Verify that tool names in ModelRequest.tools match "
"the actual tool.name values\n"
"Note: Built-in provider tools (dict format) can be added dynamically."
)
raise ValueError(msg)
Use Case:
- Agent is created without any tools
- Middleware gets the tools from MCP server which are dependent on runtime.context.user_name.
- MCPServer.getTools() requires user header (and hence these are dynamic)