
Agno 框架的 Agent 在调用自定义工具函数时,严格要求所有工具返回值必须为 str 类型;若返回 int、float 等原生数值类型,将触发 Pydantic 的 ValidationError,导致消息解析失败。
agno 框架的 agent 在调用自定义工具函数时,严格要求所有工具返回值必须为 str 类型;若返回 int、float 等原生数值类型,将触发 pydantic 的 validationerror,导致消息解析失败。
在使用 Agno 构建 agentic 应用(如计算器代理)时,一个常见却容易被忽视的关键约束是:所有注册为 tools 的函数,其返回值类型必须为 str。这是因为 Agno 内部基于 Pydantic v2 构建消息结构(如 Message 模型),其 content 字段明确声明为 Union[str, List[Any]] 类型。当工具返回 int(7) 或 float(1.75) 时,Pydantic 会拒绝该值——既不满足 str 类型校验,也不符合 list 类型要求,从而抛出类似以下的双重验证错误:
ValidationError: 2 validation errors for Message content.list[any] → Input should be a valid list content.str → Input should be a valid string
这不是你的代码逻辑有误,而是框架对工具 I/O 协议的显式约定:工具输出即“给 LLM 看的内容”,必须是可序列化、可嵌入对话上下文的字符串。
✅ 正确做法:
将所有工具函数的返回类型标注为 str,并在函数体内显式调用 str() 转换结果:
def add(x: int, y: int) -> str:
"""Add two numbers and return result as string."""
return str(x + y)
def divide(x: int, y: int) -> str:
"""Divide x by y; handles ZeroDivisionError gracefully."""
if y == 0:
return "Error: Division by zero"
return str(x / y)
def generate_random_number() -> str:
"""Generate random integer between 1–10 and return as string."""
import random
return str(random.randint(1, 10))
⚠️ 注意事项:
-
不要依赖类型提示自动转换:Python 类型注解(如
-> str)仅用于静态检查,运行时仍需手动str(...)转换; -
异常处理建议显式返回错误字符串:避免工具抛出异常中断执行流,用
"Error: ..."形式反馈更符合 agent 的容错设计; -
文档参数名需与实际形参一致:你原始代码中 docstring 写的是
a,b,但函数定义为x,y,虽不影响运行,但会降低工具描述的可信度与 LLM 理解准确性; -
随机数生成应真正随机:示例中硬编码
return "42"会导致每次结果相同,建议使用random.randint()并确保导入正确。
总结来说,Agno 的工具契约本质是「字符串即接口」——工具不是直接参与计算的底层函数,而是面向 LLM 的语义化能力单元。保持输出为 str,既是绕过 Pydantic 校验的必要条件,更是实现多步推理(如“加→乘→除→随机”链式调用)的稳定基础。











