三个 Agent 框架,我用同一个项目各实现了一遍

为什么做这个事情

从 GPT-3.5 开始,我们见证了 AI 这几年的发展,Agent 已经成为主流,Agent 的编程框架也多了起来。其中 LangChain、Pydantic AI 和 eve 是我主要关注的几个。

问题是,一个 QuickStart 体现不出各个框架的不同。

三家的入门代码长得都差不多:建一个 agent、挂两个工具、跑一轮对话。照着写完之后,对各个框架的理解还是不深刻、不到位。

所以我想用一个小项目,采用三个不同的框架各实现一遍,对比它们的实现方式。

三个框架的简单介绍

LangChain

一句话定位。 LangChain v1 给自己的定位是一条公式:

Agent = Model + Harness

特点。 官方文档里列了四条 Core benefits:

  1. Standard model interface(统一的模型接口)。 一套接口覆盖 chat model、embedding 等,跨各家 provider。换模型只需要很小的代码改动,需求演进时应用仍然是可移植的。
  2. Highly configurable harness(高度可配置的 harness)。create_agent 这个最小 harness 起步,通过 middleware 增量地加能力——护栏、重试、路由、自定义工具策略,你的场景需要什么就组合什么。
  3. Built on top of LangGraph(建立在 LangGraph 之上)。 LangChain 的 agent 建在 LangGraph 上,因此能享受 LangGraph 的持久化执行、human-in-the-loop 支持、持久化等能力。
  4. Debug with LangSmith(用 LangSmith 调试)。 在一个地方查看 trace、工具调用、状态转换和延迟;定位失败模式、评估质量、用执行数据改进 agent 行为。

此外Langchain的版本迭代快,** 这次用的是 v1(langchain 1.3.x),和网上大量 v0 教程已经对不上

LangGraph 是它下面那一层。 官方对它的定位是:

LangGraph 为任何长时间运行的有状态工作流或 agent 提供低层的支撑基础设施LangGraph 不抽象提示词,也不抽象架构。

它俩最重要的区别是:LangGraph 不替你决定 prompt 怎么写、agent 长什么样,只给你状态、持久化和调度。这就是它和 LangChain 那层的分界——一个给你 harness,一个给你地基。

LangGraph 的 Core benefits,官方列了六条:

  1. Mix deterministic and agentic steps(确定性步骤和 agent 步骤混着用)。 在同一张图里把手写的确定性逻辑和 LLM 驱动的决策组合起来——需要可靠和可预测的地方用确定性步骤,需要灵活的地方用 agent 步骤,从而对 agent 行为的每一部分都有精确控制。
  2. Persistence(持久化)。 让 agent 扛过失败、长时间运行,并从中断的地方接着跑
  3. Human-in-the-loop(人在环路中)。 可以在任意时刻检查和修改 agent 的状态,把人的监督嵌进流程。
  4. Comprehensive memory(完整的记忆)。 既有支撑当前推理的短期工作记忆,也有跨会话的长期记忆。
  5. Debugging with LangSmith。 用可视化工具追踪执行路径、捕获状态转换、提供详细的运行时指标,深入看清复杂 agent 的行为。
  6. Production-ready deployment(生产级部署)。 有为「有状态、长时间运行的工作流」这类特殊挑战设计的可伸缩基础设施。

官方文档建议:如果你刚接触 agent,先从 LangChain 那层高级抽象开始,别直接上 LangGraph。

Pydantic AI

一句话定位。 它的 slogan 是:

GenAI Agent Framework, the Pydantic way

特点(官网「Why use Pydantic AI」列了十一条,这里挑和这个项目直接相关的):

  1. Built by the Pydantic Team。 Pydantic Validation 本身被 OpenAI、Google、Anthropic 和很多主流框架用着——它是在自己最擅长的地方做 agent 框架
  2. Fully Type-safe。 支持 IDE 自动补全,在写代码的时候就报错,不用等运行时。
  3. output_type 约束输出。 用 Pydantic 模型声明 agent 必须交出什么,模型交不出合格的就重来。
  4. Output Validators。 官方的说法是「基于反思的自我纠正」——校验不过,把理由带回给模型让它重新生成。
  5. 依赖注入。 通过 RunContext 把数据和连接传进工具,类型安全。
  6. Model-agnostic。 支持 OpenAI、Anthropic、Gemini、DeepSeek 等 20 多个 provider。
  7. Durable Execution。 在 API 失败和应用重启之间保住进度。注意这一条是靠接外部编排实现的(DBOS、Temporal 这类),不是框架自带一个存储。
  8. Streamed Outputs。 流式输出结构化数据,边流边校验。
  9. Seamless Observability。 和 Pydantic Logfire 打通,追踪、调试、算成本。
  10. Powerful Evals。 系统性地测试和评估 agent 的表现。

多 agent 怎么组织,官方分了五级,从「模型说了算」一路排到「代码说了算」:

