Skip to content

第 7 章 · 工具 Tools:内置工具包原理与使用

本章目标:理解 Agno 工具调用的完整执行循环,学会使用内置工具包,并弄清"函数如何变成模型可调用的工具"。

7.1 为什么 Agent 需要工具

大模型本身只会生成文本——它不知道今天的股价、查不了你的数据库、也发不出一封邮件。工具(Tools) 是弥补这一差距的机制:把 Python 函数注册给 Agent,模型在需要时"请求调用"这些函数,Agno 负责真正执行并把结果交回给模型。

关键认知

工具不是插件式的魔法,本质是一个循环:模型输出"我想调用 get_weather(city='北京')"→ 框架执行函数 → 结果追加到上下文 → 模型继续推理。这个循环会一直持续,直到模型不再请求工具、给出最终回答。

官方文档给出的执行流程分五步:

  1. Agent 把当前上下文和**工具定义(schema)**发给模型;
  2. 模型返回普通回答,或请求一次/多次工具调用;
  3. Agno 校验参数并执行每个被请求的工具;
  4. 工具结果加入模型上下文;
  5. 循环继续,直到模型给出最终回答。

7.2 函数如何变成工具 Schema

这是本章最重要的原理:Agno 从函数名、docstring 和类型注解自动构建工具 schema。看一个官方风格的例子:

python
import os
from agno.agent import Agent
from agno.models.openai import OpenAIChat


def lookup_order(order_id: str) -> dict:
    """Return the status and delivery date for an order.

    Args:
        order_id: The order ID to look up.
    """
    return {
        "order_id": order_id,
        "status": "shipped",
        "delivery_date": "2026-07-22",
    }


agent = Agent(
    # 统一使用三方 OpenAI 兼容模型
    model=OpenAIChat(
        id="deepseek-chat",
        api_key=os.getenv("DEEPSEEK_API_KEY"),
        base_url="https://api.deepseek.com/v1",
    ),
    tools=[lookup_order],  # 直接传函数即可
    instructions="Use the order tool when a customer asks about a delivery.",
)

agent.print_response("订单 ORD-123 什么时候到?")

模型实际收到的是一段 JSON Schema,大致等价于:

json
{
  "name": "lookup_order",
  "description": "Return the status and delivery date for an order.",
  "parameters": {
    "type": "object",
    "properties": {
      "order_id": {
        "type": "string",
        "description": "The order ID to look up."
      }
    },
    "required": ["order_id"]
  }
}

由此可以推出三条写工具的铁律(官方称为 "Design Tools for Reliable Calls"):

  • 函数名要具体lookup_order 远好于 do_something,模型靠名字选工具;
  • docstring 写清楚"何时用":它是模型的说明书;
  • 类型注解 + 参数说明必须完整:直接决定入参 schema 的准确性。

7.3 内置工具包 Toolkit 实战

自己写工具固然灵活,但常见需求(搜索、行情、读网页)社区早有封装。Agno 把一组相关的函数打包为 Toolkit,一个包里的函数共享内部状态、协同工作。以最常用的 DuckDuckGoTools 为例:

bash
pip install -U agno ddgs   # DuckDuckGoTools 需要 ddgs 库
python
# search_agent.py —— 让 Agent 联网搜索
import os
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.tools.duckduckgo import DuckDuckGoTools

agent = Agent(
    model=OpenAIChat(
        id="deepseek-chat",
        api_key=os.getenv("DEEPSEEK_API_KEY"),
        base_url="https://api.deepseek.com/v1",
    ),
    tools=[DuckDuckGoTools()],
    instructions=["回答时附带信息来源链接"],
    markdown=True,
    debug_mode=True,  # v2 中观察工具调用的方式:打印详细运行日志
)

agent.print_response("最近一周 AI Agent 领域有什么大事?")

运行后你会在日志里看到类似这样的过程:

text
● Tool call: web_search(query="AI Agent 大事 最近一周")      ← 模型发起
● Tool result: [{"title": "...", "url": "..."}, ...]          ← 函数执行结果
● 最终回答(引用了搜索结果的链接)

注意:Agno 2.x 已移除旧版的 show_tool_calls=True 参数。想看到工具调用细节,用 debug_mode=True;流式场景下则监听 RunContentEvent 中的工具事件。

其他常用工具包还有 YFinanceTools(金融行情)、HackerNewsToolsNewspaper4kTools(读网页)、FileTools(本地文件) 等,全部清单见官方 Toolkit Index。再来看一个组合使用的例子:

python
# stock_agent.py —— 行情工具 + 搜索工具协作
import os
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.tools.duckduckgo import DuckDuckGoTools
from agno.tools.yfinance import YFinanceTools

