乐于分享
好东西不私藏

Agno 源码解读:它凭什么比 LangChain 快 10000 倍

Agno 源码解读:它凭什么比 LangChain 快 10000 倍

先说一个反直觉的事实:Agno 没有用任何黑科技来提速。

没有 Rust 重写核心,没有 SIMD 指令集优化,没有 JIT 编译。它只做对了一件事——不写多余的代码

上次贴了那个对比:Agent 实例化,LangChain 要花 300ms,Agno 只要 2μs。差距 10000 倍。很多人不信,觉得是 benchmark 作弊,或者测了一个玩具场景。今天拆开 Agno 的源码,仔细解释这个差距到底从哪来的。

一个 Agent 实例化时到底发生了什么

先说 LangChain。创建一个能用的 Agent,初始化链路是这样的:

AgentExecutor.__init__()
  → BaseMultiActionAgent.__init__()
    → BaseCallbackHandler.__init__()        # 注册回调管理器
    → create_model_wrapper()                # 包装 LLM
      → ChatOpenAI.__init__()
        → BaseChatModel.__init__()
          → BaseLanguageModel.__init__()
            → Pydantic BaseModel.__init__() # Pydantic v2 schema 验证
    → PromptTemplate.__init__()             # 模板解析、编译
      → 正则匹配变量占位符 + f-string 编译
    → OutputParser.__init__()               # 输出解析器
    → ConversationBufferMemory.__init__()   # 历史对话管理

完整的初始化链走下来,一个 LangChain Agent 触发了超过 150 个 Python 对象的创建。每一步都经过 Pydantic v2 的 model 验证——类型检查、默认值填充、序列化schema 构建。这些开销在前端感觉不到(总共才 300ms),但当你需要创建 100 个 Agent、或者在 API 服务器每次请求都初始化一个时,这就变成了真实瓶颈。

再看 Agno 的 Agent:

class Agent:
    def
 __init__(self, model, instructions, tools=None, ...):
        self
.model = model           # 字符串或 Model 对象
        self
.instructions = instructions
        self
.tools = tools or []     # 列表,可以为空
        # 就这些。没有其他东西了。

一个 plain Python class,没有继承任何框架基类,没有任何 Pydantic 验证,没有回调注册,没有序列化元数据。__init__ 只做一件事——属性赋值。对象数量:1 个。

这就是 10000 倍差距的根本原因。不是 Agno 做了什么优化,是 LangChain 做了太多多余的事。

核心设计哲学:三个原语足够

拆开 Agno 的代码仓库之后,核心真的只有三个类。每个都短到你可以一小时内看完。

Agent——万物皆参数

class Agent:
    model: Union[Model, str]              # 字符串也行
    instructions: Optional[str]            # system prompt
    tools: List[Union[Tool, Callable]]     # 可以直接传 Python 函数
    team: Optional["Team"]                 # 可选:属于哪个 team
    db: Optional[BaseDb]                   # 可选:持久记忆
    knowledge: Optional[KnowledgeBase]     # 可选:RAG 能力

三个最有代表性的设计取舍:

第一,model 可以是字符串 "openai:gpt-4o"。框架在内部自动解析 provider 和 model name,创建对应的客户端。你不需要先 import OpenAI、创建 client、再传给 Agent。一个字符串搞定。

第二,tools 直接接受 Python Callable。你传一个普通的 async 函数,Agno 自动读取函数的 docstring、type hints 和参数签名,动态生成 OpenAI function calling 的 JSON Schema。不需要定义 BaseTool 子类,不需要手写 schema。

第三,没有强制依赖。记忆、RAG、多模态这些高级能力都是可选参数。你不用就不加载,内存和启动时间都为零。

Team——500 行搞定多 Agent

class Team:
    members: List[Agent]
    model: Optional[Union[Model, str]]
    mode: Literal["route", "coordinate", "tasks"]

三种协作模式,核心逻辑都在一个文件里:

  • route——根据消息内容语义路由到最合适的成员 Agent,适合「万能助手」场景
  • coordinate——Team Leader 先理解任务,再分发给成员,然后汇总所有人的结果
  • tasks——预定义流程,每个步骤交给特定成员,没有 AI 自主决策开销

没有复杂的路由策略接口,没有消息总线,没有事件系统。500 行纯 Python。

Workflow——纯编排,零 AI 开销

class Workflow:
    steps: List[Union[Agent, "Workflow"]]  # 可以嵌套 Workflow
    mode: Literal["sequential", "parallel", "conditional"]