级别 是什么 下一步谁决定
1 单 agent 模型(靠 instructions 和它自己的推理)
2 Agent delegation:agent 通过工具调另一个 agent 模型,全程由它掌控
3 Programmatic agent hand-off:应用代码(或人)决定下一个调谁 代码
4 Graph-based control flow:显式配置的图,官方说是「最复杂的情况」 代码
5 Deep Agents:会规划、能操作文件、能委派任务、带沙箱执行 模型和代码分担

这张表值得记住,因为它才是「谁决定下一步」这个问题的正确答案形状——不是「这个框架属于哪一类」,而是「你选第几级」。第 5 篇会说我为什么选了第 3 级。

「the Pydantic way」这句 slogan 很准确:如果你在 Python 后端里习惯了拿 pydantic 定义边界,这一家几乎不需要额外学习成本。

它没有图,也没有 DSL,编排就是普通 Python:要循环三轮就写 for,要并行就写 asyncio.gather。没有丰富的封装

agent = Agent(
    model,
    deps_type=ReviewDeps,
    output_type=Review,      # agent 交出什么,由类型声明
    retries=3,               # 校验不过重试几次,构造参数
)

@agent.output_validator
def enforce_guards(ctx, review: Review) -> Review:
    if problem := check_blocker_has_harm(review.findings):
        raise ModelRetry(problem)   # 带着反馈让模型重做
    return review

eve

一句话定位。 这是三家里最新的一个,Vercel 在 2026 年 6 月开源。官方给自己的定位是:

一个 filesystem-first 的框架,用来构建持久化的 AI agent。

官方文档开头那句把它的世界观说得很清楚:

eve 把一个文件系统项目变成一个持久化的后端 AI agent。你在 agent/ 目录下编写 agent,eve 发现这些文件、校验它们、编译出一份 manifest,然后把运行时作为一个可部署的应用提供出去。

最核心的一条:目录就是契约,接线交给框架。

这是它和另外两家最本质的差别,也是我认为理解 eve 的关键——你不用管数据怎么传递,不用管 agent 怎么调用、怎么注册。

编排、工具调用、上下文在角色之间的传递,全部由框架实现。你要做的只是把 tools、skills、subagents 各自写好放进对应目录,框架在构建时自动发现它们、编译成一份 manifest、运行时自己去调。

于是你真正关注的东西只剩下**「这个角色要做什么」**——而那件事写在 markdown 里。

同一件事,三家要你写的东西差别很大:

加一个工具 数据怎么传给工具 谁调用谁
Pydantic AI agent.tool(read_draft) 一行行注册 deps_type 声明,RunContext 自己写 for 循环和 gather
LangGraph tools=[...] 传进 create_agent state schema + reducer 声明怎么合并 自己连边、自己写条件跳转
eve tools/ 下加一个文件 不用管 不用管

其余特点:

  1. 一个文件一个工具,文件名就是模型看到的工具名。
  2. 持久化是框架自带的。 session 跑在 Vercel Workflows 上,「把进度作为事件日志持久化,并确定性地重放来重建状态」,所以一个 session 能扛过冷启动、重新部署和长时间等待。
  3. 每个 agent 都有一个 sandbox。 官方描述是「隔离的、bash 风格的计算环境,有自己的文件系统」,框架自带的 bashread_filewrite_file 都指向它。
  4. skill 和 subagent 是两个东西。 官方的区分是:skill 给正在运行的 agent 加指令,而 subagent「作为一个独立的 agent 运行,有全新的对话历史和状态」。
  5. channels 是平台入口。 HTTP、Slack 这些接入方式各是一个文件,共用同一个 agent 运行时。
  6. 可观测开箱即用。 Vercel 面板里直接有 Agent Runs,能看 session、turn、工具调用、推理、耗时和 token 用量,不用写 instrumentation.ts
  7. 模型串走 AI Gateway。 部署到 Vercel 之后可以用 OIDC,不用自己管各家 provider 的 key。

官方列出的目录约定:

agent/
  instructions.md      始终生效的系统提示词
  agent.ts             运行时配置,通过 defineAgent 指定模型等
  tools/*.ts           一个文件一个类型化工具,文件名就是工具名
  skills/*             按需加载的流程,模型只在相关时才载入
  subagents/*          子 agent,模型把聚焦的子任务委派给它
  channels/*           平台入口,比如 HTTP 和 Slack
  connections/*        与外部服务的类型化集成
  sandbox/*            agent 隔离的计算环境

「接线交给框架」这件事,落到代码上就是几乎没有代码agent.ts 短到出乎意料:

export default defineAgent({
  description: "编辑视角审核:查事实性错误、编造的数据、跑不通的命令……",
  model,
});

一个 agent 的声明就这么多,它的行为全部写在同目录的 instructions.md。工具也一样,放进 tools/ 就能用,不需要在任何地方登记一笔。

对于用的人来说,注意力被强行拉回到**「这个角色该做什么、该怎么判断」**上——这些恰恰是最该花时间的地方。

另外两点体感差异:

一是默认工具面。 另外两家默认是空的,要什么自己写;eve 默认都给你(bash、文件读写、globgrepweb_fetch),不需要的自己关掉。

二是编排本身也可以是一个 agent。 你不写编排代码,而是写一份指令交给一个「主编」agent,让它决定这一步该调谁。这一条官方没有直接强调,但这个很重要。

一句话对照

读完官方文档,有一件事得先纠正——我一开始也想当然了:

三家的默认,其实都是「模型决定下一步」。

这很自然,因为 agent 框架的出发点就是「把决策交给模型」。LangChain 的 create_agent、Pydantic AI 的前两级、eve 的主编 agent,都是模型看着 prompt 自己判断这一步该干什么。

真正的差别在于:当你想把决定权收回到代码手里时,各自要付出什么。

框架给的编排方式 想让代码决定的话 默认工具面 持久化 官方可观测方案
LangChain / LangGraph create_agentStateGraph 下沉一层到 LangGraph 画图。middleware 只管得了重试、提前终止这类事,路由管不了 自带 checkpointer LangSmith
Pydantic AI 官方五级,从单 agent 到图 选第 3/4 级,编排写成普通 Python 接外部编排 Pydantic Logfire
eve 主编 agent + subagents 没有现成的路,只能用 prompt 去约束模型 自带 sandbox 和 harness 自带(Vercel Workflows) Vercel Agent Runs

我们要做什么

单个 Agent 没什么难度。 挂几个工具、写段提示词、跑一轮对话,三个框架写出来的东西差不多,还是看不出区别——这跟 QuickStart 是一个问题。

所以我想用一个稍微成熟一点的项目来做,也就是多 Agent

角色一多,事情才开始有意思:谁先谁后、能不能并行、上下文怎么在角色之间传、一个角色能不能干另一个角色的活、某个角色跑歪了谁来兜。这些正好能体现出来各个框架的不同,单 Agent 根本碰不到。

想来想去选了写博客。这个场景天然就是多角色的:有一个人写,有用户来读。 在这个基础上,我还加了一个编辑来 review。

三个角色各管一段:

角色 干什么
执笔 把主题和笔记写成初稿,按意见修订。唯一有写权限的角色
读者视角 照着做能不能跑通、哪里看不懂、哪里会卡住
编辑视角 查事实性错误、编造的数据、跑不通的命令、逻辑断裂

做的过程中又补了一个运营视角(标题跟搜索词匹不匹配、标签怎么打、开头能不能留住人),凑成三个审核视角。

串起来是这样一条流水线:

执笔写初稿
  ↓
三个视角并行审核(编辑 / 读者 / 运营),互相不看对方的意见
  ↓
汇总判定(纯函数算的,不由模型说了算)
  ↓
不通过 → 执笔按意见修订 → 复审,最多三轮

有两条设计要在这里先说,因为后面每一篇都会回到它们:

一、加编辑这个角色不是为了凑数。 AI 写技术文章会犯一些很稳定的错,而且 prompt 劝不住

二、判定权不在模型手上。 分工是这样的:模型只负责按等级给意见,每条意见标上 blocker / major / minor能不能发布由一个函数按这些等级算——有 blocker 就是不可发布,只剩 major 就是建议修订后发布,都没有才是可以发布。

if missing or blockers > 0:
    status = "blocked"           # ❌ 不可发布
elif majors > 0:
    status = "needs_revision"    # ⚠️ 建议修订后发布
else:
    status = "publishable"       # ✅ 可以发布

模型压根没有「宣布可以发」这个动作可用。 它能影响结论的唯一方式,是把某条意见标成什么等级——而标完之后怎么算,是计数和比大小的事。

这么分是因为模型会为了让流程走完而说「可以发了」,函数不会。missing 那一项也是同理:少一个视角的意见直接判不可发布,没审完等于没审,模型没法靠跳过一轮审核来让文章通过。

具体会犯哪些错、五道结构性防护分别怎么设计,第 02 篇细讲。这里只要记住一件事:这些跨角色的约束,正是三个框架差别最大的地方——有的框架你写了约束它静默失效,有的默认会把整条流程炸掉,有的写上就跑。

项目结构

仓库长这样:

csdn-blog-agent/
├── CONTRACT.md          三家必须一致的部分:落盘布局、指纹算法、判定规则、HTTP 接口
├── fixtures/            共享测试语料:4 篇人造草稿 + 期望的检查结果
├── docs/                系列文章和视频大纲
└── impl/
    ├── eve/             TypeScript,端口 2000
    ├── pydantic-ai/     Python,端口 2100
    └── langgraph/       Python,端口 2200

后续安排

先说清楚我们要实现的功能,从 LangChain 、Pydantic AI、eve 依次来实现我们的功能,最后横向对比各个框架,

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