内置工具

ADK-Rust 提供了多个内置工具,无需自定义实现即可扩展 agent 的功能。这些工具开箱即用,并能与 agent 框架无缝集成。

现在,提供商原生工具通过常规的 Tool API 进行声明,而不是使用特定于提供商的 GenerateContentConfig.extensions 数据块。这意味着你可以在同一个 agent 中,将 Gemini Google Search、Anthropic Web Search 或 OpenAI Responses web search 等原生工具与普通的 FunctionTool 实例混合使用。

概述

工具用途使用场景
#[tool] 宏零样板自定义工具任何自定义函数 — 参见函数工具
FunctionTool手动注册自定义工具动态工具、闭包
GoogleSearchTool通过 Gemini 进行网络搜索实时信息检索
UrlContextToolGemini URL 接地对实时 URLs 进行总结或推理
GoogleMapsToolGemini Google 地图接地地点、路线和本地上下文
GeminiCodeExecutionToolGemini 原生代码执行服务器端 Python 执行
WebSearchToolAnthropic 原生网络搜索Claude 服务器端网络搜索
OpenAIWebSearchToolOpenAI 响应网络搜索OpenAI 托管检索
AgentTool将代理封装为可调用工具代理组合与委派
ExitLoopTool循环终止控制 LoopAgent 迭代
LoadArtifactsTool工件加载访问存储的二进制数据

GoogleSearchTool

GoogleSearchTool 支持代理使用 Google Search 搜索网络。此工具由 Gemini 模型通过 grounding 功能在内部处理,这意味着搜索由模型本身在服务器端执行。

基本用法

use adk_rust::prelude::*;
use std::sync::Arc;

#[tokio::main]
async fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
    let api_key = std::env::var("GOOGLE_API_KEY")?;
    let model = GeminiModel::new(&api_key, "gemini-3.7-flash")?;

    // Create the GoogleSearchTool
    let search_tool = GoogleSearchTool;

    // Add to agent
    let agent = LlmAgentBuilder::new("research_assistant")
        .description("An assistant that can search the web for information")
        .instruction(
            "You are a research assistant. When asked about current events, \
             recent news, or factual information, use the google_search tool \
             to find accurate, up-to-date information."
        )
        .model(Arc::new(model))
        .tool(Arc::new(search_tool))
        .build()?;

    println!("Agent created with Google Search capability!");
    Ok(())
}

工作原理

与常规函数工具不同,GoogleSearchTool 的运行方式有所不同:

  1. 服务器端执行:搜索由 Gemini 的 grounding 功能执行,而不是在本地执行
  2. 自动调用:模型根据查询内容决定何时进行搜索
  3. 结果集成:搜索结果会直接整合到模型的响应中

如果直接调用该工具,其实现会返回错误,因为实际搜索发生在 Gemini API 内部:

// This is handled internally - you don't call it directly
async fn execute(&self, _ctx: Arc<dyn ToolContext>, _args: Value) -> Result<Value> {
    Err(AdkError::tool("GoogleSearch is handled internally by Gemini"))
}

工具详情

属性值
名称google_search
描述“执行 Google 搜索以从网络检索信息。”
参数由 Gemini 模型确定
执行服务器端(Gemini grounding)

使用场景

  • 时事:“今天新闻里发生了什么?”
  • 事实查询:“东京的人口是多少?”
  • 最新信息:“人工智能领域有哪些最新进展?”
  • 研究任务:“查找有关可再生能源趋势的信息”

示例查询

// The agent will automatically use Google Search for queries like:
// - "What's the weather forecast for New York this week?"
// - "Who won the latest championship game?"
// - "What are the current stock prices for tech companies?"

AgentTool

AgentTool 将任何代理封装为可调用工具,从而实现委托后返回的组合:调用方调用子代理、接收其结果,然后继续执行。子代理发出的状态和工件增量会合并到父工具事件中。子会话还会立即应用每个事件,因此委托工作流中的后续步骤可以看到之前的状态/历史记录变更。

旧版默认行为仍保持隔离并向后兼容。可移植团队可以选择启用父级历史记录/状态快照、记忆转发、失败传播、有限委托深度、精确的状态/历史记录投影,以及对已注册子代理交接的内部执行。已消费的子代理交接仍会作为事件保留,但其传输操作会在转发前被清除,因此父 Runner 不会重复执行该交接。请求元数据、取消操作、作用域、密钥、工件和并行共享状态均遵循配置的转发策略。AgentTool 本身不会运行 Runner 的全局交接循环;编译后的 TeamSpec 会为混合拓扑提供精确的嵌套交接注册表。已编译的团队还会选择启用嵌套事件转发,使委托活动在父事件流中保持可见;独立的 AgentTool 会保留旧版事件输出,除非选择了 forward_events(true)。

