Web Search
The WebSearch capability gives your agent web search. Like all provider-adaptive tools, it uses the provider’s native web search when the model supports it and can fall back to a local implementation on other models.
WebSearch defaults to native-only. Backed by WebSearchTool on the native side (see Web Search Tool for provider support and configuration) — pass native=WebSearchTool(...) directly when you need full control over the native instance.
For the local side, pass local='duckduckgo' (or local=True) for a DuckDuckGo fallback (requires the duckduckgo optional group); for other search providers, use a Tavily wrapper from common_tools, the ExaSearchToolset from the Pydantic AI Harness, or any callable, Tool, or AbstractToolset.
Native configuration fields: search_context_size, user_location, blocked_domains, allowed_domains,
max_uses, and OpenAI Responses’ external_web_access. The domain and max_uses constraints require a native web
search that applies them, as does external_web_access=False, because a local fallback cannot guarantee cached or
indexed-only search. On a model whose native search can’t apply one that is set (Gemini applies none of them; see
restricting parameters), WebSearch raises a
UserError rather than searching without the restriction.
Setting these fields on WebSearch itself disables the local fallback, since the bundled local tools can’t apply
them. To fall back to a local search that applies the restriction itself on such models, put the restriction on the
native tool instead:
from pydantic_ai.capabilities import WebSearch
from pydantic_ai.native_tools import WebSearchTool
def search_pydantic_docs(query: str) -> str:
"""Search pydantic.dev only."""
return f'pydantic.dev results for {query}'
web_search = WebSearch(native=WebSearchTool(allowed_domains=['pydantic.dev']), local=search_pydantic_docs)
from pydantic_ai.capabilities import WebSearch
# Native-only — raises on models without native web search
WebSearch()
# Native preferred; DuckDuckGo fallback (needs `pydantic-ai-slim[duckduckgo]`)
WebSearch(local='duckduckgo')
# Native preferred; custom callable as fallback
def my_search(query: str) -> str: ...
WebSearch(local=my_search)