Gemini 工具组合:一次请求混用内置工具与自定义函数,模型自己排调用顺序
大多数真正能干活的智能体,一次任务里需要好几个工具配合。一个 DevOps 智能体发现了 CVE 漏洞,还需要顺手在内部系统里建一张工单。直到最近,这类交接要么得你自己写编排逻辑,要么只能在自定义工具里绕开内置工具。
Gemini API 的工具组合(tool combination)能力改变了这一点:现在可以在同一次请求里,把内置工具与自定义函数声明(function declarations)组合起来用。由 Gemini 自己决定调用哪些工具、按什么顺序调用,并在工具之间自动传递上下文。
下面是两个可以直接复现的工具组合示例。
示例一:函数调用与内置工具的组合
在同一个请求里组合 Google 搜索、URL 上下文读取和一个自定义函数。模型自己去网上搜索、读完页面、调用你的函数——全程不需要你指定顺序。
先准备环境:申请一个 Gemini API 密钥,然后安装官方 SDK:
pip install google-genai
接着定义一个自定义函数,把它与内置工具一起传入:
from google import genai
client = genai.Client()
file_incident = {
"type": "function",
"name": "file_incident",
"description": "Files a security incident in the internal tracking system.",
"parameters": {
"type": "object",
"properties": {
"cve_id": {"type": "string", "description": "CVE identifier"},
"severity": {"type": "string", "description": "Critical, High, Medium, or Low"},
"summary": {"type": "string", "description": "Brief description of the vulnerability"},
},
"required": ["cve_id", "severity", "summary"],
},
}
interaction = client.interactions.create(
model="gemini-3-flash-preview",
input="Search for the latest critical CVE affecting react, read the full advisory page, and file an incident for it.",
tools=[
{"type": "google_search"},
{"type": "url_context"},
{"type": "function", "name": "file_incident", "parameters": ...},
],
)
for output in interaction.outputs:
print(f"{output.type}...")
if output.type == "function_call":
print(f"Function: {output.name}")
print(f"Arguments: {output.arguments}")
运行这段代码,你会看到输出按顺序滚动:先是一轮 google_search_call 与 google_search_result,接着又是一轮搜索调用与结果,然后是一个 thought,最后是 function_call。模型自己完成了”搜索最新 React 严重漏洞 → 打开完整公告页读取细节 → 调用 file_incident 建工单”的全链条,函数收到的参数是结构化好的真实数据:CVE 编号 CVE-2025-55182、严重级别 Critical,以及一段从公告页提炼的漏洞摘要——React Server Components 的不安全反序列化漏洞,影响 19.0 到 19.2.0 版本,攻击者可通过构造 HTTP 请求执行任意代码。
这就是工具组合的实际价值:搜索结果和页面内容作为上下文自动流向了你的自定义函数,你写的只有函数声明本身。
动手验证时可以对比旧做法:先单独调一次搜索 API,把结果手工拼进第二次请求,再手动触发函数调用——三段编排代码,现在收敛为一次请求。在你的编程项目里粘贴上面代码,替换 file_incident 为你自己的业务函数(比如建客服工单、写数据库、发通知),跑一轮观察 output.type 的输出序列,就能确认模型确实在工具间自动流转上下文。
示例二:跨轮上下文传递
第二个能力是上下文循环(context circulation):内置工具的结果可以跨对话轮次保留。传入 previous_interaction_id,后续提问就能直接推理早前轮次的结果,不必重新执行工具。当然,如果模型需要新数据,它仍然可以发起新的工具调用。
from google import genai
client = genai.Client()
# 第一轮:URL 上下文工具读取 Philipp 的个人介绍页
turn1 = client.interactions.create(
model="gemini-3-flash-preview",
input="Who is Philipp Schmid? https://www.philschmid.de/philipp-schmid",
tools=[{"type": "url_context"}],
)
print(turn1.outputs[-1].text)
# 第二轮:后续问题复用第一轮的上下文
turn2 = client.interactions.create(
model="gemini-3-flash-preview",
input="What is his twitter handle?",
tools=[{"type": "url_context"}],
previous_interaction_id=turn1.id,
)
print(turn2.outputs[-1].text)
第一轮让模型用 URL 上下文工具读一个网页并回答”这是谁”;第二轮只问”他的 Twitter 账号是什么”,不重新给 URL——因为 previous_interaction_id 把第一轮读取的页面内容带进来了,模型直接从已有上下文里答出账号,不再发起第二次页面抓取。省一次工具调用,也就省一次延迟和成本。
把这两个能力叠起来,就能搭出过去要写大量编排代码才能实现的智能体:多工具自动协作,加上跨轮记忆。编程实现时建议先在测试项目里跑通示例二(只有两轮、无自定义函数,最简单),确认 previous_interaction_id 生效后,再叠加示例一的混合工具声明,观察每一步的 output.type 序列,你会清楚看到模型在工具之间的自主调度路径。
原文信息
作者:Philipp Schmid(@_philschmid),AI 工程师
原文地址:
这篇文章分析得很透彻,收藏了!
看完了,收获满满,期待更多更新。
写得挺用心的,支持一下。