对于受控回写,请独立于输入 state_keys 投影使用 output_state_keys。state_merge_policy(RejectConflicts) 会将当前父级值与委托开始时获取的快照进行比较,并以原子方式拒绝冲突写入。artifact_prefixes 将相同的允许列表原则应用于工件名称。为保持向后兼容性,独立默认值仍采用最后写入者获胜策略,并允许不受限制的输出;编译后的团队可以选择其精确的边策略。

基本用法

use adk_rust::prelude::*;
use adk_tool::AgentTool;
use std::sync::Arc;

let sub_agent = LlmAgentBuilder::new("summarizer")
    .description("Summarizes text content")
    .instruction("Summarize the provided text concisely.")
    .model(model.clone())
    .build()?;

let agent_tool = AgentTool::new(Arc::new(sub_agent));

let coordinator = LlmAgentBuilder::new("coordinator")
    .instruction("Use the summarizer tool when asked to summarize content.")
    .model(model.clone())
    .tool(Arc::new(agent_tool))
    .build()?;

工作原理

  1. 父代理决定将包装后的代理作为工具调用
  2. AgentTool 使用 StreamingMode::None 创建调用上下文
  3. 子代理运行至完成,并累积其完整响应
  4. 响应文本返回给父代理
  5. 状态增量和工件增量转发到父上下文

工具详细信息

属性值
名称与被包装 agent 的名称相同
描述与被包装 agent 的描述相同
参数request:字符串(要发送给子代理的输入)
返回值{"response": "..."},包含子代理的文本输出

关键行为

  • 子代理在内部以非流式模式运行,以可靠地捕获响应
  • 子代理的状态更改(output_key)会传播到父会话
  • 子代理保存的工件会转发到父上下文
  • 有关代理组合模式的更多信息,请参阅多代理系统

ExitLoopTool

ExitLoopTool 是与 LoopAgent 配合使用的控制工具,用于指示迭代过程何时应终止。调用该工具时,它会设置 escalate 标志,从而使循环退出。

基本用法

use adk_rust::prelude::*;
use std::sync::Arc;

#[tokio::main]
async fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
    let api_key = std::env::var("GOOGLE_API_KEY")?;
    let model = GeminiModel::new(&api_key, "gemini-3.7-flash")?;

    // Create an agent with ExitLoopTool for iterative refinement
    let refiner = LlmAgentBuilder::new("content_refiner")
        .description("Iteratively improves content quality")
        .instruction(
            "Review the content and improve it. Check for:\n\
             1. Clarity and readability\n\
             2. Grammar and spelling\n\
             3. Logical flow\n\n\
             If the content meets all quality standards, call the exit_loop tool.\n\
             Otherwise, provide an improved version."
        )
        .model(Arc::new(model))
        .tool(Arc::new(ExitLoopTool::new()))
        .build()?;

    // Use in a LoopAgent
    let loop_agent = LoopAgent::new(
        "iterative_refiner",
        vec![Arc::new(refiner)],
    ).with_max_iterations(5);

    println!("Loop agent created with exit capability!");
    Ok(())
}

工作原理

  1. 代理评估是继续运行还是退出
  2. 准备退出时,代理调用 exit_loop
  3. 工具设置 actions.escalate = true 和 actions.skip_summarization = true
  4. LoopAgent 检测到升级标志并停止迭代

工具详情

属性值
名称exit_loop
描述"退出循环。仅在收到指示时调用此函数。"
参数无
返回空对象 {}

最佳实践

  1. 明确的退出条件:在 agent 的指令中定义具体条件
  2. 始终设置 max_iterations:将无限循环作为安全措施加以防止
  3. 有意义的指令:帮助 agent 理解何时退出
// Good: Clear exit criteria
.instruction(
    "Improve the text until it:\n\
     - Has no grammatical errors\n\
     - Is under 100 words\n\
     - Uses active voice\n\
     When all criteria are met, call exit_loop."
)

// Avoid: Vague criteria
.instruction("Improve the text. Exit when done.")

LoadArtifactsTool

