Repository: pydantic/pydantic-ai
File: pydantic_ai_slim/pydantic_ai/builtin_tools.py (Python)

Code before:
    """Built-in tool identifier, this should be available on all built-in tools as a discriminator."""

    def __init_subclass__(cls, **kwargs: Any) -> None:
        super().__init_subclass__(**kwargs)
        _BUILTIN_TOOL_TYPES[cls.kind] = cls

    @classmethod
    def __get_pydantic_core_schema__(
        cls, _source_type: Any, handler: pydantic.GetCoreSchemaHandler
    ) -> core_schema.CoreSchema:
        if cls is not AbstractBuiltinTool:
            return handler(cls)

        tools = _BUILTIN_TOOL_TYPES.values()
        if len(tools) == 1:  # pragma: no cover
            tools_type = next(iter(tools))
        else:
            tools_annotated = [Annotated[tool, pydantic.Tag(tool.kind)] for tool in tools]
            tools_type = Annotated[Union[tuple(tools_annotated)], pydantic.Discriminator(cls._tool_discriminator)]  # noqa: UP007

        return handler(tools_type)

    @staticmethod
    def _tool_discriminator(tool_data: dict[str, Any] | AbstractBuiltinTool) -> str:
        if isinstance(tool_data, dict):
            return tool_data.get('kind', AbstractBuiltinTool.kind)
        else:
            return tool_data.kind


@dataclass(kw_only=True)
class WebSearchTool(AbstractBuiltinTool):
    """A builtin tool that allows your agent to search the web for information.

    The parameters that PydanticAI passes depend on the model, as some parameters may not be supported by certain models.

    Supported by:

    * Anthropic
    * OpenAI Responses
    * Groq
    * Google
    """

    search_context_size: Literal['low', 'medium', 'high'] = 'medium'
    """The `search_context_size` parameter controls how much context is retrieved from the web to help the tool formulate a response.

    Supported by:

    * OpenAI Responses
    """

Review comment (bug):
Feels like we should raise an error if there is no value for `kind` here, I worry that the error will be confusing if you have data that refers to a builtin tool that hasn't been imported or doesn't exist. Obviously this could happen if you create custom ones, which is weird, but it could also happen if we add new ones in the future and you have a temporal worker running an older version than was used to generate the tool call. (Still a bug, but less exotic of circumstances to create it.)

Either way, all I care about is that we get reasonable behavior if you try to reference an unknown tool. I think it probably should be an error if you reference an unknown tool rather than silently ignoring it, and if it does error, the error message should clearly identify the cause and possible resolution (something like "no builtin tool was found with kind '...', did you import it?" or "tool data must have a kind field, but it was not found" or similar).

Code after:
    """Built-in tool identifier, this should be available on all built-in tools as a discriminator."""

    def __init_subclass__(cls, **kwargs: Any) -> None:
        super().__init_subclass__(**kwargs)
        _BUILTIN_TOOL_TYPES[cls.kind] = cls

    @classmethod
    def __get_pydantic_core_schema__(
        cls, _source_type: Any, handler: pydantic.GetCoreSchemaHandler
    ) -> core_schema.CoreSchema:
        if cls is not AbstractBuiltinTool:
            return handler(cls)

        tools = _BUILTIN_TOOL_TYPES.values()
        if len(tools) == 1:  # pragma: no cover
            tools_type = next(iter(tools))
        else:
            tools_annotated = [Annotated[tool, pydantic.Tag(tool.kind)] for tool in tools]
            tools_type = Annotated[Union[tuple(tools_annotated)], pydantic.Discriminator(_tool_discriminator)]  # noqa: UP007

        return handler(tools_type)


@dataclass(kw_only=True)
class WebSearchTool(AbstractBuiltinTool):
    """A builtin tool that allows your agent to search the web for information.

    The parameters that PydanticAI passes depend on the model, as some parameters may not be supported by certain models.

    Supported by:

    * Anthropic
    * OpenAI Responses
    * Groq
    * Google
    """

    search_context_size: Literal['low', 'medium', 'high'] = 'medium'
    """The `search_context_size` parameter controls how much context is retrieved from the web to help the tool formulate a response.

    Supported by:

    * OpenAI Responses
    """

    user_location: WebSearchUserLocation | None = None
    """The `user_location` parameter allows you to localize search results based on a user's location.

    Supported by:

    * Anthropic