AI Agent 工程师课程
程序员进阶版

A10 · Agno / AgentOS 与跨语言 Runtime

接入第一个不在你语言里的 Runtime,用协议边界替代进程内契约,并回答工具治理如何跨进程延续

本模块产出:runtime-agno(跨进程 Adapter)、Tool Governance 边界方案、跨语言 exit drill 报告 · 新增模块 · 建议 4 到 5 天

这个模块和前面五个 Adapter 不是一回事

A5 的五个 Runtime 都是同语言、同进程的 TypeScript 包,它们共用同一个 @agent-os/tool-runtime,这是平台能跨 Runtime 统一策略的根本原因。Agno 是 Python,跑在另一个进程里,它不会走你的 Tool Runtime。这个模块真正教的不是 Agno 的 API,是这条前提被打破之后你的平台要怎么办。

为什么加这一个框架

三个理由,按重要性排序:

  1. 它是求职市场上绕不开的一个。 这门课主线是 TypeScript,但 AI Agent 岗位里 Python 岗占比不低。Agno 是目前 Python 侧工程完成度最高的一档:SDK 加 AgentOS 运行时加控制台三层齐全,四万多 star,迭代频繁。简历上只有 TS 栈的候选人,在 Python 岗面前会直接被过滤。
  2. 它把「平台无关」这句话逼到真实边界。 前五个 Adapter 说自己框架无关,其实只证明了 TypeScript 无关。抽象漏没漏,跨语言这一刀切下去才知道。
  3. 它自带 A2A、MCP、AG-UI 三个接口。 这三个协议正好是第 8 周、A7、A8 教的东西。接入面已经在你的知识范围内,不需要新学一套私有协议。

关于语言

Agno 只有 Python SDK,官方文档没有 TypeScript 或 JavaScript 版本。网上有文章说 Agno 构建在某个 TS harness 之上,那个说法在官方文档和仓库里都找不到依据,不要采信。这个模块要你写一点 Python,量不大,大约两百行,重点在边界不在语法。

学前自测

1. 前五个 Runtime 共用同一个 Tool Runtime 带来了什么?换成跨进程之后,哪一条会先断?

带来的是统一的 Permission Gate、统一的沙箱、统一的工具级 Trace。你在第 3 周立的那套规矩,五个 Runtime 一视同仁。

跨进程之后先断的是 Permission Gate。Agno 有一百多个内置 toolkit,它调 DuckDuckGoTools 或者读写文件的时候,走的是 Python 进程自己的执行路径,你的审批和沙箱一概不知道。这不是配置问题,是架构问题。

2. 一个跑在别的进程、别的语言里的 Agent,你的 Capability Matrix 要多记哪几列?

至少两列:进程边界和语言边界。它们会连带影响几乎所有既有列的答案。取消从「传一个 AbortSignal」变成「发一个 HTTP 请求去中断远端」,延迟多了一跳,成功率不再是百分之百。事件从「函数调用直接拿到对象」变成「解析 SSE 流」,中间可能丢包。

再往下还有第三列:故障域。同进程的 Adapter 挂了整个服务一起挂,跨进程的 Adapter 挂了你的平台还活着,这既是好处也是新的一类问题(部分可用怎么表达)。

3. AgentOS 说自己「stateless」,但它又要你配数据库。这两句话矛盾吗?

不矛盾,说的是两件事。stateless 指的是进程无状态可水平扩展,任何一个副本都能处理任何请求。要配数据库是因为 session、memory、knowledge、trace 这些状态被外置到了库里,而不是留在进程内存里。

这正是无状态服务的标准做法,也是你从第 9 周就在做的事。看到这两句话觉得矛盾,说明还没分清「进程状态」和「系统状态」。

4. 如果 Agno 的 session 存在它自己的库里,你的平台还怎么做统一的 Trace 和 Eval?

这是这个模块最难的一题,没有免费答案。三条路:

  • 双写:Agno 侧记它的,你的边界层同时往你的 Trace 库写一份。简单,但两份数据会漂移
  • 只认边界:你只记录跨进程调用的入参出参和事件流,不关心 Agno 内部发生了什么。干净,但 Agno 内部的工具调用对你不可见
  • 拉取:用 AgentOS 的 REST 接口定期把它的 session 和 trace 拉过来做归一化。完整,但有延迟且耦合了它的数据模型

选哪条取决于你要不要对 Agno 内部行为负责。这个取舍要写进方案,面试会问。

学习目标

接入第一个不在你语言、也不在你进程里的 Runtime,并回答一个前五个 Adapter 回避掉的问题:当工具执行不再经过你的 Tool Runtime,平台治理靠什么延续。

课程内容