LoadArtifactsTool 允许 agent 按名称检索已存储的工件。当 agent 需要访问之前保存的文件、图像或其他二进制数据时,这非常有用。

基本用法

use adk_rust::prelude::*;
use std::sync::Arc;

#[tokio::main]
async fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
    let api_key = std::env::var("GOOGLE_API_KEY")?;
    let model = GeminiModel::new(&api_key, "gemini-3.7-flash")?;

    // Create agent with artifact loading capability
    let agent = LlmAgentBuilder::new("document_analyzer")
        .description("Analyzes stored documents")
        .instruction(
            "You can load and analyze stored artifacts. \
             Use the load_artifacts tool to retrieve documents by name. \
             The tool accepts an array of artifact names."
        )
        .model(Arc::new(model))
        .tool(Arc::new(LoadArtifactsTool::new()))
        .build()?;

    println!("Agent created with artifact loading capability!");
    Ok(())
}

工具详情

属性值
名称load_artifacts
描述"按名称加载工件并返回其内容。接受工件名称数组。"
参数artifact_names:字符串数组
返回值包含 artifacts 数组的对象

参数

该工具需要一个 JSON 对象,其中包含一个 artifact_names 数组:

{
  "artifact_names": ["document.txt", "image.png", "data.json"]
}

响应格式

该工具返回一个包含已加载构件的对象:

{
  "artifacts": [
    {
      "name": "document.txt",
      "content": "The text content of the document..."
    },
    {
      "name": "image.png",
      "content": {
        "mime_type": "image/png",
        "data": "base64-encoded-data..."
      }
    },
    {
      "name": "missing.txt",
      "error": "Artifact not found"
    }
  ]
}

要求

要使 LoadArtifactsTool 正常工作,需要:

  1. 在运行器中配置 ArtifactService
  2. 之前已保存到服务中的构件
  3. 将该工具添加到 agent
use adk_rust::prelude::*;
use std::sync::Arc;

// Set up artifact service
let artifact_service = Arc::new(InMemoryArtifactService::new());

// Configure runner with artifact service
let runner = Runner::new(agent)
    .with_artifact_service(artifact_service);

组合内置工具

你可以将多个内置工具组合使用:

use adk_rust::prelude::*;
use std::sync::Arc;

#[tokio::main]
async fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
    let api_key = std::env::var("GOOGLE_API_KEY")?;
    let model = GeminiModel::new(&api_key, "gemini-3.7-flash")?;

    // Create agent with multiple built-in tools
    let agent = LlmAgentBuilder::new("research_agent")
        .description("Research agent with search and artifact capabilities")
        .instruction(
            "You are a research agent. You can:\n\
             - Search the web using google_search for current information\n\
             - Load stored documents using load_artifacts\n\
             Use these tools to help answer questions comprehensively."
        )
        .model(Arc::new(model))
        .tool(Arc::new(GoogleSearchTool))
        .tool(Arc::new(LoadArtifactsTool::new()))
        .build()?;

    println!("Multi-tool agent created!");
    Ok(())
}

创建自定义内置工具

你可以通过实现 Tool trait,按照与内置工具相同的模式创建自己的工具:

use adk_rust::prelude::*;
use async_trait::async_trait;
use serde_json::{json, Value};
use std::sync::Arc;

pub struct MyCustomTool;

impl MyCustomTool {
    pub fn new() -> Self {
        Self
    }
}

#[async_trait]
impl Tool for MyCustomTool {
    fn name(&self) -> &str {
        "my_custom_tool"
    }

    fn description(&self) -> &str {
        "Description of what this tool does"
    }

    async fn execute(&self, ctx: Arc<dyn ToolContext>, args: Value) -> Result<Value> {
        // Your tool logic here
        Ok(json!({ "result": "success" }))
    }
}

API 参考

GoogleSearchTool

impl GoogleSearchTool {
    /// Create a new GoogleSearchTool instance
    pub fn new() -> Self;
}

ExitLoopTool

impl ExitLoopTool {
    /// Create a new ExitLoopTool instance
    pub fn new() -> Self;
}

LoadArtifactsTool

impl LoadArtifactsTool {
    /// Create a new LoadArtifactsTool instance
    pub fn new() -> Self;
}

impl Default for LoadArtifactsTool {
    fn default() -> Self;
}

上一页:← 函数工具 | 下一页:浏览器工具 →

内置工具 - ADK-Rust 文档 | ADK-Rust