PydanticAI 原生工具(Native Tools)实战指南:Web 搜索、代码执行与 Provider 自适应能力的选择
【免费下载链接】pydantic-aiHow Python does AI. Agents, realtime voice, image generation, embeddings. Every model, every interface, typed end to end.项目地址: https://gitcode.com/GitHub_Trending/py/pydantic-ai
本指南围绕 PydanticAI 仓库中的 NATIVE-TOOLS.md 参考文档展开,系统讲解如何通过
NativeTool能力为 Agent 接入厂商原生的 Web 搜索、网页抓取、代码执行、图像生成、记忆、MCP 服务器与文件检索等工具,并深入对比「原生工具」与「Provider 自适应能力」两类方案的适用场景。读完你将掌握原生工具的最小接入写法、动态配置技巧、关键参数含义,以及基于仓库源码理解其底层注册与解析机制。
什么是 Native Tools
PydanticAI 将「由模型厂商(Provider)在服务端直接提供、无需本地实现」的一类工具统称为Native Tools,典型代表包括 Web 搜索(web search)、网页抓取(web fetch)、代码执行(code execution)、记忆(memory)和文件检索(file search)等。与本地编写的@agent.tool函数不同,原生工具由模型 API 原生承载,调用发生在服务端,PydanticAI 只负责把工具配置序列化并随请求一起发送。
在仓库源码中,所有原生工具都继承自 AbstractNativeTool 这个抽象基类,它定义了三个对所有原生工具通用的核心属性:
kind:原生工具的类型标识(如'web_search'、'code_execution'),同时作为 Pydantic 判别联合(discriminated union)的判别字段;optional:是否为「尽力而为」的升级项。为True时,若模型不支持该原生工具则被静默丢弃(适用于存在本地兜底工具的场景);默认False,模型不支持时直接报错——用户显式要求了它,就应该大声失败而不是悄悄替换行为;unique_id/label:分别用于本地兜底工具的unless_native关联判定与 UI 展示。
此外,基类通过__init_subclass__自动把每个工具子类注册进全局注册表NATIVE_TOOL_TYPES(按kind字符串索引),这就是后续NativeTool.from_spec()能够按kind反序列化出具体工具实例的原因(见 native_tools/init.py)。
快速上手:给 Agent 添加 Web 搜索或代码执行
原生工具统一通过NativeTool能力包装,并以capabilities=[...]参数传给Agent。NativeTool是定义在 capabilities/native_tool.py 中的一个 dataclass,其唯一字段tool接受一个静态的AbstractNativeTool实例,或一个能动态产出工具实例的可调用对象;get_native_tools()返回的就是[self.tool]。
文档给出的最小示例是给 Agent 挂上 Web 搜索:
from pydantic_ai import Agent from pydantic_ai.capabilities import NativeTool from pydantic_ai.native_tools import WebSearchTool agent = Agent('openai-responses:gpt-5.2', name='web_search_agent', capabilities=[NativeTool(WebSearchTool())]) result = agent.run_sync('Give me a sentence with the biggest news in AI this week.') print(result.output)这里有两个关键点需要特别注意:
- 模型前缀:使用 OpenAI 的 Web 搜索必须走 Responses API,即模型 ID 前缀为
openai-responses:,而不是openai:。这是因为该原生工具依赖 Responses API 的web_search工具,旧式 Chat Completions 接口不提供等价能力。 - 限制实时外网访问:如需把 OpenAI Responses 的 Web 搜索限制为只使用缓存或已索引内容,可在
WebSearch能力或WebSearchTool上设置external_web_access=False。源码注释进一步说明(见 native_tools/init.py):None表示省略该参数、采用厂商默认(OpenAI 当前默认True),且 OpenAI 旧版web_search_preview工具会忽略此参数。
原生工具清单:默认可用的八类工具
当厂商支持时,以下是文档推荐的默认原生工具(源码实现均位于 pydantic_ai_slim/pydantic_ai/native_tools/init.py):
| 工具类 | kind | 支持厂商(来自源码 docstring) | 核心用途 |
|---|---|---|---|
WebSearchTool | web_search | Anthropic、OpenAI Responses、Groq、Google、xAI、OpenRouter | 服务端 Web 搜索 |
WebFetchTool | web_fetch | Anthropic、Google | 抓取指定 URL 内容 |
CodeExecutionTool | code_execution | Anthropic、OpenAI Responses、Google、Bedrock (Nova2.0)、xAI | 在隔离环境执行代码 |
ImageGenerationTool | image_generation | OpenAI Responses、Google | 生成/编辑图像 |
MemoryTool | memory | Anthropic | 跨会话记忆 |
MCPServerTool | mcp_server | OpenAI Responses、Anthropic、xAI | 直连 MCP 服务器 |
FileSearchTool | file_search | OpenAI Responses、Google (Gemini)、xAI | 基于向量检索的托管 RAG |
AdvisorTool | advisor | Anthropic、OpenRouter | 让快速的执行模型在生成中咨询更强的顾问模型 |
WebSearchTool 参数详解
WebSearchTool是参数最丰富的原生工具,全部为kw_only可选字段,PydanticAI 会按模型能力决定实际传递哪些参数:
search_context_size:'low' | 'medium' | 'high',默认'medium',控制从 Web 检索的上下文量(OpenAI Responses、OpenRouter 支持);user_location:WebSearchUserLocation类型,用于按用户地理位置本地化搜索结果(Anthropic、OpenAI Responses、xAI、OpenRouter 支持)。该 TypedDict 包含city、country(OpenAI 与 xAI 要求 2 字母 ISO 3166-1 alpha-2 国家码,如'US')、region、timezone四个可选键;blocked_domains/allowed_domains:域名过滤列表,二者在 Anthropic 上互斥、只能使用其一;max_uses:搜索次数上限。注意 OpenRouter 仅在非原生搜索引擎或 Anthropic 原生搜索下生效,其他原生厂商会忽略;external_web_access:是否允许抓取实时网络内容,False表示仅用缓存/索引结果(仅 OpenAI Responses 的web_search工具支持)。
其余工具的关键参数速览
- WebFetchTool(
web_fetch):max_uses、allowed_domains/blocked_domains(Anthropic 上互斥)、enable_citations(默认False)、max_content_tokens等,其中enable_citations与max_content_tokens目前仅 Anthropic 支持。 - CodeExecutionTool(
code_execution):唯一的可选字段files用于向执行环境注入上传文件(仅 Anthropic、OpenAI Responses 使用;其他厂商的文件会被忽略)。 - ImageGenerationTool(
image_generation):参数极多,包括action('generate' | 'edit' | 'auto')、background、input_fidelity、moderation、model(已知 OpenAI 图像模型gpt-image-2、gpt-image-1.5、gpt-image-1、gpt-image-1-mini)、output_format('png' | 'webp' | 'jpeg')、output_compression、partial_images(0–3,流式部分图)、quality、size(OpenAI:1024x1024等;Google Gemini:512/1K/2K/4K)、aspect_ratio(21:9、16:9、4:3、3:2、1:1、9:16、3:4、2:3、5:4、4:5)。 - MCPServerTool(
mcp_server):必填id(唯一标识,其unique_id为kind:id形式)与url(OpenAI 可用x-openai-connector:<connector_id>指定 connector),可选authorization_token、description、allowed_tools、headers。 - FileSearchTool(
file_search):必填file_store_ids(OpenAI 为 vector store ID、Google 为 Files API 存储名、xAI 为 collection ID),可选max_num_results、instructions、retrieval_mode('hybrid' | 'semantic' | 'keyword',xAI 服务端默认hybrid)。 - AdvisorTool(
advisor):必填model(Anthropic 上使用模型 ID,如claude-opus-4-8;OpenRouter 上使用目录 slug,如anthropic/claude-opus-4.8),可选max_uses(每次请求上限而非每次运行预算)、max_tokens(下限 1024,低于该值构造时会抛出ValueError)、caching('5m' | '1h'的临时上下文缓存 TTL,OpenRouter 不支持)。
动态原生工具配置:根据请求按需装配
当原生工具的具体配置依赖当前用户或请求上下文时,文档推荐把「准备函数(prepare function)」包装进NativeTool(...):该函数接收RunContext,返回一个工具实例或None。返回None意味着本轮不提供该工具。
from pydantic_ai import Agent, RunContext from pydantic_ai.capabilities import NativeTool from pydantic_ai.native_tools import WebSearchTool async def prepared_web_search(ctx: RunContext[dict]) -> WebSearchTool | None: if not ctx.deps.get('location'): return None return WebSearchTool(user_location={'city': ctx.deps['location']}) agent = Agent( 'openai-responses:gpt-5.2', name='dynamic_web_search_agent', capabilities=[NativeTool(prepared_web_search)], deps_type=dict, )上面的示例中,只有deps里携带了location时,Agent 才会装配带user_location定位的 Web 搜索;否则该工具被整体省略。这正是 NativeOrLocalTool 中native字段可接受「可调用工厂」这一设计的体现——工厂返回None时原生工具被跳过。
fallback_subagent_model 下的例外行为
文档特别强调了一个反直觉的边界情况:当XSearch或ImageGeneration能力设置了fallback_subagent_model时,不支持的模型会被路由到子代理(subagent)执行,而不是退化为本地工具;同时它们的native=工厂会在子代理运行时被第二次解析。
这意味着:一旦设置了fallback_subagent_model,prepare 函数返回None不再表示「省略工具」——子代理工具依然保持提供状态,此时调用它会抛出UserError。正确的做法是:要么返回一个配置好的工具实例,要么干脆移除fallback_subagent_model。从源码看,这与 NativeOrLocalTool._resolve_native_with_overrides 的处理一致:工厂解析结果为None时直接抛出UserError,而不会悄悄替换为默认实例。
Native Tools vs Provider-Adaptive Capabilities:如何选择
这是文档的核心决策点,两条路线对应不同的源码基类:
路线一:Provider 自适应能力(推荐默认)
from pydantic_ai import Agent from pydantic_ai.capabilities import WebSearch agent = Agent('anthropic:claude-sonnet-4-6', name='adaptive_web_search_agent', capabilities=[WebSearch()])WebSearch、WebFetch、MCP、ImageGeneration都继承自 NativeOrLocalTool。该基类的设计是「原生 + 本地兜底」配对:模型支持原生工具时移除本地兜底(通过给本地工具定义打上unless_native标记实现,见 native_or_local.py);模型不支持时则移除原生工具、保留本地工具。例如WebSearch的_default_local()会自动装配 DuckDuckGo 本地搜索(需要pip install "pydantic-ai-slim[duckduckgo]",local=True等价于local='duckduckgo',见 capabilities/web_search.py)。约束类字段(如allowed_domains、external_web_access=False)由_requires_native()标记为「必须原生」,此时本地兜底被抑制、模型不支持则直接抛UserError。
适合选择此路线的场景:
- 代码需要跨厂商运行;
- 原生支持缺失时希望有本地兜底;
- 用户尚未确定使用哪家 Provider。
路线二:直接使用原生工具(NativeTool(WebSearchTool(...)))
适合选择此路线的场景:
- 用户明确要求厂商原生行为;
- 需要厂商特定的配置(如
WebSearchTool(user_location=...)、域名过滤、search_context_size等); - 用户已经选定了支持该工具的厂商。
一个实用经验:当WebSearch这类自适应能力无法表达原生工具的全部参数时,就用NativeTool(WebSearchTool(...))直连;当需要跨厂商可移植性时,则回到WebSearch()。
深入源码:工具注册、反序列化与配置校验
从源码结构可以进一步梳理出原生工具体系的几个底层机制:
- 自动注册表:
NATIVE_TOOL_TYPES由__init_subclass__在每个工具类定义时自动填充;SUPPORTED_NATIVE_TOOLS是全部原生工具类型的 frozenset,NATIVE_TOOLS_REQUIRING_CONFIG则标记了必须显式配置的工具(FileSearchTool、MCPServerTool、MemoryTool、AdvisorTool、内部ToolSearchTool),见 native_tools/init.py。 - YAML/Spec 反序列化:
NativeTool.from_spec()支持两种 YAML 形式——扁平式{NativeTool: {kind: web_search, search_context_size: high}}与显式式{NativeTool: {tool: {kind: web_search}}},内部通过pydantic.TypeAdapter(AbstractNativeTool)与基于kind的判别器完成实例化(见 capabilities/native_tool.py),这为声明式/配置文件驱动地装配 Agent 提供了通道。 - 自校验规则:多个工具在构造时即校验非法组合,例如
XSearchTool不允许同时设置allowed_x_handles与excluded_x_handles、单边列表最多 20 个 handle(见 native_tools/init.py),AdvisorTool要求max_tokens >= 1024。
仓库测试中也覆盖了相关行为,例如 tests/test_native_tool_search_vcr.py 与 tests/test_thinking_native_tools.py 验证了原生工具与思考过程、工具搜索等能力的协同路径,可作为深入理解实现细节的入口。
小结
原生工具把搜索、抓取、代码执行、图像生成等重活交给模型厂商的服务端完成,PydanticAI 通过统一的AbstractNativeTool基类与NativeTool能力把它们接入 Agent。接入时只需记住三个要点:用capabilities=[NativeTool(SomeTool())]装配;OpenAI 系列原生工具走openai-responses:前缀模型;需要按请求动态装配时把 prepare 函数包装进NativeTool。至于「原生直连」还是「自适应能力」,则取决于你是否已经锁定厂商、是否需要本地兜底——这也正是NativeOrLocalTool系列能力与NativeTool二者设计分工的本质。
【免费下载链接】pydantic-aiHow Python does AI. Agents, realtime voice, image generation, embeddings. Every model, every interface, typed end to end.项目地址: https://gitcode.com/GitHub_Trending/py/pydantic-ai
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考