一、Agno SDK 的核心抽象

  1. Agent:model / tools / db / knowledge / instructions / session_id / user_id / add_history_to_context / enable_user_memories
  2. 执行入口:print_response() 用于开发,run() 与 arun() 用于生产,返回 RunOutputEvent 流
  3. Team:members 加 mode,三种模式 coordinate(leader 分派并汇总)、route(路由到成员)、tasks(迭代任务循环,配 max_iterations)
  4. Workflow 与步骤原语:Step、Steps、Parallel、Condition、Loop、Router,步骤间用 StepInput.previous_step_content 和 StepOutput 传递
  5. Knowledge 与 db:多种向量库与关系库后端,对照你自己的 @agent-os/rag-kit
  6. Tools 与 Toolkit 生态,以及 MCP 接入

二、AgentOS 运行时

  1. AgentOS(agents=[...], db=..., tracing=True, scheduler=True, mcp_server=True, a2a_interface=True) 与 get_app() / serve()
  2. 五十多个 REST 端点、SSE 与 WebSocket
  3. JWT 加 RBAC、共享密钥、scoped service account
  4. 审批流(human-in-the-loop)与 checkpoint
  5. 内置接口:MCP、A2A、AG-UI、Slack、Telegram

三、接入你的平台

  1. 三种接入方式的选型:A2A、MCP、裸 HTTP
  2. RunOutputEvent 到 AgentEvent 的映射与丢包处理
  3. 跨进程的取消、超时与预算控制
  4. Tool Governance 边界:薄工具回调 vs 受限租户,两种方案的代价
  5. Trace 与 Eval 的三条归一化路径
  6. 跨语言 exit drill 与数据迁移成本

三种接入方式怎么选

AgentOS 同时提供 A2A、MCP 和裸 REST,选哪个不是口味问题。

接入方式适合什么代价
A2A(推荐起步)把 Agno 当成一个平级的远程 Agent,走 agent-card.json 发现、message:stream 流式语义最贴合,但 A2A 的能力表达比你的内部契约粗
MCP只想把 Agno 的某几个能力当工具用,不需要它跑完整对话降级成工具就丢掉了 session 和 memory
裸 REST / SSE需要 AgentOS 特有的能力(scheduler、审批、knowledge 管理)耦合最深,退出成本最高

推荐路径是先用 A2A 跑通,再按缺口局部下沉到 REST。一上来就直接调 REST,等于把 A7 学的协议白学了,而且 Adapter 会长满 AgentOS 的私有字段。

A2A 的三个端点是固定的,记住它们就够开工:

  • /a2a/agents/{id}/.well-known/agent-card.json 发现
  • /a2a/agents/{id}/v1/message:stream 流式执行
  • /a2a/agents/{id}/v1/message:send 同步执行

边界在哪里

Control PlaneAgent Definition · Policy · Capability Matrix六个 Runtime 共用同一份定义,这一层不因为多了一个 Python 进程而改变同进程 · TypeScript函数调用,类型在编译期对齐NativePiLangChainLangGraphMastra五个都走同一个Tool Runtime跨进程 · PythonHTTP / SSE,类型只在运行期校验Agno AgentOS(FastAPI)自带 Toolkit自带 db / memory不经过你的 Tool Runtime不经过你的 Permission GateData PlaneTool Runtime · Trace / OTel · Eval Dataset · Policy Gate右边这条虚线怎么接回来,就是这个模块要交付的方案
虚线是这个模块的全部内容。左边五个 Adapter 共用 Tool Runtime,右边这个不共用,治理必须换一套办法

Tool Governance:这个模块真正的考题

前五个 Adapter 有一条隐含前提:工具执行永远在你手里。 不管上层是 LangGraph 的节点还是 Mastra 的 step,最终 execute 的都是 @agent-os/tool-runtime,所以 Permission Gate、沙箱、工具级 Trace 一次实现处处生效。

Agno 打破了这条前提。它有自己的一百多个 toolkit,在 Python 进程里直接执行。你的审批流对它不可见。

两种解法,各有代价,方案里必须选一个并说明理由。

方案一 · 薄工具回调

Agno 侧只注册一批没有实际执行逻辑的工具,每个工具的函数体是一次回调,把调用请求打回你的 Tool Runtime,等结果再返回给 Agno。

  • 好处:Permission Gate、沙箱、工具级 Trace 全部保留,治理和前五个 Runtime 完全一致
  • 代价:每次工具调用多一次网络往返,延迟明显上升;Agno 的一百多个内置 toolkit 基本用不上,等于放弃了它的一大卖点
  • 适合:工具本身涉及写操作、外部副作用、或者受合规约束的场景

方案二 · 受限租户

把整个 Agno 进程当成平台里的一个租户,不管它内部调什么工具,只在边界上做策略:网络出口白名单、文件系统只读挂载、独立凭证、租户级配额。

  • 好处:Agno 的生态可以照常用,延迟没有额外开销
  • 代价:工具级审批做不了,只能做进程级隔离;Trace 里看不到它内部调了哪个工具,除非从 AgentOS 拉
  • 适合:只读的检索、研究、分析类 Agent

