Are dynamic tool lists allowed when using create_agent?

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)