第 36 章 · 进入 Agno 实战轨
从“看懂”到“跑起来”之间那道坎
一位做欧洲站的跨境卖家读完前 34 章,理解了 Agent Harness 的全部原理:ReAct 循环怎么转、工具怎么调、上下文怎么裁剪、会话怎么持久化、多 Agent 怎么编排。可当他真要动手时,卡住了——他要的是一个能今晚就跑起来的选品研究助手:白天抓竞品 Listing,晚上比对差评关键词,遇到含电池、含化妆品成分的品类还要查合规,最后把结论存下来供团队复用。
主书用 pi 把每一个控制点都拆给他看过了,但从“看懂控制点”到“攒出一个跑通的应用”,中间还隔着一层:向量库怎么接、记忆存哪、几个 Agent 怎么分工、上线怎么变服务。这一层不是新理论,而是工程组装。Part 10 就是补这一层——换用 Agno 这个应用框架,把前 34 章讲透的模式,一个个落成可运行的 Python 代码。本章是附册开篇,先交代清楚:为什么用 Agno、Agno 的能力怎么对应主书、以及从这里到第 43 章要走的完整路线。
为什么 Part 10 用 Agno
前 34 章一直以 pi 为主线,因为 pi 让你看清 Agent Harness 的底层:循环、工具、上下文、会话、扩展、RPC、观测和安全边界。Part 10 换一个视角:用 Agno 把同一套模式快速做成应用。
这不是改主线,也不是说 Agno 替代 pi。二者站的位置不同:pi 是 harness(运行时),把控制权交到你手里,你看得见每一个环节为什么这样设计;Agno 是 Agent 应用框架,把常见能力(Tools、Knowledge、Memory、Team、Workflow、AgentOS)做成一等公民(first-class),你用参数就能把它们组合起来。
| 视角 | pi | Agno |
|---|---|---|
| 核心定位 | agent harness / 运行时 | Agent 应用框架 |
| 读者收获 | 看懂底层控制点 | 快速组合完整应用 |
| 强项 | Hooks、会话、RPC、编码 Agent、运行时透明 | Agent、Tools、Knowledge、Memory、Team、Workflow、AgentOS 开箱即用 |
| 学习目的 | 理解系统为什么这样设计 | 验证这些设计怎样快速落地 |
所以 Part 10 的目标很清楚:用 Agno 跑通主书模式,而不是重写 Agno 中文文档。 每读到一个 Agno 能力,你都应该能立刻回想起“这对应主书第几章讲的什么模式”——这种映射本身,就是附册最想让你带走的东西。
Agno 的能力如何映射主书
理解 Agno 最省力的方式,不是背它的 API 清单,而是把它的能力按主书已经讲过的模式对号入座。Agno 的核心抽象大致可以分成几层,每一层都能在主书里找到理论出处:
- Model + Agent:一个
Agent绑定一个model,配上description(角色)和instructions(行为规则)。这对应主书第 4 章的提示词分层与 ReAct 基础。 - Tools:内置工具(如
DuckDuckGoTools)与自定义工具(一个带 docstring 的普通 Python 函数),对应第 4 章的工具调用;接 MCP Server 对应第 5 章;用response_model拿到结构化输出对应第 6 章。 - Knowledge:内置 RAG——
Embedding、Vector DB、hybrid search都是一等能力,对应第 11 章。 - Storage / Memory / State / Context:会话历史、用户长期记忆、任务进度、本轮临时参考,对应第 12 章(及第 8、9 章的上下文与记忆)。
- Team / Workflow:多 Agent 协作(
coordinate模式)与流程编排(顺序/并行/条件/循环),对应第 15、16 章。 - AgentOS:把脚本变成可观测、可交互、可恢复的服务,对应第 22、23、24 章的运行时、预算与可观测性。
一句话:Agno 把主书“你需要自己接入的能力”做成了内置组件。 主书教你这些能力为什么存在、边界在哪;Agno 让你用几行参数把它们拼起来。附册的价值就在这个落差里——你不会再学一套新理论,只是看同一个模式在应用框架里长什么样。
本 Part 的贯穿项目
我们继续使用主书的 Research Agent,但把实现视角切换到 Agno。最终目标是一个面向跨境卖家的研究助手,它要能:
- 搜索公开资料(竞品 Listing、市场趋势)和内部文档(选品与合规手册)。
- 把调研结果输出为固定结构(品类、目标市场、合规要点、风险评级)。
- 记住用户偏好(主营站点、关注品类)和会话历史。
- 由多个 Agent 分工:一个搜集、一个审校合规、一个汇总成报告。
- 通过 AgentOS 变成一个团队能调用的服务。
- 做评测、观测、权限和上线检查。
它和第 35 章的 pi 示例是同一个业务问题,只是抽象层不同。后续各章正是围绕这个项目逐步长出来的,路线图如下:
| 主书模式 | Agno 实战章 | 这一章给项目加什么 |
|---|---|---|
| 工具调用、MCP、结构化输出 | 第 37 章 | 让 Agent 会搜索、会输出固定结构 |
| RAG、Knowledge、Context | 第 38 章 | 接入内部合规手册,回答有据可依 |
| Storage、Memory、State | 第 39 章 | 记住聊过什么、用户是谁、任务到哪 |
| 多 Agent、Team、Workflow | 第 40 章 | 搜集/审校/汇总三 Agent 分工 |
| 远程服务、观测、接口 | 第 41 章 | 用 AgentOS 变成可观测的服务 |
| 治理、安全、上线 | 第 42 章 | 加权限、人审、预算与上线门槛 |
| 综合项目 | 第 43 章 | 把以上全部组装成完整 Research Agent |
如果你已经读完前 34 章,这一部分不会引入一套新理论。它只在回答一个问题:“同样的模式,如果用 Agno,代码和工程边界长什么样?”
第一个 Agno Agent
Agno 的最小 Agent 很直接。先跑通这一个,后面所有能力都是往它身上挂:
from agno.agent import Agent
from agno.models.openai import OpenAIChat # 需要在环境变量里配置 OPENAI_API_KEY
agent = Agent(
model=OpenAIChat(id="gpt-4o"), # 模型层:底层调用哪个 LLM
description="面向跨境卖家的研究助手。", # 角色:这个 Agent 是谁
instructions=[ # 行为规则:做事时遵守什么
"用简体中文回答。",
"先给结论,再列依据。",
"不知道时明确说明,不要编造。",
],
markdown=True, # 输出偏好:面向人时用 Markdown 排版
)
# print_response 直接把回答流式打印到终端;stream=True 边生成边显示
agent.print_response("请解释什么是 Agent Harness。", stream=True)
这段代码和第 4 章的提示词分层正好对应:
| Agno 参数 | 主书里的概念 | 作用 |
|---|---|---|
description | 角色描述 | 说明这个 Agent 是谁,负责什么 |
instructions | 行为指令 | 说明它做事时遵守什么规则 |
model | 模型层 | 决定底层调用哪个 LLM |
markdown | 输出偏好 | 影响面向人的表达形式 |
如果你想把它变成一个可反复对话的调试入口,Agno 还提供了两种调用形态,后面章节会反复用到:
# 形态一:拿到结构化的返回对象,便于在程序里处理(取内容、看工具调用、看用量)
resp = agent.run("含锂电池的玩具能发德国吗?")
print(resp.content)
# 形态二:起一个交互式命令行会话,像聊天一样连续提问,适合本地调试
agent.cli_app()
一个关键纪律要在开篇就立下:运行时临时信息不要塞进 description。 当前用户是谁、经营哪个店铺、这次上传了什么文件、检索到了什么资料、任务进行到第几步——这些都不该写死在角色描述里,而应该通过 context、工具返回、storage 或 workflow 的 session_state 注入。这条纪律贯穿整个附册,第 39 章会把它讲透。
给它第一件工具:从“会说话”到“能干活”
上面的 Agent 只会凭模型记忆回答——它对昨天的竞品降价、今早新出的合规通告一无所知。要让它真正为跨境卖家干活,第一步就是给它一件工具。Agno 里加工具只是往 tools=[] 里塞东西,而工具既可以是内置的,也可以是你自己写的一个普通 Python 函数:
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.tools.duckduckgo import DuckDuckGoTools # 内置的网络搜索工具
# 自定义工具就是一个带清晰 docstring 的普通函数——docstring 就是给模型看的"说明书"
def check_battery_rule(country: str) -> str:
"""查询某国对含锂电池商品的进口合规要求。
Args:
country: 目标国家的中文名,例如"德国""日本"。
Returns:
该国锂电池进口的关键合规要点(示意数据,真实场景应查内部合规库)。
"""
rules = {
"德国": "需 UN38.3 测试报告 + CE 标识;空运含电池商品受 IATA 限制。",
"日本": "需符合 PSE 认证;容量超阈值的锂电池按危险品申报。",
}
return rules.get(country, f"暂无{country}的锂电池合规数据,建议人工核查。")
agent = Agent(
model=OpenAIChat(id="gpt-4o"),
description="面向跨境卖家的研究助手。",
instructions=[
"回答合规问题前,必须先调用工具查证,不要凭记忆作答。",
"先给结论,再列依据,并说明数据来源。",
],
tools=[DuckDuckGoTools(), check_battery_rule], # 内置工具 + 自定义工具混用
show_tool_calls=True, # 打印出模型调了哪个工具、传了什么参数,便于调试与观测
markdown=True,
)
agent.print_response("含锂电池的玩具能发德国吗?需要什么认证?", stream=True)
运行时你会在输出里看到模型先调用了 check_battery_rule(“德国”),拿到真实条款(这就是第 3 章说的 Observation),再基于它作答。这正是第 4 章工具调用原则的 Agno 落地:Agent 本身不存知识,需要时“去查”。 show_tool_calls=True 让整个调用过程透明可见,这一点在第 41 章讲可观测性时会继续深化。
注意这里两种工具的写法差异:DuckDuckGoTools() 是实例化的内置工具类,而 check_battery_rule 直接传函数本身。Agno 会读取函数的类型标注和 docstring,自动生成模型需要的工具 schema——所以 docstring 写得清不清楚,直接决定模型会不会在对的时机调它。这个细节第 37 章会展开。
至此,我们已经有了一个“会搜索、会查合规、过程可见”的最小助手。它离最终的 Research Agent 还差得远——不会记事、只有单个 Agent、还跑在脚本里——但骨架已经立住。附册接下来的每一章,都是往这具骨架上挂一块肌肉:第 37 章让工具与输出更规范,第 38 章接上真正的知识库,第 39 章给它记忆,第 40 章让它变成一支队伍,第 41 章把它推上线,第 42 章给它上治理,第 43 章收口成完整应用。
深入一层:为什么先立这套映射
初学者拿到 Agno 常犯的错,是把它当成“一个更方便的 SDK”,照着文档堆 API,结果攒出一个能跑但说不清边界的东西。附册坚持先立“能力→主书章节”的映射,是因为框架会变,模式不会变。
举个具体的:Agno 的 instructions 接受一个字符串列表,而不是一整段大 prompt。这不是风格问题——分条写让每条指令都可被单独审视、单独回归测试,这正是第 4 章强调的“提示词要能被治理”。再比如 Agno 把 Knowledge 做成内置组件,你一行 knowledge= 就有了 RAG;而 pi 里 RAG 是“接进来的一次工具调用”(第 11 章)。两种做法底层是同一套 RAG:检索增强生成,差别只在“框架替你封装了多少”。
选参数时也应回到模式想。比如后面选 num_history_responses(带几轮历史进上下文)时,本质是在第 24 章的预算和第 12 章的多轮连贯之间权衡——带得多更连贯但更烧 token。你若只盯着 API 文档,是看不出这层权衡的;映射到主书模式,就一目了然。这就是为什么本章要花力气先立标尺,而不是急着写复杂代码。
还有一层容易被忽略的收益:这套映射让你能判断“某个需求该不该用 Agno 承接”。 举例,如果跨境项目要求检索必须走公司自研的、带权限过滤的向量服务,那么 Agno 内置的 Knowledge 未必合适——这时更好的做法是把那套服务封装成一个自定义工具接进来(回到第 4 章的思路),而不是硬套 knowledge=。反过来,如果只是“把一份 PDF 手册变成可问答的知识库”这种标准需求,Agno 内置 RAG 几行就搞定,自己造轮子反而是浪费。框架的边界感,来自你对模式的理解,而不是对 API 覆盖面的记忆。 附册每一章都会在“用内置能力”和“自己接入”之间给出这类判断,而判断的坐标系,就是主书那 34 章。
动手看看
拿上面第一个 Agent 做三个小改动,感受“参数即模式”:
- 把
instructions里加一条“回答控制在 200 字以内,超出就分点”,再问同一个问题,观察输出结构怎么变——这就是在用最轻的方式约束行为,对应第 4 章。 - 把
model从gpt-4o换成一个更小的模型(如gpt-4o-mini),问一个需要推理的合规问题,对比回答质量与速度——这是第 24 章成本与效果权衡的最小实验。 - 把
markdown=True去掉再运行,看纯文本和 Markdown 排版的差别,体会“输出偏好”是面向人的表达层,而不是内容层。
你会发现,Agno 的“魔法”其实很朴素:每个参数背后都是一个你在主书里学过的决策。 把这层看穿了,后面接 Knowledge、Memory、Team 都只是“往这个 Agent 上挂更多能力”。
实战中的几个坑
坑一:把 Agno 当黑盒魔法。
- 现象:功能堆得很快,但一问“这个工具的权限边界在哪、数据会不会外泄”就答不上来。
- 原因:框架封装度高,容易让人以为“能跑=可用”,跳过了权限、数据边界、评测这些系统责任。
- 对策:始终把 Agno 当“帮你省事的组件库”而非“替你负责的系统”,工具权限、数据边界、评测和上线仍由你把关(详见第 42 章)。
坑二:把运行时信息写进 description。
- 现象:换个用户、换个店铺,Agent 还在用上一个人的偏好回答。
- 原因:把当前用户、店铺、文件这类临时状态硬编码进了角色描述。
- 对策:
description/instructions只放稳定不变的角色与规则,临时信息走context、工具返回、storage、session_state。
坑三:instructions 写成一大段散文。
- 现象:想调整某条规则时牵一发动全身,也没法单独测某条指令有没有生效。
- 原因:没利用 Agno 分条列表的结构,把所有约束糊成一段自然语言。
- 对策:一条规则一行,短句祈使句,让每条都可单独审视、单独回归(对应第 4 章“提示词可治理”)。
坑四:照着 API 文档堆功能,不回扣模式。
- 现象:示例越写越复杂,却说不清哪个能力该由框架承接、哪个边界该系统设计负责。
- 原因:把 Agno 当“更方便的 SDK”,忘了它只是模式的一种落地。
- 对策:每加一个能力,先问“这对应主书哪一章的什么模式”,代码要服务于模式而非炫 API。
Agno vs 主书 pi 做法
同样是“把主书模式落地”,Agno 和 pi 的分工可以这样对照:
| 能力 | Agno 怎么做 | pi(harness)怎么做 | 各自适合谁 |
|---|---|---|---|
| 组一个 Agent | Agent(model=, instructions=[], tools=[]),参数即能力 | 在 harness 上注册工具、写循环、管上下文 | Agno 适合快速攒应用;pi 适合要看清每个控制点 |
| 接知识库 | knowledge= 内置 RAG,开箱即用 | 把检索封装成一次工具调用/MCP/技能 | Agno 适合标准 RAG 快落地;pi 适合自定切片与检索策略 |
| 记忆与会话 | storage=、memory=、session_state= 一等能力 | 自己设计存储层与状态注入 | Agno 适合复用成熟方案;pi 适合特殊持久化需求 |
| 多 Agent | Team/Workflow 声明式编排 | 自己写编排逻辑与消息传递 | Agno 适合常见协作模式;pi 适合非标流程控制 |
| 上线为服务 | AgentOS 一步变可观测服务 | 用 RPC/接口自行封装 | Agno 适合快速服务化;pi 适合深度定制运行时 |
分野很清楚:Agno 把这些能力做成了内置组件,搭起来最快;pi 把它们当作“接入的能力”,更灵活、也更贴合“每个环节都由你定”的真实工程需求。 底层的模式是同一套,只是抽象层不同。附册选 Agno,正是为了让你在读懂原理之后,能最快看到一个完整应用长什么样。
小结
- pi 是主书的 harness 主线,Agno 是 Part 10 的应用框架实战轨——不是替代关系,而是“同一模式的两个抽象层”。
- Agno 的价值在于把 Agent、Tools、Knowledge、Memory、Team、Workflow、AgentOS 做成一等能力,用参数就能快速组合成完整应用。
- 理解 Agno 的正确姿势是把它的能力对号入座到主书章节(Tools→第3/4/5章、Knowledge→第 11 章、Storage/Memory/State→第 12 章、Team/Workflow→第15/16章、AgentOS→第22/24章),框架会变、模式不会变。
- Part 10 继续用跨境电商 Research Agent 作贯穿项目,从第 37 章到第 43 章逐步长成:先会用工具,再接知识库、加记忆、组多 Agent、上线服务、做治理,最后综合组装。
- 学 Agno 不是背 API,而是理解哪些能力应该由框架承接、哪些边界仍要由系统设计负责——
description只放稳定角色,运行时信息走context/storage/session_state。
铺好了这条实战轨,我们就从最基础也最高频的能力开始动手:让 Research Agent 学会调用工具、连接 MCP、并把调研结果输出成固定结构。