大多数团队最后是混合的:读类工具走方案二,写类和高风险工具走方案一。能把这条混合边界画清楚,比选哪一个更能说明你想过。

实施任务

实现 runtime-agno,这是第六个 Runtime Adapter,也是第一个跨语言跨进程的:

  1. 起一个最小 AgentOS 服务:一个 Agent,接 SqliteDb,开 a2a_interface=True 与 tracing=True(骨架在 services/agno-os/)
  2. 在 TS 侧补齐 packages/runtime-agno/,通过 A2A 三个端点调用它,复用 A7 的 A2A 客户端
  3. 把 RunOutputEvent 流映射为统一 AgentEvent,明确标注哪些事件类型无法一一对应
  4. 实现跨进程取消:TS 侧收到取消信号后如何中断远端,以及远端已经发出的工具调用怎么办
  5. 选一种 Tool Governance 方案落地,至少实现三个薄工具回调作为对照
  6. 把 runtime-agno 注册进 Agent Registry,Capability Matrix 补上进程边界、语言边界、故障域三列,并用 formatCoverage() 打出策略覆盖率
  7. 执行一次跨语言 exit drill

框架对照

维度前五个 AdapterAgno Runtime
语言TypeScriptPython
调用方式进程内函数调用HTTP / SSE
类型对齐编译期运行期,靠 Zod 在边界校验
Tool 执行统一 @agent-os/tool-runtime不统一,这是全部问题的源头
Permission Gate自动生效要么薄工具回调,要么进程级隔离
取消AbortSignal远端中断请求,非百分百可靠
事件直接构造 AgentEvent解析 SSE,可能丢包和乱序
故障域与平台同生共死独立,可部分可用
Session 存储平台自己的库AgentOS 的库,需要归一化
退出成本删包,业务零改动删 HTTP 客户端很容易,迁移它库里的 session 和 memory 很难

最后一行是这张表最反直觉的地方:跨进程的依赖在代码上更容易退出,在数据上更难退出。 很多人只算代码那一半。

动手挑战

三十分钟,只做一件事:证明 Agno 的工具调用绕过了你的 Permission Gate。

  1. 在 Agno 侧给 Agent 装一个内置 toolkit,比如网络搜索
  2. 在你的平台侧把 Permission Gate 的策略调到最严:拒绝一切网络出口工具
  3. 通过 A2A 发起一次会触发搜索的请求
  4. 观察:请求成功了,你的审批日志里一条记录都没有

看到这个结果之后再往下做。没亲眼见过绕过,就不会真的重视边界方案。

进阶半步:把 Agno 进程的网络出口用防火墙规则封掉,再跑一次,看错误是从哪一层冒出来的、你的平台收到的是什么事件。这半步能让你直观理解方案二的隔离粒度。

Agent OS 里程碑

Agent Registry 支持六类 Runtime,其中一类跨语言跨进程。Capability Matrix 新增三列。

验收标准

  • 同一份 Agent Definition 可通过 A2A 调度到 Agno Runtime 执行
  • 核心 packages 不出现任何 Agno 或 AgentOS 私有概念,边界只在 packages/runtime-agno/
  • 跨进程取消可用,且取消不可靠时显式失败而不是假装成功
  • Capability Matrix 明确记录 Agno 在事件完整度上的缺口
  • Tool Governance 方案落地并有对照数据:薄工具回调的延迟开销、受限租户的可见性缺口
  • 完成跨语言 exit drill,报告同时包含代码迁移成本和数据迁移成本

学后自测

1. 你的薄工具回调,一次往返多了多少毫秒?这个开销在什么场景下不可接受?

要有实测数字,通常在十几到几十毫秒之间,取决于部署拓扑。不可接受的场景是单次 Run 里工具调用次数多的,比如一个需要连续查十几次的研究型任务,累加起来是几百毫秒到一秒。

答不出数字的,说明只搭了架子没跑过压测。这题在面试里几乎必被追问。

2. RunOutputEvent 里有哪几类事件在你的 AgentEvent 里没有对应项?你怎么处理的?

必然有对不上的,因为两套事件模型是各自演化的。正确处理是显式丢弃并记录,不是硬塞进最像的那个类型里。

硬塞是这类 Adapter 最常见的错误:把一个语义不同的事件映射成你已有的类型,下游的 Eval 和 Trace 会得出错误结论,而且极难排查,因为数据看起来是完整的。

3. Agno 进程挂了,你的平台会返回什么?和 Native Adapter 挂了有什么不同?

Native 挂了整个服务一起挂,是全局故障。Agno 挂了平台还活着,只有路由到它的请求失败,这是部分可用。