agent = Agent(
    model=OpenAIChat(
        id="deepseek-chat",
        api_key=os.getenv("DEEPSEEK_API_KEY"),
        base_url="https://api.deepseek.com/v1",
    ),
    tools=[
        YFinanceTools(enable_stock_price=True, enable_analyst_recommendations=True),
        DuckDuckGoTools(),
    ],
    instructions=[
        "金融数据优先使用行情工具获取实时数据",
        "行业新闻用搜索引擎查询,并注明来源",
        "用表格展示数据对比",
    ],
    markdown=True,
    debug_mode=True,
)

agent.print_response("对比英伟达和 AMD 的最新股价与分析师评级")

7.4 工具包的参数与裁剪

Toolkit 不是黑盒,大多数都提供构造参数控制行为,还支持统一裁剪暴露给模型的函数。以 DuckDuckGoTools 为例:

python
# toolkit_params.py —— 精确控制工具包行为
from agno.tools.duckduckgo import DuckDuckGoTools

tools = DuckDuckGoTools(
    enable_news=False,       # 关闭新闻搜索,只留 web_search
    fixed_max_results=3,     # 固定最多返回 3 条结果
    region="cn-zh",          # 区域设置
    timeout=15,              # 超时秒数
)

此外,Agent 级别还有两个通用参数可以进一步收窄暴露面:

python
agent = Agent(
    # ...model 等配置同上...
    tools=[YFinanceTools(all=True)],
    include_tools=["get_current_stock_price"],  # 只暴露白名单内的函数
    # exclude_tools=["get_company_profile"],    # 或者排除指定函数
)

为什么要裁剪工具

暴露的工具越多,模型的选择越困难,误调用率越高(官方文档明确指出 "Expose only the tools needed for the task")。生产环境里,一个只带 2 个精准工具的 Agent 几乎总比带 20 个杂乱工具的更可靠。

7.5 工具执行的控制手段

Agno 提供了一组细粒度控制项,这里先认识两个最常用的,其余(人工确认、外部执行)在第 16 章 Guardrails 再展开:

配置作用
tool_call_limit=N限制单次 run 内最多调用 N 次工具,防止死循环烧钱
read_chat_history=True给模型额外加一个 get_chat_history() 工具,按需回看历史
工具内注入 run_context框架自动注入运行上下文(用户、session state 等),不会进入模型 schema

run_context 是理解后续章节(会话状态)的关键——只要工具函数声明了这个参数,Agno 就会在执行时自动传入,并且不把它算进模型可见的参数里

python
# run_context_demo.py —— 框架注入的隐藏参数
import os
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.run import RunContext


def who_is_calling(run_context: RunContext) -> str:
    """Get the current user id of this session."""
    # run_context 由框架注入,模型看不到它
    return f"当前用户: {run_context.user_id or '匿名'}"


agent = Agent(
    model=OpenAIChat(
        id="deepseek-chat",
        api_key=os.getenv("DEEPSEEK_API_KEY"),
        base_url="https://api.deepseek.com/v1",
    ),
    tools=[who_is_calling],
)

agent.print_response("我是谁?", user_id="gao", session_id="s1")

类似的内建注入参数还有 agentteam、以及 images / videos / audios / files(访问本次运行携带的多模态输入)。

本章小结

  • 工具 = 注册给 Agent 的 Python 函数;执行是"请求 → 执行 → 回填 → 再推理"的循环;
  • 函数名 + docstring + 类型注解共同构成模型可见的工具 schema,三者质量直接决定调用可靠性;
  • 内置 Toolkit 开箱即用(DuckDuckGoToolsYFinanceTools 等),构造参数可精控行为;
  • include_tools / exclude_tools 裁剪暴露面;工具宁少勿多;
  • v2 观察 tool call 用 debug_mode=Trueshow_tool_calls 已移除);run_context: RunContext 是框架自动注入的隐藏参数。

🧪 随堂测验

点击你认为正确的选项。答错时会展示正确答案与原因解析。

1. Agno 根据什么为普通 Python 函数生成工具 schema?

2. Agno 2.x 中想观察 Agent 的工具调用过程,正确做法是?

3. 关于在工具中声明 run_context: RunContext 参数,下列说法正确的是?

4. 某 Agent 挂了 20 个工具但模型经常选错工具,最有效的改进是?

🛠️ 动手实践

  1. 写一个 word_count(text: str) -> dict 工具(统计字符数/词数),让 Agent 通过它回答"这段话有多少个词",并用 debug_mode=True 截取一次完整的工具调用循环日志。
  2. 安装 ddgs,用 DuckDuckGoTools(fixed_max_results=3) 做一个"每日科技快讯"Agent,要求回答附来源链接。
  3. 给 7.5 节的 Agent 加上 tool_call_limit=3,然后故意提一个诱导它连续搜索的问题(如"依次查 5 家公司的股价"),观察达到上限后 Agent 的行为变化。

完成动手实践后,进入第 8 章:自定义工具与 Toolkit 开发