Workflow 不是 Agent,不调用 LLM。它就是按照你定义的步骤一步步执行。sequential 顺序走,parallel 同时走,conditional 按条件分支。跑 100 步和跑 1 步的时间差只来自你实际调用的 Agent——框架本身没有额外开销。

调试对比:一行日志 vs 穿透五层

这是我最想强调的差异。当你的 Agent 给出了奇怪的回答,你要排查原因:

LangChain 下你需要排查五个东西

  1. 1. Prompt 模板有没有被污染?变量有没有被错误填充?
  2. 2. OutputParser 有没有把模型的输出错误解析了?
  3. 3. Memory 有没有注入了不相关或者过期的历史对话?
  4. 4. Retriever 有没有检索了无关的文档片段导致模型跑偏?
  5. 5. 某个 Callback 中间件有没有修改了输入或者输出?

你需要穿透 5-6 层抽象,才能看到真正发给 OpenAI/Anthropic 的原始 API 请求。而每一层都有自己的日志格式、自己的数据结构。

Agno 下你只需要看模型的 messages 列表——就是发给 API 的那个 list of dict。一行 print(agent.run_history.messages) 就能看到所有上下文。简单,直接,不隐藏任何东西。

这个差异在日常使用中比 benchmark 数字重要得多。

内存占用的秘密

创建 100 个相同的 Agent,对比内存占用:

       
                                           
LangChainAgno倍数
100 实例总内存~1600 MB~1 MB1600x
单实例~16 MB~0.01 MB1600x
Python 对象总数~15000 个100 个150x
       
     

差距来源有三:

  1. 1. Pydantic BaseModel 元数据:每个 LangChain 对象都带 __fields_set____private_attributes__model_config、JSON Schema 缓存等,这些元数据比实际数据大得多
  2. 2. 全局回调系统:LangChain 的 CallbackManager 是全局注册的,每个 Agent 实例都带完整的回调链
  3. 3. 序列化能力:每个 LangChain 对象都支持 save/load/dumpd/loadd,维护序列化路径和版本信息需要额外内存

Agno 的 Agent 本质上就是一个 dict 的薄包装。没有序列化要求,没有回调系统,没有 Pydantic 验证开销。

run() 的执行流程差异

处理一次带工具调用的对话,两个框架的路径:

LangChain:AgentExecutor._call() → _take_next_step() → Agent.plan() → ChatOpenAI._generate() → ToolExecutor.execute() → _handle_tool_error() → _call_after_agents() → OutputParser.parse() → Memory.save_context(),一次工具调用走 15-20 个函数。

Agno:Agent._run() → Model.response(messages) → Tool.execute() → loop_until_no_tool_call,3-5 个函数。

如果一个任务需要 5 轮工具调用(这在 Agent 场景很常见——搜索、读文件、写代码、跑测试、修 bug),LangChain 多走 50+ 个函数。函数调用开销本身不大,但每个函数里都可能做额外的数据拷贝、格式转换、日志记录。累积起来就明显了。

代价是什么

Agno 不是没有取舍:

  1. 1. 模型可移植性:LangChain 让你写一套代码,切换 OpenAI / Anthropic / Gemini 只需要改模型名字。因为它在所有模型上面都盖了一层统一抽象。Agno 的模型适配是独立的,切换时你需要确认参数名兼容、确认 message format 差异
  2. 2. 生态集成广度:LangChain 有 800+ 现成的工具集成和向量数据库集成。Agno 目前只有几十个。如果你需要接一个非常小众的向量数据库,大概率要自己写适配
  3. 3. 深度自定义限制:如果你需要自定义 Memory 的存储策略(比如按时间衰减)、自定义 Retriever 的检索算法(比如混合检索+重排序),LangChain 给了完整的接口体系。Agno 目前只能「用内置的」

但对于 90% 的场景,你要的不是一套可以自定义一切的框架。你要的是一个能让你快速把 Agent 写出来、跑起来、部署出去的工具。用更少的代码做事。代码越少,bug 越少,维护越容易。

快速判断用哪个

       
                                           
你的场景选 Agno选 LangChain
新项目,快速启动
多 Agent 协作
需要接 10+ 种向量数据库
深度自定义 RAG pipeline
生产环境部署+监控✅ (AgentOS)
团队有 LangChain 深厚积累
学习 Agent 编程概念✅ (上手快)
       
     

下一篇:用 Agno 从零构建你的第一个 SaaS AI 产品,从本地脚本到 Docker 部署的完整流程。

关注「八小时之外」,每天一篇 AI 实战干货。