本节摘要:工具是智能体从"会说"变"会做"的关键——挂上搜索工具能查最新资讯,挂上金融工具能拿实时行情。本节讲清工具机制、两种挂载方式(内置工具与自定义函数),并用搜索与金融两个真实工具跑通完整示例。
阅读完本节,你应当能够:
模型的知识截止在训练时点,问"今天股市怎么样"它答不上来;模型不会算复杂公式,让它解个方程组也是错。工具就是补这两块短板:搜索工具给最新信息,计算工具给精确结果。Agno 里挂工具几乎零成本——一行参数,智能体就多了一项本领。
模型本身不会执行工具,它只决定要不要用:模型在回复中声明"我需要调用 XX 工具",框架代为执行,把结果塞回上下文,模型再基于结果生成最终答案。这个"模型决策 → 框架执行 → 结果回传"的循环,是智能体工具机制的底层逻辑。

from agno.agent import Agent from agno.tools.duckduckgo import DuckDuckGoTools agent = Agent( name="news_bot", description="擅长检索最新资讯的智能体", tools=[DuckDuckGoTools()], show_tool_calls=True, # 开发期显示工具调用过程 ) agent.print_response("搜索一下今天人工智能领域最重要的新闻")
💡 关键直觉:开发期务必开
show_tool_calls=True——你能看到模型"决定用工具 → 框架执行 → 回传结果"的全过程,排查"为什么没搜到"时一目了然。
from agno.agent import Agent from agno.tools.yfinance import YFinanceTools agent = Agent( name="stock_bot", tools=[YFinanceTools(stock_price=True, analyst_recommendations=True)], show_tool_calls=True, ) agent.print_response("某科技龙头的当前股价和机构评级如何?")
from agno.agent import Agent def calculate_discount(price: float, ratio: float) -> float: """计算折扣后价格。price 原价, ratio 折扣比例 0-1""" return round(price * ratio, 2) agent = Agent( name="shop_bot", tools=[calculate_discount], instructions=["算价格时调用折扣工具"], ) agent.print_response("原价 1299 的商品打 85 折,多少钱?")
普通函数 + 装饰器标记(在 Agno 中自定义工具直接传函数即可),模型会自动理解函数签名与 docstring,按需调用。
⚠️ 常见坑:自定义工具的 docstring 就是模型的理解依据。docstring 写清楚参数含义与返回格式,模型才能正确调用;写得太含糊,模型会传错参数。
| 工具 | 场景 | 安装 |
|---|---|---|
| DuckDuckGoTools | 联网搜索 | duckduckgo-search |
| YFinanceTools | 金融行情 | yfinance |
| 自定义函数 | 业务逻辑 | 无 |
原始资料对 DuckDuckGoTools 与 YFinanceTools 给了一组现成的问答实验,把这些问题亲手跑一遍,对"工具扩展知识边界"的体会比读十页文档深。
搜索工具的实验设计成对照组:先问"纽约的突发新闻"(本地化,结果具体),再问泛化的"突发新闻"(范围大,结果发散)。跑完能直观看到工具型智能体的一个特性——回答质量受查询词影响,而你可以通过指令教它把用户问题改写成更好的搜索词。
金融工具的实验覆盖三类典型查询:问特斯拉股价(单点数据)、问苹果的分析师评级(聚合观点)、问微软的公司信息(基本面画像)。三问对应三种数据形态,智能体都能把工具返回的结构化数据转成自然语言,还能按指令用表格呈现——"用表格展示数据"这条指令在原始示例里反复出现,说明它对可读性的提升立竿见影。
from agno.tools.yfinance import YFinanceTools finance_agent = Agent( tools=[YFinanceTools(stock_price=True, analyst_recommendations=True, company_info=True)], instructions=["始终用表格展示数据", "数据必须来自工具结果,不得编造"], ) finance_agent.print_response("特斯拉当前股价多少?分析师怎么看?")
注意工具构造参数的写法:能力按开关粒度传入,要什么开什么。这既是权限控制(不让智能体碰不需要的接口),也是降噪(能力越多,模型选择越容易发散)。
一个智能体可以挂多个工具,模型按需选用。但工具数量上去后有两个副作用:选择准确率下降、提示词变长。经验阈值是单智能体五六把工具以内,再多就该考虑拆分——这正是团队登场的理由之一:搜索型智能体、金融型智能体各带各的工具,队长按任务性质派活。
| 工具组合 | 适合的问题 | 注意点 |
|---|---|---|
| 仅搜索 | 时效性问题、开放信息 | 教模型改写查询词 |
| 仅金融 | 股价、评级、公司画像 | 明确数值必须来自工具 |
| 搜索 + 金融 | "前景 + 财务"复合问题 | 复杂问题建议直接组团队 |
| 多工具堆叠 | 助手 | 控制数量,开调试提示 |
💡 关键直觉:工具是智能体的"手",指令是"脑子的用法"。手再多,脑不清楚也没用——先写好"什么时候用什么工具、结果怎么呈现"的规则,再谈扩工具箱。
看过官方工具的长相,自己设计工具时照着四个原则打磨。第一,单一职责:一把工具干一件事,"搜索新闻"与"查股价"分开,模型选择才准。第二,描述写给模型看:工具描述不是给程序员的注释,是一份"什么时候该调用我"的说明书,要写清适用场景、输入含义、返回形态,几句话的描述质量直接决定调用准确率。第三,返回宁短勿长:工具结果是塞进上下文的,返回一大篇网页原文既贵又干扰推理,做好运维级摘要再返回。第四,失败要可读:出错时返回结构化的错误说明(什么错了、还能不能重试),模型读到后能自行决策,比抛一堆堆栈友好得多。
工具安全是绕不开的另一半。权限最小化前面提过,这里补执行层的三道保险:超时控制(外部接口卡死不能拖垮整个请求)、重试上限(避免模型对失败工具无限重试)、结果校验(返回格式先验证再进上下文)。三道保险装好,工具层就从"最脆弱的环节"变成"最皮实的环节"。
评估工具配置是否合理,有个简单的观测法:统计一段真实使用里各工具的调用分布与成功率。某把工具从不被调用,要么描述不行要么根本多余;某把工具失败率高,先修它;调用集中在一两把上,说明职责划分可能太粗。让数据替你决定工具箱的取舍。
失败信息会回到模型,它可能重试、换工具或如实报告失败。生产上要防连锁失败:对不稳定的工具设置重试与超时,对关键路径准备降级回答。
可以。自定义工具就是普通的 Python 类或函数,包一层调用内部接口的逻辑即可,第 3 章扩展定制一节会展开做法。注意权限最小化:智能体只需要完成任务的接口,不要顺手把管理权限给它。
看缺的是"知道"还是"想到"。缺实时或私有数据,是"知道"的问题,加工具;推理质量差、不会拆步骤,是"想到"的问题,换模型或改指令。两者症状不同,先分清再动刀。
工具智能体做顺之后,自然会长出一个"工具生态"的问题:公司里不同项目各写各的工具,重复造轮子、行为不一致。治理思路是给工具分层:最底下是通用工具(搜索、网页提取、文件解析),全公司共享一份实现;中间是业务工具(查订单、查库存),按业务域封装、接口契约清晰;最上面是场景工具(某个活动页专用),允许快速堆叠不求复用。层与层之间只许上层调用下层,不许横穿。
这个分层的收益在半年后显现:新人接手项目时,看到的工具都是熟面孔;某把通用工具修了个缺陷,所有项目同步受益;而快速试错的场景工具烂在顶层也无所谓,反正影响半径被层隔离了。智能体应用的工程化成熟度,看工具治理就能判断个七八成——散装工具堆的项目,再炫的智能体配置也撑不了多久。
个人开发者同样适用,只是规模缩小:自己的常用工具收进一个文件夹、统一命名与描述风格、定期清理不再用的。工具箱的整洁度,就是开发者的段位证书。
工具智能体进入日常使用后,建议尽早给每次工具调用打上三类标签:调用了哪把工具、成功还是失败、结果被模型采纳了多少。累积一段时间就能回答关键问题——哪把工具是顶梁柱、哪把在吃干饭、失败集中在什么场景。这些观测不需要专门平台,在工具封装里加几行日志、每周用文本工具汇总一次就够,但它能把"感觉工具挺多"变成"这两把工具贡献了八成调用",后续的工具箱治理从此有了依据。
还有一个调试细节:当模型该调工具却不调时,先别急着改指令,把该问题的用户表述抄下来看看——口语化、带错别字的提问最容易让模型误判为无需工具。在指令里补一条"涉及时间敏感信息时必须先检索",比反复重写整段指令见效快得多。
最后提一句工具的"作息管理":外部接口有高峰期,智能体也有。把高频工具的调用限额、时段偏好纳入配置考量,高峰期自动降级到缓存或备用源,工具层的稳定性就从"看运气"变成"有预案"。这套思路在第 3 章性能优化里会正式展开,这里先埋个种子。
智能体"会干活"了,下一节让它"有知识"——挂上知识库,回答它没学过的内容。