Agent 框架与运行时工具:一张选型地图(Agent Frameworks & Runtimes)
所属:01-fundamentals / 04-agent-architecture
面试权重:★★(面经里是直接题 ——「Agent 框架选型:LangChain / LangGraph / Eino 各自的抽象与适用场景?」;它同时是「Agent Runtime 基础」这一块的入口:讲不清一个工具站在哪一层,后面讲项目就没有坐标系)
来源:四类划分的骨架取自 LangChain 官方文档的 Framework / Runtime / Harness 三分法(https://docs.langchain.com/oss/python/concepts/products,这是 LangChain 自己给的分类,它有立场),第四类「通用持久化执行引擎」由本仓库补上;书的基线是《深入理解 AI Agent:设计原理与工程实践》第 1 章的「主流 Agent 框架简要对比」表、五阶段演进(提示工程 ⊂ 上下文工程 ⊂ Harness 工程 ⊂ Loop 工程 ⊂ Graph 工程)与「Harness 中绝大部分代码是约束、验证与纠正」,以及第 10 章「AutoGen 群聊 vs OpenAI Swarm 的控制流」;Claude Agent SDK(https://code.claude.com/docs/en/agent-sdk/overview)、OpenAI Agents SDK(https://openai.github.io/openai-agents-python/)、Google ADK(https://adk.dev/)、Eino(https://www.cloudwego.io/docs/eino/overview/)、Agno(https://docs.agno.com/introduction、https://www.agno.com/products/sdk)、Microsoft Agent Framework(https://learn.microsoft.com/en-us/agent-framework/workflows/orchestrations/handoff)为官方文档口径;Pi、Pydantic AI、Mastra、Strands Agents、Letta、smolagents、Semantic Kernel / AutoGen 的现状取自官网与第三方对比文章,未做一手考证。框架生态变动快,除参考书外的定位描述以写作时抓取的官方文档为准
相关知识点:./15-orchestration.md(分工:那篇讲「路径谁定」的四档定位差异,本篇是它的展开 —— 讲同一层里不同工具各自站哪一档,§7 那张表从这里接着讲)、./08-agent-stack.md(分工:那篇分栈的层次 Tool→MCP→Skill→Agent→Harness,本篇分同一层里不同产品的定位)、../07-distributed-systems/state-machine.md§8(Temporal / DBOS / Step Functions 的持久化执行细节不在本篇展开)、../07-distributed-systems/recoverable-task-runtime.md(可恢复任务执行系统的完整设计)、./14-agent-state.md(Agent 视角的状态建模与 checkpoint 粒度)、../../02-interview/projects/writing-copilot.md(本篇唯一的一手经验落点:LangGraph 多智能体)
一句话#
先分清它是框架、运行时还是 Harness,再谈选型 —— 判据不是谁功能多,而是「谁的抽象层少、且不骗你」。 而「不骗你」在这张地图上最具体的一处是:不要把一个库的 checkpointer 说成持久化执行 —— 前者保数据可恢复(失败那一轮的工作要重做,所以它逼你写幂等),后者保执行可恢复(已完成的活动不会重跑)。
为什么重要(面试角度)#
- 它是直接题,不是背景知识。 面经信号里「Agent 框架选型:LangChain / LangGraph / Eino 各自的抽象与适用场景?」由 B5 与 B13 两条共同指向(见
../../02-interview/questions/interview-signals.md§3.1);而且「Agent 体系(编排 / 框架 / Runtime)」是信号里命中最多的话题簇。面试官问这句时,想要的是坐标系,不是功能清单。 - 它是讲项目的坐标系。 Writing Copilot 是 LangGraph 上的多智能体;说不清 LangGraph 是「框架」还是「运行时」,就说不清你在这个项目里自己写了哪一部分、框架替你兜了哪一部分 —— 而那恰恰是面试官要挖的。
- 它是第 1 块「Agent Runtime 基础」的入口。 用户的原话是「langgraph、agno、pi、Claude code SDK 是 agent runtime 工具」—— 这句话把四类东西装进了同一个词。把这句话拆开,就是这一块学习的地图本身。
- 它有一个能立刻分层的考点:checkpointer ≠ 持久化执行。 大多数人的答案是「LangGraph 有 checkpointer,所以它能从失败点恢复」;能说清它恢复的是数据不是执行、失败那一轮会被重做、所以要求幂等,并知道 LangGraph Platform 提供了服务器侧恢复、Temporal 还有 LangGraph 插件(即不要把 OSS 库的边界说成整个产品的边界)的人,明显在另一层。详见 §4。
- 它专治「按名词选型」。 「低代码」的 n8n / Dify、「角色化」的 CrewAI、「极简」的 Pi 与「自带全套工具」的 Claude Agent SDK 不在同一个取舍轴上 —— 先把取舍轴说清楚,再谈选谁。
⚠️ 边界声明:你的一手经验只有 LangGraph(Writing Copilot) 一家。Eino 只到「知道它站在哪一档、它的抽象叫什么」,没有用过;Agno / Pi / Claude Agent SDK / Codex Harness / Google ADK 等其余工具,一律按「按这张图我会这么选」讲,不得讲成用过。大规模分布式(Temporal 那一侧)见
../07-distributed-systems/state-machine.md的边界声明。
核心内容#
1. 先分清四类东西#
「Agent 工具」这个词把四件不同的事混在一起了。按它替你兜住什么分开,问题立刻清楚:
| 类别 | 官方口径的一句话 | 它替你兜住什么 | 代表(按 LangChain 文档的分类) | 你还要自己写什么 |
|---|---|---|---|---|
| 框架(Framework) | 「提供抽象,让你更容易上手」 | 抽象与集成:模型、工具、检索、结构化输出、agent 循环的封装 | LangChain、Vercel AI SDK、LlamaIndex、CrewAI、OpenAI Agents SDK、Google ADK | 循环、编排、状态、部署 |
| 运行时(Runtime) | 「提供在生产里跑 agent 的工具」 | durable execution / streaming / HITL / persistence | LangGraph、Temporal、Inngest | 图或流程的设计、状态 schema、幂等 |
| Harness | 「有主见的、开箱即用的框架,自带工具与能力」 | 预置工具 / 提示 / 子 agent / 权限模型 | Deep Agents SDK、Claude Agent SDK、Manus | 很少 —— 你改的是配置、工具与边界 |
| 通用持久化执行引擎 | 本仓库补的第四类:不关心你 agent 不 agent | 事件历史 + 确定性重放 + 活动重试 + 跨重启定时器 | Temporal、DBOS、Inngest、Restate、AWS Step Functions | 工作流代码要做到可确定性重放 |
一句话判据把四类分开:「你想省抽象、想跑得住、还是想连循环都不写?」
- 想省抽象(少写模型适配、工具 schema、检索管线)→ 框架;
- 想跑得住(跨重启、流式、人工审批、状态持久化)→ 运行时;
- 想连循环都不写(工具、提示、子 agent 都给你)→ Harness;
- 只想让「一件事跑到一半挂了能接着跑」→ 通用持久化执行引擎。
这张表要带着一个提醒用:三分法是 LangChain 官方给的,而 LangChain 把自己放「框架」、把 LangGraph 放「运行时」、把 Deep Agents SDK 放「Harness」(后两者分别是它的下一代与上层产品)。这个分类有立场,但它有解释力 —— 它抓住的正是一个工具替你兜住什么。用它的时候标明出处即可。
另外两条同源事实:LangChain 1.0 建在 LangGraph 之上(框架建在运行时之上),Deep Agents SDK 建在 LangGraph 之上(Harness 建在运行时之上)。也就是说这三层不是并列竞品,很多情况下它们是叠着用的。
2. 把书里那张表映射进来#
书第 1 章的「主流 Agent 框架简要对比」有 9 行,按「核心定位 / 编排模式 / 开发方式 / 适用场景」分档。它的分档口径和上面四类不是同一个轴(书分的是「编排模式 + 开发方式」,即 15-orchestration.md §7 讲的那件事),映射过来看会更清楚:
| 书里的框架/平台 | 核心定位(书) | 编排模式 | 归到本文的哪一类 |
|---|---|---|---|
| Codex Harness | Codex 的开源 Agent 运行时 | 自主 | Harness / 运行时(可嵌入自有应用) |
| Claude Agent SDK | 生产级 Agent 开发框架 | 自主 | Harness(自带工具与循环) |
| LangChain / LangGraph | 通用 LLM 应用框架 | 工作流 + 自主 | 框架 + 运行时(一家两代) |
| n8n | 可视化工作流自动化 | 工作流 + 自主 | 低代码框架 |
| Dify | LLM 应用开发平台 | 工作流 + 对话式 | 低代码框架(含平台层) |
| CrewAI | 角色化多 Agent 编排 | Multi-Agent 协作 | 框架(多 Agent 原语) |
| OpenClaw | 开源全能个人 Agent | 自主 + 事件驱动 | Harness(配置 + 代码) |
| DeepSeek Harness | Agent 自进化框架 | 一切皆插件 | Harness / 框架(可定制) |
| Pi | 极简 Coding Agent 框架 | 自主 | Harness(极简,见 §3.2) |
读表两句话:① 书里「运行时 / SDK」那一档(Codex Harness / Claude Agent SDK / Pi)基本都落在本文的 Harness 类 —— 它们的共同点是自带你那个 agent 循环,你不写编排;② LangChain / LangGraph 横跨两行,正是「框架建在运行时之上」的实例。
书里对前两行有一处澄清,值得单独记(它是「产品 vs 运行时」这个区分最好的例子):Codex 是产品(App / CLI / IDE 扩展),Codex Harness 是驱动这些形态的那一层运行时;它给三条集成路径 ——
codex exec(脚本与 CI 里的一次性任务)、Codex SDK(第三方应用代码启动 / 恢复 / 流式处理任务)、app-server(JSON-RPC,持久会话 + 事件流 + 审批回调,适合把 Agent 做进产品)。Claude Agent SDK 与 Claude Code 也是类似的关系 —— 区别是 Claude 侧对外开放的是 SDK 接口,Harness 实现本身并不开源。
3. 逐类点名#
3.1 框架类#
| 工具 | 一句话定位 | 核心抽象 | 什么时候选它 |
|---|---|---|---|
| LangChain(一手:只用过它的下游 LangGraph) | 通用 LLM 应用框架 | 结构化内容块、agent 循环、中间件;1.0 建在 LangGraph 之上 | 要快速接很多模型 / 检索 / 工具,愿意接受一层抽象 |
| LangGraph | 「构建、管理、部署长时间运行的有状态 agent 的低层编排框架与运行时」(官方描述) | 图 + 共享状态:节点是步骤、边是迁移、条件边是守卫、checkpointer 落盘 | 控制流要可枚举、可测试、可画出来;要 HITL 与恢复。这是 Writing Copilot 的那一档 |
| Eino | Go 生态的 LLM 应用框架(CloudWeGo 出品,Apache-2.0,Go 1.18+) | 见下方专段 | Go 技术栈、要类型安全与显式编排 |
| OpenAI Agents SDK | Swarm 的生产级后继;原语刻意少 | Agents(instructions + tools)、Handoffs(委派给别的 agent)、Guardrails(校验输入输出) | 已在 OpenAI 生态、要最少原语 + 内置 tracing |
| Google ADK | 开源,语言覆盖最广(Python / TypeScript / Go / Java / Kotlin) | Agents、Tools(function / MCP / OpenAPI)、Graph Workflows、Context(sessions / state / events / memory / compaction / caching)、Artifacts、Skills | 要跨语言、要 A2A、部署目标在 Google 侧 |
| Microsoft Agent Framework | 微软系(Semantic Kernel 已并入,见 §3.4 注) | executors + edges + middleware;编排模式含 handoff / concurrent / sequential / group chat / magentic | .NET / Azure 技术栈 |
| Agno(SDK 侧) | 定位正在从「多 agent 框架」转向「agent 服务层」,见 §3.5 | 旧版三级原语 Agents / Teams / Workflows | 想要开箱即用的 agent 服务而非只拿 SDK |
| Pydantic AI(未做一手考证) | 类型安全、结构化输出,可接多个持久化执行引擎,OTel 观测 | 类型化的 agent 与依赖注入 | Python + 强类型诉求 |
| Mastra(未做一手考证) | TypeScript 优先 | agents + graph workflow + memory + RAG + evals + MCP | TS 技术栈 |
| Strands Agents(未做一手考证) | AWS 系,model-driven 循环 | 模型驱动的 agent 循环 | AWS 生态 |
| smolagents(未做一手考证) | Hugging Face,极小 | 动作是「写 Python 代码」而不是发 JSON 工具调用,可接沙箱 | 要极小、要研究代码即动作 |
OpenAI Agents SDK 还带的几件东西值得记住(它们是「框架顺带把运行时的事也做了」的例子):sessions(持久记忆层)、内置 tracing、MCP、human-in-the-loop、sandbox agents(在真实隔离工作区里跑、会话可恢复)、realtime / voice。它默认走 Responses API,官方把它定位成「更高层的 runtime」—— 注意:同一个工具,在它自己的文档里会自称 runtime,在 LangChain 的三分法里会被归进 framework。这不是谁错了,是分类的轴不同;面试时把这句话说出来,比背分类更值钱。
Google ADK 有一处口径很值得引:它把 context 当「源代码」对待 —— 过滤无关事件、摘要旧轮次、惰性加载 artifact、追踪 token 用量;并原生支持 A2A 协议,Workflow Agents 预置 Sequential / Loop / Parallel,部署目标为 Agent Runtime / Cloud Run / GKE。
3.2 Eino(面经直接题,写足)#
它为什么在面经里出现:B13 的标题就是「AI Agent 开发实战(Eino 框架)」,且 B5 把它与 LangChain / LangGraph 并列成一道选型题。它的定位是「Go 生态里那一档」 —— CloudWeGo 出品,自称「draws inspiration from … LangChain and LlamaIndex」但「more in line with Go programming conventions」。Go 语言特性(静态类型、显式错误、结构体)直接塑造了它的抽象形态,这是它和 Python 系框架最本质的差别。
| 面 | 内容 |
|---|---|
| 组件(Component) | ChatModel / Tool / PromptTemplate / Retriever / Document Loader / Lambda |
| 编排三 API | Chain(只能向前的链式有向图)/ Graph(有向、可环、最强最灵活)/ Workflow(DAG + 结构体字段级数据映射) |
| Graph 编排负责什么 | 类型检查、流处理、并发管理、切面注入、选项赋值 —— 也就是把「编排」这件事做成编译器/框架能校验的 |
| 回调与流式 | 回调五类;流式四种范式 Invoke / Stream / Collect / Transform |
| ADK 部分 | ChatModelAgent 内部处理 ReAct 循环并逐步发事件 |
| 运行入口 | Runner 是单次运行入口(Query / Run → 事件流),支持从 checkpoint Resume |
| 多 agent | 可转移控制,或经 adk.NewAgentTool 包装成工具 |
| HITL | 可暂停等人工批准 |
| 预置模式 | DeepAgent(任务规划 + 子 agent 委派)、Supervisor、Sequential |
| 可扩展 | 中间件系统(如文件系统中间件) |
怎么在面试里讲它(这是「知道它站在哪一档」的正确用法):三 API 的差别就是「约束强度」的差别 —— Chain 是线性且只能向前(换控制流就得换工具),Graph 可环最灵活(代价是复杂度与你要自己保证终止),Workflow 是 DAG 加字段级映射(确定性最强、最接近「数据流」而不是「控制流」)。这正好对上 15-orchestration.md 的三档:Chain ≈ 提示链、Workflow ≈ 工作流、Graph ≈ 自主/可环编排。Eino 的 ADK 层做的事(内置 ReAct、Runner + Resume、预置 Supervisor / DeepAgent、中间件)说明它也在从「框架」往「运行时 / Harness」长 —— 和 §3.5 的 Agno、以及 LangChain→LangGraph→Deep Agents 是同一条演化路径。边界:以上是文档口径,你没有写过 Eino,讲的时候说「按文档它站在这一档」。
3.3 低代码平台#
| 工具 | 一句话定位 | 开发方式 | 什么时候选它 | 代价 |
|---|---|---|---|---|
| n8n | 可视化工作流自动化 | 拖拽 | 业务自动化、非技术团队;书里明确提到它允许在同一个系统里同时使用工作流节点和自主 Agent 节点 | 控制流藏在画布后面,可测试性与版本管理弱于代码 |
| Dify | LLM 应用开发平台 | 可视化 + API | 企业级 RAG、知识库应用,要快出成果 | 定制到一定深度会撞到平台的边界 |
它们和 LangGraph 的差别不在「功能」,在「控制流存在哪」 —— 代码里还是画布里。画布的好处是可见与可交接,代价是抽象层更厚、调试时的盲区更多(呼应 §5 的判据)。
3.4 多 Agent 原语#
| 工具 | 一句话定位 | 编排形态 |
|---|---|---|
| CrewAI | 角色化多 Agent 编排(书里就这一行) | 角色分工 + 协作 |
| AutoGen / AG2 | 群聊式多 Agent | 共享对话记录 + 中心化调度 —— 发言者由中心化的 GroupChatManager 裁决,不是真正的去中心化 |
| OpenAI Swarm | 已由 OpenAI Agents SDK 接续 | handoff 网络:每个 agent 配有若干移交选项,可随时把控制权交给任意其他 agent,没有中心调度者 |
书第 10 章的口径要记准:MetaGPT 的控制流实际上是固定流水线(只在通信机制上解耦),AutoGen 群聊是「共享对话记录 + 中心化调度」的混合形态,只有 OpenAI Swarm 在控制流上做到了真正的对等去中心化。另外书里有一条提醒:「Agent Swarm」这个词不对应单一架构 —— 它既指 Swarm 式的 handoff 网络,也被一些商业产品用来指规模化的管理者模式(主 Agent 动态创建大量子 Agent 并行),看到名字要先问它的实际拓扑。
一条二手转述(标清楚):Semantic Kernel 已并入 Microsoft Agent Framework,AutoGen 转入维护模式 —— 这条来自第三方对比文章与项目自述,未做一手考证;但它和「Swarm → Agents SDK」是同一类现象:这一层的产品在快速合并与换代,所以 §5 里「别背 API」那条不是套话。
3.5 服务化 / 平台层#
这一层要单独列,因为它是「同一个产品换个形态卖」的地方,也是最容易被说混的地方。
| 工具 | 服务化形态 |
|---|---|
| Agno | 定位在演进,两版口径不同,如实说:旧版文档讲三层原语 Agents / Teams / Workflows(Teams 三种模式 route / coordinate / collaborate;Workflows 是设计期固定的确定性流水线),外加 Memory 与 session storage;新版官网改口叫 「run agents as a service」,分三层 —— SDK(用 Agno SDK / Claude Agent SDK / Codex SDK 建 agent)/ AgentOS(把 agent 跑成安全、可恢复(durable)、多副本的服务,暴露 REST API 与 MCP server)/ Control Plane(AgentOS UI,看运行、看会话、管平台) |
| LangGraph Platform | LangGraph 的服务器侧产品形态 —— 它提供了 OSS 库没有的恢复与运维能力(见 §4 的口径提醒) |
| Google Agent Runtime | ADK 的部署目标之一(与 Cloud Run / GKE 并列) |
| Claude Managed Agents | Anthropic 托管的 harness,会话跑在 Anthropic 托管的云沙箱里,也可自托管沙箱 |
| Codex app-server | Codex Harness 的持久会话 / 事件流 / 审批回调形态 |
Agno 这件事本身就是一道题:同一个项目,旧文档教你怎么写多 agent,新官网教你怎么把它跑成服务。 面试里最好的答法不是选一边,而是把这条演进说出来 —— 它的意思不是「多 agent 框架过时了」,而是**「建 agent」和「跑 agent」这两件事正在被拆成两层**,这正是本文四类划分在真实产品上的投影。
而 Claude 官方对四个东西的并列区分,是这一层最实用的一张表(建议直接背):Agent SDK(把 Claude Code 的 agent 嵌进你自己的进程)/ Claude Code CLI(终端交互)/ Client SDK(直接调 Claude API,工具循环你自己写)/ Managed Agents(Anthropic 托管 harness)。Agent SDK 给它的是「the same tools, agent loop, and context management that power Claude Code」,并且它跑的是 Claude Code 的二进制;能力清单含内置工具(读写文件、跑命令、网页搜索)、Hooks、Subagents、MCP、Permissions、Sessions(可 resume / fork)、Skills / commands / memory、Plugins。
3.6 通用持久化执行引擎(只做定位)#
| 引擎 | 一句话定位 |
|---|---|
| Temporal | 编排即代码:工作流是普通函数加 SDK 注解,引擎负责事件历史、确定性重放、活动重试与定时器;控制流表达力最强,约束也最硬(代码必须可确定性重放) |
| DBOS | 把持久化执行放进数据库:状态迁移与业务写同库同事务,用「同库同事务」换掉引擎与业务库之间的一致性缝隙,代价是绑定数据库 |
| Inngest / Restate | 同类引擎,LangChain 文档把 Inngest 与 LangGraph、Temporal 并列放在「运行时」 |
| AWS Step Functions | 编排即数据:声明式 JSON 状态机,没有代码级确定性约束;代价是复杂控制流啰嗦、定义与代码两个产物容易漂移 |
细节一律见 ../07-distributed-systems/state-machine.md §8(Temporal / Step Functions / DBOS 的取舍)与 recoverable-task-runtime.md(崩溃点矩阵、事务性发件箱、幂等三边界),本篇不复述。
4. 重点:checkpointer ≠ 持久化执行#
这是本篇最容易踩、也最能分层的一个坑。 先把两个词分开:
| 对比项 | LangGraph 的 checkpointer | Temporal 的持久化执行 |
|---|---|---|
| 保的是什么 | 数据可恢复 | 执行可恢复 |
| 恢复材料 | checkpoint(某一步之后的状态快照) | 事件历史(每一次决策与活动结果) |
| 挂掉之后怎么续 | 从最后一个 checkpoint 往前续 | 从头重放代码,已记录的命令直接返回记录结果、不真的执行 |
| 失败那一轮的工作 | 要重做 | 已完成的活动不会被重跑 |
| 由此产生的约束 | 你必须自己写幂等(重跑那一轮会不会产生重复副作用,是你要负责的) | 工作流代码必须确定性重放(不能直接 now() / random() / 发网络请求) |
| 谁来把中断的运行重新拉起来 | 在 OSS 库里是另一个问题 —— 见下面的口径提醒 | 引擎内建(重放 + 跳过已完成) |
为什么这个区别要紧:它决定你要为「重复副作用」负多少责任。给 LangGraph 挂一个 checkpointer,恢复点之后那一轮如果已经发过邮件、扣过款,重跑就会重做 —— 所以 ../../02-interview/projects/writing-copilot.md 里那条 HITL 故障(无人值守时任务全部挂起)如果要靠 checkpoint 恢复,必须同时保证中断点之后的每一步是幂等的。而 Temporal 那一路,活动级重试与幂等仍然要你写(它管不到外部世界的副作用是否只发生一次,见 ../07-distributed-systems/state-machine.md §5),但它不会因为重放而重跑已经记录过的活动。
⚠️ 口径提醒(不要把一个库的边界说成整个产品的边界):
- LangGraph 侧:开源库里的 checkpointer 提供的是持久化状态与恢复材料;LangGraph Platform 提供的是服务器侧的恢复与运维能力(服务器侧帮你把中断的运行拉起来)。所以「LangGraph 没有持久化执行」这句话对 OSS 库成立,对整个产品不成立 —— 说的时候要指明是哪一侧。
- Temporal 侧:Temporal 出过一个 LangGraph 插件,把 LangGraph 的图当作 Temporal Workflow 跑(这是二手转述,未做一手考证)—— 也就是说这两者不是非此即彼的关系,而是可以把图嵌进引擎里。
两句话合起来才是准确的:LangChain 的三分法里 LangGraph 同时是「框架」和「运行时」;而「运行时」这个词在不同产品上覆盖的范围不一样 —— 判断一个工具到底保到哪一级,要看它的恢复材料是快照还是事件历史、以及它把「重新拉起来」这一步做在哪一层。
接回既有的两篇:state-machine.md §4–§6 讲的是事件历史与确定性重放、以及「重试是「重放 + 跳过已完成」的特例」这条谱系(加 checkpoint 就是手工版的持久化执行);recoverable-task-runtime.md 讲的是把这件事做成一个系统要穷举哪些崩溃点。本篇只做一个动作:把这两个词贴到具体产品上,并说清谁保到哪一级。
5. 选型判据#
书里的两条(这一条最值钱,先背它):
- 「关键考量不在于框架本身的复杂度,而在于它能否用尽可能少的抽象层让你专注于业务逻辑。」
- 「Agent 框架发展迅速……学会某个具体框架的用法并不重要。」
第 2 条不是让你别学,而是说要学的是「这个工具替我兜了什么」,不是它的 API —— 前者管三年,后者管一个版本。呼应 15-orchestration.md 引的 Anthropic 那条:每多一层抽象都会成为以后调试时新的盲区。
再加上工程四条(这四条决定你要不要上运行时 / Harness,而不只是选哪家):
| # | 问题 | 答「要」的后果 |
|---|---|---|
| 1 | 要不要跨重启 | 任务的生命周期能不能被一个进程包住?不能,就必须回答恢复材料是什么(快照还是事件历史)、恢复点由「保存返回」还是「提交完成」决定 |
| 2 | 要不要 HITL | 要,就得有中断 → 等待 → 恢复的原语(见 ./human-in-the-loop.md);HITL 的代价是打断自动化,超时与恢复要在设计时就有 |
| 3 | 谁来运维 | 自建引擎 = 多一个有状态依赖与故障域(../07-distributed-systems/state-machine.md §7 那句「多一个真相来源」)。小团队常常该选托管形态 |
| 4 | 锁定成本 | 编程模型一旦被锁定(工作流必须可重放、状态 schema 必须符合框架要求),迁移成本是改写控制流,不是换个包。Go 技术栈选 Eino / TS 选 Mastra 这类选择,本质是在为「语言生态」而不是「功能」付费 |
一个把四条串起来的落地判据:先问「我需要的是抽象、是恢复、还是循环」—— 需要抽象选框架,需要恢复选运行时或引擎,不想写循环选 Harness;三者都要时,多数团队会选「运行时 + 薄框架」而不是「全都要的 Harness」,因为 Harness 的自带工具与提示同时也是你要绕开的默认值。
6. 接回「从 0 手写」#
框架替你兜的,正好是 Harness 五要素里偏后的那几项。 五要素(书的定义)是上下文管理 + 工具接口 + 约束 + 验证 + 纠正(见 ./08-agent-stack.md),而书里有一句很硬的话:以 Claude Code 为例,它的 Harness 中绝大部分代码是约束、验证与纠正,而非上下文与工具 —— 工具本身只是一小部分。
| Harness 五要素 | 框架能替你兜什么 | 框架兜不了什么 |
|---|---|---|
| 上下文管理 | 消息组装、压缩 / compaction、记忆层(各框架都做了) | 你的业务里什么信息必须留在上下文里 —— 这要你自己判定与评测 |
| 工具接口 | schema 生成、调用解析、结果回灌、MCP 接入 | 描述得好不好(工具选错是描述问题,不是协议问题) |
| 约束 | 权限模型、Guardrails、护栏钩子 | 哪些能力该默认关闭(故障安全默认值是业务决策) |
| 验证 | 结构化输出校验、部分框架带 checkpoint / 恢复 | 「结果真的达成了吗」—— 且只看结构化数据,不看模型自由生成的文本 |
| 纠正 | 重试、超时、中断恢复原语 | 失败时先自己收拾到哪一步、收拾不了何时外抛 |
这张表的用法:从 0 手写一遍的价值,是让你知道框架替你兜的是哪几格、以及没兜的那几格将来会在哪爆。也正因此,姐妹篇 ./17-agent-loop-from-scratch.md 讲的是搭起来的顺序,本篇讲的是搭起来之后你要不要把它交给某一档工具 —— 两篇的接缝就在这张表上。
再加一条必须说清的:框架兜不住「恢复」的语义。它给你 checkpointer 或事件历史,但 「这一步的副作用能不能重做」是你写的(§4)。所以先做幂等与状态设计,再选框架 —— 顺序反了,换哪个框架都会在故障里露馅(recoverable-task-runtime.md 的崩溃点矩阵就是为这件事存在的)。
7. 面试怎么讲#
答这类题的模板(四步):
- 先分档:这个工具是框架 / 运行时 / Harness / 执行引擎里的哪一类(或哪两类)—— 一句话把坐标系立起来;
- 给它的核心抽象与编排模式(图 + 共享状态 / 三原语 Agents-Handoffs-Guardrails / Chain-Graph-Workflow ……);
- 说出它的边界:它兜住了什么、没兜住什么(后半句是加分项,也是 §4 那个坑的落点);
- 落回项目:Writing Copilot 用的是 LangGraph,我写的是 state schema、图的拓扑、HITL 的插入点与幂等;框架替我兜的是消息组装、checkpoint 落地与中断原语。
边界怎么说才自然:不要回避没用过的工具,而是把「用过」和「知道它站在哪一档」显式分开 —— 「Eino 我没写过,但按文档它在 Go 生态里对位 LangGraph,编排三 API 是 Chain / Graph / Workflow,约束强度依次是越来越松 / 越来越灵活;如果让我在 Go 栈上选,我会先看我的控制流需不需要环」。这句话既证明了你有地图,又没有越界。
常见面试问法#
Q: 你都用过哪些 Agent 框架?怎么选?
A:先划边界再给地图。 一手只用过 LangGraph(Writing Copilot 的多智能体写作架构),其余是按定位了解的。选型上我先把候选分成四类 —— 框架(省抽象:LangChain、OpenAI Agents SDK、Google ADK、Eino)、运行时(保证跑得住:durable execution / streaming / HITL / persistence,LangGraph、Temporal、Inngest)、Harness(自带循环与工具、编排不由你写:Claude Agent SDK、Deep Agents SDK、Codex Harness、Pi),再加第四类通用持久化执行引擎(Temporal、DBOS、Step Functions)。判据是「我需要的是抽象、是恢复、还是循环」,而不是谁功能多。书里那两句我一直用:关键考量不是框架复杂度,而是它能不能用尽可能少的抽象层让你专注业务逻辑;以及框架发展很快,学会某个具体框架的用法并不重要。最后落回项目:Writing Copilot 里我真正写的是 state schema、图的拓扑、HITL 插入点与中断后的幂等,框架兜的是消息组装、checkpoint 落地与中断原语。
Q: LangGraph 有 checkpointer,是不是就等价于 Temporal 那种持久化执行?
A:不等价,这是两个不同级别的保证。 checkpointer 保「数据可恢复」 —— 它把某一步之后的状态落盘,恢复时从最后一个 checkpoint 往前续,所以失败那一轮的工作要重做,这就要求你自己把这段做成幂等。Temporal 保「执行可恢复」 —— 它记的是事件历史,恢复时从头重放代码,已记录的命令直接返回记录的结果、不真的执行,所以已完成的活动不会被重跑;代价是工作流代码必须确定性重放(不能直接调 now() / random() / 发网络请求,IO 要放进活动)。口径上还要注意一层:开源库的 checkpointer 边界不等于整个产品的边界 —— LangGraph Platform 提供了服务器侧的恢复与运维能力,而 Temporal 也出过 LangGraph 插件,把图当 Workflow 跑(后者是二手转述)。所以准确的问法是:它的恢复材料是快照还是事件历史、以及「把中断的运行重新拉起来」这一步做在哪一层。
Q: LangChain、LangGraph、Eino 各自的抽象和适用场景是什么?
A:按「抽象强到什么程度」答。 LangChain 是最上面那层框架 —— 提供结构化内容块、agent 循环、中间件这些抽象,1.0 建在 LangGraph 之上;它的价值是少写集成代码,代价是抽象层厚、调试时盲区多。LangGraph 是底层的编排框架与运行时 —— 核心抽象是图 + 共享状态(节点是步骤、边是迁移、条件边是守卫),换来的是控制流可枚举、可测试、可画出来,加上 checkpointer 做状态落盘与 HITL 中断;代价是 state schema 要你自己设计。Eino 是 Go 生态的那一档(CloudWeGo 出品),组件是 ChatModel / Tool / PromptTemplate / Retriever / DocumentLoader / Lambda,编排三个 API 是 Chain(只能向前的链)/ Graph(可环、最灵活)/ Workflow(DAG + 结构体字段级映射);它的 ADK 层还内建了 ChatModelAgent 的 ReAct 循环、Runner 的 checkpoint Resume、预置的 DeepAgent / Supervisor / Sequential 和中间件系统。适用场景一句话:要最少胶水代码用 LangChain,要控制流可控可测用 LangGraph,Go 技术栈且要类型安全用 Eino。补一句边界:Eino 我没写过,以上是文档口径。
Q: Claude 侧的 SDK / CLI / Client SDK / Managed Agents 这几个到底怎么选?
A:它们是同一件事的四种「谁来跑循环、跑在哪」的答案,官方就是并列区分的:Agent SDK 是把 Claude Code 的 agent(the same tools, agent loop, and context management that power Claude Code)嵌进你自己的进程,它跑的是 Claude Code 的二进制,能力含内置工具、Hooks、Subagents、MCP、Permissions、可 resume / fork 的 Sessions、Skills / memory;Claude Code CLI 是终端交互形态;Client SDK 是直接调 Claude API,工具循环你自己写(也就是回到 §6 那张表,五要素全是你的事);Managed Agents 是 Anthropic 托管的 harness,会话跑在托管的云沙箱里,也支持自托管沙箱。判据:要最大可控性、愿意自己写循环 → Client SDK;要现成的循环与工具、又要嵌进自家产品 → Agent SDK;连运维都不想管 → Managed Agents。书里对同类事情给过一个对照:Codex 是产品,Codex Harness 是驱动 App / CLI / IDE 扩展这些形态的那层运行时,它给三条集成路径(codex exec / Codex SDK / app-server),区别是 Codex 的 Harness 开源,Claude 侧对外开放的是 SDK 接口,Harness 实现本身并不开源 —— 这一条在选型时会变成实打实的可改造性差异。
Q: 给你一个「任务要跑几十分钟、中途要人工审批、团队只有两三个人运维」的场景,你怎么选?
A:先问需求落在哪一格,再选形态。 这个场景同时踩中 §5 的三条:要跨重启(几十分钟的任务不能被一个进程的生命周期包住)、要 HITL(人工审批 = 中断 → 等待 → 恢复)、运维人力薄。所以:① 恢复必须先设计再选工具 —— 说清恢复材料是快照还是事件历史、恢复点由「提交完成」还是「保存返回」决定、以及中断点之后的每一步是否幂等(否则重做会重复副作用);② 能不运维就不运维,小团队优先托管形态(Temporal 托管服务 / LangGraph Platform / Step Functions)而不是自建集群 —— 因为自建引擎等于多一个有状态依赖和一个故障域,还多一个真相来源;③ 锁定成本要提前算:一旦编程模型被锁(工作流必须可重放),迁移成本是改写控制流而不是换包;④ 别把 Harness 当默认解 —— 它自带的工具与提示同时也是你要绕开的默认值,而审批回调、权限这类东西在各家 Harness 里语义并不一致。收口一句:这个场景里「选哪家」不如「先确定恢复语义与幂等边界」重要,因为框架换得起,故障路径上的漏洞换不起。
易错点#
| 易错说法 | 问题 | 应该说 |
|---|---|---|
| 「LangGraph 有 checkpointer,所以它是持久化执行」 | 把数据可恢复说成执行可恢复 | checkpointer 保数据:从最后一个 checkpoint 往前续,失败那一轮要重做,所以要求你写幂等;Temporal 保执行:事件历史 + 确定性重放,已完成的活动不重跑 |
| 「LangGraph 没有持久化执行」 | 用开源库的边界代替产品的边界 | LangGraph Platform 提供服务器侧的恢复能力;而 Temporal 也有 LangGraph 插件把图当 Workflow 跑。要说清「哪一侧、哪一层」 |
| 「用了运行时就不用管幂等了」 | 越过了信任边界 | 持久化执行只自动跳过已记录的步骤;外部副作用是否只发生一次,仍然是你的事(state-machine.md §5) |
| 「Claude Code 的 Harness 是开源的」 | 与书的口径相反 | Codex 的 Harness 开源(Codex Harness);Claude 侧对外开放的是 SDK 接口,Harness 实现本身并不开源。这个差别在选型时是可改造性差异 |
| 「Codex 和 Codex Harness 是一回事」 | 产品 vs 运行时 | Codex 是产品(App / CLI / IDE 扩展),Codex Harness 是那层运行时,给 codex exec / Codex SDK / app-server 三条路径 |
| 「Agno 就是个多 agent 框架」 | 定位已经演进 | 旧文档是 Agents / Teams / Workflows 三层原语;新官网改口 「run agents as a service」(SDK / AgentOS / Control Plane)—— 如实说它在从框架转向服务层 |
| 「AutoGen 群聊和 Swarm 都是去中心化」 | 混了两种拓扑 | AutoGen 群聊是共享对话记录 + 中心化调度(发言者由 GroupChatManager 裁决);只有 Swarm 的 handoff 网络在控制流上做到对等去中心化 |
| 「Agent Swarm 是一种架构」 | 名字不等于结构 | 书第 10 章:这个词至少指两类东西 —— handoff 网络,以及规模化的管理者模式(主 Agent 动态创建大量子 Agent)。先问实际拓扑 |
| 「选框架看谁功能多」 | 判据反了 | 书里的判据是**「能否用尽可能少的抽象层让你专注于业务逻辑」**;每多一层抽象都是调试时的新盲区 |
| 「先把 LangGraph 的 API 背熟」 | 学到会过期的部分 | 书:「学会某个具体框架的用法并不重要」 —— 要学的是它替你兜了什么、没兜什么 |
| 「n8n / Dify 和 LangGraph 是一类东西」 | 混淆了同一层里的不同开发方式 | 三者都可能被归进「框架」,但 n8n / Dify 是低代码,控制流存在画布里而非代码里;代价是可测试性与版本管理更弱 |
| 「OpenAI Agents SDK 就是 Swarm 改名」 | 漏了它的定位 | 它是 Swarm 的生产级后继,原语刻意少(Agents / Handoffs / Guardrails),另外自带 sessions、tracing、MCP、HITL、sandbox agents,官方自称更高层的 runtime |
| 「Temporal / DBOS 是 Agent 框架」 | 类型错 | 它们是通用持久化执行引擎,不针对 Agent;细节见 state-machine.md §8 |
| 「Pi 内置四个工具,所以它只能做四件事」 | 二手描述,要标来源 | 二手说法是它内置 read / write / edit / bash 四个工具,靠 TypeScript 扩展与 skill 加能力,会话是树结构可分支 —— 未做一手考证,讲的时候说这是二手 |
| 「框架能保证恢复正确」 | 高估了框架的边界 | 框架给的是恢复材料与中断原语;「这一步能不能重做」是你写的。所以先做幂等与状态设计,再选框架 |
| 把「知道它站在哪一档」讲成「我用过」 | 触碰仓库硬规矩 | 一手只有 LangGraph(Writing Copilot);Eino 只到「按文档它在 Go 生态对位 LangGraph」;其余按「按这张图我会这么选」讲 |
自测#
1. 用户说「langgraph、agno、pi、Claude code SDK 是 agent runtime 工具」。这句话哪里不准?你会怎么拆开它?
答案
不准在它把四件不同类型的东西装进了同一个词。 逐个拆:
- LangGraph —— 官方描述是「构建、管理、部署长时间运行的有状态 agent 的低层编排框架与运行时」,所以它同时是框架和运行时(这也是 LangChain 三分法里唯一横跨两类的那个)。
- Agno —— 它的定位正在演进,两版口径不同:旧文档讲 Agents / Teams / Workflows 三层原语(多 agent 框架),新官网改口成 「run agents as a service」,分 SDK / AgentOS / Control Plane 三层。所以现在更准确的说法是「框架 + agent 服务层」。
- Pi —— 是极简 Coding Agent Harness(二手描述:内置只有 read / write / edit / bash 四个工具,靠扩展与 skill 加能力)。它是 Harness,不是运行时。
- Claude Agent SDK —— 书里的定位是「生产级 Agent 开发框架」,LangChain 的三分法会把这类归进 Harness(自带工具、提示与循环)。而且要说清 Claude Code / Agent SDK / Client SDK / Managed Agents 四者的分工。
拆法就是本文 §1 那张表:框架(省抽象)/ 运行时(保证跑得住:durable execution、streaming、HITL、persistence)/ Harness(自带循环与工具)/ 通用持久化执行引擎。判据一句话:「你想省抽象、想跑得住、还是想连循环都不写?」 —— 拆开之后,后面「选哪个」才有意义,否则是在比四个不同问题的答案。
要补的一句:同一个工具在不同文档里会被归到不同类(OpenAI Agents SDK 官方自称「更高层的 runtime」,LangChain 的三分法会把它归进 framework)—— 这不是谁错了,是分类的轴不同。面试时点出这一点,比背分类更值钱。
2. 一个跑在 LangGraph 上的流程,在「调用外部支付接口」之后进程被杀。同事说「有 checkpointer,重启就能续上」。这句话哪里对、哪里不对?
答案
对的部分:checkpointer 确实让状态可恢复 —— 重启后能从最后一个 checkpoint 读回状态并往前续,不至于从头开始。这是它的真实价值。
不对的部分有三层:
- 恢复的是数据,不是执行。 从最后一个 checkpoint 往前续,意味着checkpoint 之后那一轮的工作全部重做。如果那一轮包含「调用支付接口」,重跑就是再扣一次钱。而 Temporal 式的持久化执行里,已记录的活动不会被重跑(重放时先查事件历史,有记录就返回记录结果、不真的执行)—— 两者不是同一个保证。
- 所以幂等是你的事,不是 checkpointer 的事。 正确做法是:这一步带操作标识(幂等键),重跑时先查询外部系统的实际结果再决定是否重做(
recoverable-task-runtime.md§5 的四步);写操作本身要么幂等,要么可补偿。checkpointer 只负责「把状态放回去」,它不知道外部世界发生了什么。 - 口径上还要分清是哪一侧。 如果用的是 LangGraph Platform,它提供服务器侧的恢复与运维能力(帮你把中断的运行拉起来);开源库的 checkpointer 本身不解决「谁来重新拉起这次运行」。「LangGraph 没有持久化执行」这句话对 OSS 库成立,对整个产品不成立。
收口:框架换得起,故障路径上的漏洞换不起。 所以正确顺序是先设计幂等与状态,再选框架 —— 反过来做,换哪个框架都会在故障里露馅。
3. 有人问「Eino 和 LangGraph 有什么区别」。你没写过 Eino,怎么答得不心虚?
答案
显式分开口径:「LangGraph 我做过,Eino 我按文档知道它站在哪一档。」 然后按结构化信息答:
定位对照:LangGraph 是 Python 生态的低层编排框架与运行时,核心抽象是图 + 共享状态;Eino 是 Go 生态的 LLM 应用框架(CloudWeGo 出品),Go 的静态类型与显式错误风格直接塑造了它的抽象形态,官方说它「draws inspiration from LangChain and LlamaIndex」但更贴合 Go 的编程习惯。
抽象对照:Eino 的组件是 ChatModel / Tool / PromptTemplate / Retriever / Document Loader / Lambda;编排三个 API是 Chain(只能向前的链式有向图)/ Graph(有向、可环、最强最灵活)/ Workflow(DAG + 结构体字段级数据映射)。这三者的差别就是「约束强度」的差别 —— Chain 最死但最简单,Workflow 最强确定性(最像数据流),Graph 最灵活(代价是复杂度与你要自己保证终止)。这正好对上编排的三档:Chain ≈ 提示链、Workflow ≈ 工作流、Graph ≈ 可环的自主编排。
运行时侧对照:Eino 的 ADK 层说明它也在往运行时 / Harness 长 —— ChatModelAgent 内部处理 ReAct 循环并逐步发事件;Runner 是单次运行入口(Query / Run → 事件流)支持从 checkpoint Resume;预置 DeepAgent(任务规划 + 子 agent 委派)、Supervisor、Sequential;有多 agent 控制转移与 adk.NewAgentTool(把 agent 包装成工具);human-in-the-loop 可暂停等人工批准;有可扩展中间件系统。
收口:「如果我在 Go 栈上选,我会先看我的控制流需不需要环 —— 需要就走 Graph,不需要就退到 Chain / Workflow 拿更强的确定性和更少的自由度。」 这样答的要点是:你给的是地图和一个可执行的判据,而不是假装用过。
4. 团队要做一个长任务平台:任务跑几十分钟到几小时,中途有若干人工审批点,且希望「重启后接着跑」。请给出选型判据,并说明哪些是「选型」解决不了的。
答案
先立判据,再点名工具。
① 需求落在哪一格:跨重启(几十分钟到几小时的任务包不住一个进程)+ 人工审批(中断 → 等待 → 恢复)→ 这里要的是运行时或通用持久化执行引擎,不是「功能更多的框架」。判据一句话:「我要的是抽象、是恢复、还是循环?」—— 这个场景要恢复。
② 恢复语义先定,工具后选:说清三件事 —— 恢复材料是快照还是事件历史(决定失败那一轮要不要重做)、恢复点由「保存返回」还是「提交完成」决定(异步写入会让「保存返回」不等于可用)、副作用如何判重(操作标识 / 幂等接口 / 补偿)。工具形态上,要执行可恢复就选事件历史那一类(Temporal / DBOS / Step Functions),只接受数据可恢复 + 自己写幂等就用 LangGraph 这类图的方案。
③ 运维与锁定成本:小团队优先托管形态而非自建集群 —— 自建引擎等于多一个有状态依赖、一个故障域、一个真相来源。锁定成本要提前算:一旦编程模型被锁(工作流必须可重放、状态 schema 必须符合框架要求),迁移成本是改写控制流而不是换包,Go 栈选 Eino / TS 栈选 Mastra 这类选择本质是在为语言生态而不是功能付费。
选型解决不了的(这部分更要答出来):① 幂等是设计出来的,不是选出来的 —— 无论选哪个引擎,外部世界的副作用是否只发生一次,都要靠你带操作标识、先查后重试(recoverable-task-runtime.md §5);② 审批语义的跨框架不一致 —— HITL 这个回调在不同运行时里语义不同(谁触发、状态存在哪、超时怎么办),框架换得起,语义漂移要你自己兜;③ 故障路径的验收方式 —— 「跑通一遍」证明不了可恢复性,要靠在崩溃点矩阵的每一行注入故障 + 用会计数的 stub 断言每个外部操作恰好真正执行一次;④ 验证「结果真的达成了吗」 是 Harness 五要素里的「验证」,这是业务判定,框架给不了。