部分可用要能表达出来:Capability Matrix 要能查到它当前不可用、Registry 要能自动降级到别的 Runtime 或者显式拒绝、监控要区分「平台故障」和「某个 Runtime 故障」。做不到这三条,跨进程带来的好处就没吃到。

4. 跨语言 exit drill 里,代码删除花了多久,数据迁移花了多久?

典型结果是代码几十分钟、数据几天。因为 session、memory、knowledge 都在 AgentOS 的库里,schema 和你的不一样,要写迁移脚本还要处理历史对话的完整性。

如果你的数据迁移也只花了几十分钟,检查一下是不是根本没往 Agno 的库里写过真实数据。空库迁移是零成本的,那不叫演练。

本模块作业

  1. services/agno-os/:最小 AgentOS 服务,含一个 Agent、一个 Team、A2A 接口开启
  2. packages/runtime-agno/:TS 侧 Adapter,含事件映射表与跨进程取消实现
  3. docs/agno-tool-governance.md:两种方案的对照,含薄工具回调的延迟实测和受限租户的可见性缺口清单
  4. Capability Matrix 更新:进程边界、语言边界、故障域三列,六个 Runtime 全填
  5. docs/agno-exit-drill.md:跨语言 exit drill 报告,代码成本和数据成本分开记

面试考点

这个模块对应面试里的异构系统集成与治理边界,是 Staff 级面试里区分度最高的一类题。

  • 「你们平台怎么支持不同语言的 Agent?」:答协议边界替代进程内契约,讲 A2A 先跑通再按缺口下沉的路径。多数候选人只能答「用 HTTP 调」,你能说清楚为什么先 A2A 后 REST。
  • 「跨进程之后你的权限控制还生效吗?」:这题是陷阱,答「生效」就完了。诚实答不生效,要重新设计,然后给薄工具回调和受限租户两个方案加各自代价加混合边界。承认抽象失效比声称万能更能拿分。
  • 「Agno 和 LangGraph 你选哪个?」:不要站队。答分场景:需要状态图显式建模和 time travel 调试的选 LangGraph,需要快速起一个带 RBAC 和审批的多租户服务的选 AgentOS,团队是 Python 栈的后者省掉一整层。给判断依据不给结论。
  • 「引入一个别的语言的运行时,长期成本是什么?」:答三块,代码维护、数据迁移、团队技能。重点讲数据迁移成本被低估这一条,用 exit drill 的两个耗时数字对比。这是很成熟的架构回答,能报数字的候选人极少。
  • 「部分可用怎么向调用方表达?」:答 Capability Matrix 加自动降级加监控分层,强调不能把 Runtime 故障伪装成平台故障,反过来也不行。
  • 反向陷阱:面试官可能说「既然治理都失效了,为什么还要接」。答生态和岗位现实,同时承认如果团队全是 TS 栈且没有 Python 需求,这一层确实不值得。边界画得比方案更重要。

复习与延伸

官方文档

本仓库对应源码

起手代码已经在仓库里,四个模块正好对应这个模块的四个论点:

文件论点
packages/runtime-agno/src/agent-card.ts能力不足显式失败,不静默降级
packages/runtime-agno/src/events.ts映射不上就丢弃并计数,不硬塞进最像的类型
packages/runtime-agno/src/policy-coverage.ts策略覆盖率,另外五个 Adapter 算不出的那个数
packages/runtime-agno/src/client.ts跨进程取消有 unconfirmed 这一档
pnpm --filter @agent-os/runtime-agno test

29 条测试,全部不依赖网络(fetch 和时钟都是注入的)。测的是机制不是某个版本的事件名,所以 Agno 升级不会让它们变红,只会让 MappingReport.droppedByName 里多出条目。

Python 侧在 services/agno-os/:两个 Agent 分别演薄工具回调和受限租户,一个 Team 给 A6 的编排范式对照用。services/agno-os/README.md 里有绕过实验的完整步骤。

对照着读的:

  • packages/contracts/src/agent.ts:AgentDefinition,跨语言之后它仍然是唯一的共同语言
  • packages/tool-runtime/:前五个 Runtime 共用的执行层,读一遍才知道跨进程丢的是什么
  • packages/adapter-langchain/src/messages.ts:同语言反腐层的写法,和跨进程边界对照着看

相关模块

  • A5 的 Capability Matrix 与 exit drill 是这个模块的直接上游
  • A7 的 A2A 客户端在这里被复用,Agno 是它第一个真实的对端
  • A6 的 Multi-Agent 设计可以拿 Agno 的 Team 三种模式做对照实验
  • A9 的责任边界在跨进程场景下要重新过一遍

下一步:回到 A5 把 Capability Matrix 补完,或者去 附录 C 把 Agno 加进贯穿式对照实验。

On this page