2026 Agent 框架怎么选?拆 3 层底层逻辑(运行循环 / 记忆 / 工具协议)+ 一张决策表

本文剖析2026年主流Agent框架(LangGraph、CrewAI、OpenAI/Claude SDK等)的底层选型逻辑,指出功能对比表失效的根本原因在于框架本质是架构约束而非功能集合。核心聚焦三层不可变逻辑:运行循环(控制流归属)、记忆系统(工作记忆/会话状态/长期记忆的分层治理)、工具协议(MCP统一后模型供应商与部署路径的隐性绑定)。强调长期记忆应脱离框架、通过MCP接入外部系统,选型需按模型策略→项目阶段→团队能力顺序决策。

CFzjy

AI Engineer


  ▍深耕领域  AI Agent 架构设计 Harness 插件开发 Context Engineering 多智能体协同 & RAG
  ▍技术底座  Python TypeScript · Cordis 插件 MCP & Skills · FastAPI Docker
  ▍工程能力  专注 Agent 运行时与 Harness 插件开发、长上下文与流式交互优化、LLM 全链路工程化落地

   

「 让 AI 交互更智能,让技术落地更高效 」   |   欢迎技术探讨 / 项目合作,关注解锁大模型与智能交互的无限可能!

2026 Agent 框架怎么选?拆 3 层底层逻辑(运行循环 / 记忆 / 工具协议)+ 一张决策表

📚 《大模型效率拆解》连载专栏 · 第 05 篇

每年都有人问同一个问题:LangGraph、CrewAI、OpenAI Agents SDK、Claude Agent SDK、AutoGen……2026 年该用哪个?而每年的大多数"选型指南"都在做同一件事:把官网 feature 列表抄进一张对比表,最后给一句"按需选择"的正确废话。你读完还是不会选。

这篇换个拆法:框架之间真正的差异不在功能列表,而在三层底层逻辑——运行循环、记忆系统、工具协议。功能列表每年过期,这三层逻辑三年内都不会变。把三层拆透,你就能自己推导出任何框架的适用边界,再也不用依赖别人的结论。文末附一张可直接照抄的决策表。

痛点一:被 feature 列表绑架。 “CrewAI 有 role 概念!LangGraph 有 checkpoint!”——你在比较的是营销词汇,不是架构决策。

痛点二:选完框架才发现被绑定。 用了半年 OpenAI Agents SDK,公司要换国产模型,重构成本比重新立项还高。

痛点三:分不清"框架"和"模型"。 2026 年框架之争的本质是生态之争——框架绑定的是模型供应商、工具生态和部署路径,而不是抽象的技术优劣。

本文基于 2026 年 10 月主流框架的公开文档与社区实测共识(State of AI Agents 报告、各框架官方文档、多份横向对比),不替任何厂商站台。想回看系列前四篇(Flash 五板斧、推理强度、单卡压缩术、多 Agent 反共识),可以先关注我的 CSDN 主页。

一、为什么功能对比表没用:框架是"约束"不是"功能包"

1.1 从一个直觉误区说起:你以为在选工具,其实在选约束

选框架时你的第一反应是打开一张"功能对比表":谁有记忆、谁有缓存、谁有流式输出。但框架的本质不是提供功能,而是施加约束——它决定了你怎么写代码、状态存哪、控制流谁说了算。同样的功能(比如多步工具调用),在不同框架里是三种完全不同的写法:

角色式框架(CrewAI)

循环式框架(OpenAI/Claude SDK)

图式框架(LangGraph)

你画状态机
节点+边显式定义

控制流:代码说了算
确定性、可审计

你写 agent loop
模型自己决定下一步

控制流:模型说了算
灵活、涌现

你写角色和任务清单
框架内部编排

控制流:框架说了算
上手快、黑盒

同一种功能,三种工程形态
选框架 = 选控制流的归属

这就是为什么"LangGraph 和 CrewAI 谁更好"是个伪问题:一个是"把控制流写死在代码里的确定性引擎",一个是"把控制流交给框架的声明式编排器"——它们适合的人群、项目阶段、可维护性曲线完全不同。理解框架,要从三层底层逻辑开始。

二、第一层:运行循环——控制流归谁

所有 Agent 框架剥到最里层,都是同一个最小循环的变体。先把原版循环写出来(这段 Python 是一个完整可运行的最小 Agent loop,所有框架都在它之上做文章):

"""最小 Agent 运行循环:模型 → 工具 → 观察 → 再模型,直到产出最终答案。
LangGraph / OpenAI Agents / Claude Agent SDK 都是这个循环的不同变体。"""
from dataclasses import dataclass, field
from typing import Callable


@dataclass
class ToolCall:
    """模型发起的一次工具调用。"""
    name: str
    args: dict


@dataclass
class LoopState:
    """循环状态:消息历史 + 已用步数。"""
    messages: list = field(default_factory=list)
    steps: int = 0


def run_agent_loop(
    call_model: Callable[[list], dict],
    call_tool: Callable[[ToolCall], str],
    max_steps: int = 20,
) -> str:
    """最小 Agent 循环。

    每轮:模型看消息历史 → 决定(调用工具 / 给出终答)
    - 工具调用 → 执行工具 → 结果写回历史 → 下一轮
    - 终答 → 返回
    max_steps 是防死循环的硬闸(对应各框架的 step 上限)。
    """
    state = LoopState()
    state.messages.append({"role": "user", "content": "帮我查一下北京今天的天气并给出行建议"})

    for _ in range(max_steps):
        state.steps += 1
        decision = call_model(state.messages)          # 模型决策
        if decision.get("done"):
            return decision["answer"]                   # 循环出口
        tool = ToolCall(decision["tool"], decision["args"])
        result = call_tool(tool)                        # 工具执行
        state.messages.append({"role": "tool", "content": result})
    raise RuntimeError(f"超过 {max_steps} 步仍未收敛")   # 兜底:防死循环


if __name__ == "__main__":
    # 演示用假模型/假工具:第一轮调工具,第二轮收尾
    fake_model = lambda msgs: ({"done": True, "answer": "天气晴,建议短袖出行。"}
                               if len(msgs) > 1
                               else {"done": False, "tool": "get_weather", "args": {"city": "北京"}})
    fake_tool = lambda tc: "晴,28°C" if tc.name == "get_weather" else "unknown"
    print(run_agent_loop(fake_model, fake_tool))

框架的分野,就发生在这个循环的三个决策点上:

决策点一:下一轮"去哪"谁定? LangGraph 的答案:你定——状态图里每个节点连向下一个节点,循环是图的一部分;OpenAI/Claude SDK 的答案:模型定——循环内置,模型输出决定继续调工具还是收尾;CrewAI 的答案:框架定——任务清单和角色关系在框架内部被翻译成执行顺序。

决策点二:状态存哪、谁可见? LangGraph 把循环状态(消息、中间产物)放进显式的 State 对象,可持久化(checkpoint)、可回放、可人审;SDK 系把状态收进会话对象,开发者能读但不用管;角色式框架的状态最不透明——出问题最难调试。

决策点三:流程失败后能否"接上"? 图式框架支持从任意节点恢复(checkpoint 重放),这是生产级长任务的关键能力;循环式支持重试单步;角色式往往只能整轮重来。

一句话选型结论:需要审计、恢复、确定性的生产工作流 → 图式;要快速原型、模型自由度高 → 循环式;要演示级多角色协作 → 角色式。 更多判据看第五章决策表。

三、第二层:记忆系统——状态的生命周期

Agent 的"记忆"其实是三个不同生命周期的东西,被框架们笼统地叫成一个词。拆开看:

记忆类型生命周期典型实现LangGraphOpenAI/Claude SDKCrewAI
工作记忆单次运行消息列表(上下文窗口)Statesession内部上下文
会话状态跨轮对话持久化状态/checkpointcheckpointersessionsmemory 模块
长期记忆跨会话向量库/知识库/文件store + 外部检索自管(接外部)long-term memory

关键判断:你需要的到底是哪一层? 大多数业务 Agent 只需要前两层——而这两层所有主流框架都够用。真正拉开差距的是第三层(长期记忆),而它恰恰是最不该依赖框架内置实现的一层:长期记忆的质量取决于你的检索/存储方案(向量库、知识图谱、文件系统),把这块绑死在框架的 memory 模块里,等于把最核心的数据资产交给了最不透明的黑盒。长期记忆用外部系统 + MCP 工具接入,是 2026 年的主流实践——框架只管前两层,第三层保持可替换。

四、第三层:工具协议——MCP 之后,绑定风险藏在哪

2026 年工具协议的故事很简单:MCP 赢了。四大主流框架全部支持 MCP,工具生态以 MCP server 的形式流通。但"都支持 MCP"不等于"没有绑定",真正的绑定风险在另外两个地方:

第一,模型供应商绑定。 OpenAI Agents SDK 对 OpenAI 系模型(含 reasoning、结构化输出等新特性)支持最深;Claude Agent SDK 对 Claude 系(长上下文、流式、工具调用语义)最顺。你选的框架默认假设你用的是哪家模型——先定模型策略,再定框架,顺序反了会非常难受。

第二,部署路径绑定。 LangGraph 深度绑定 LangSmith/LangGraph Platform(可观测、部署、托管);OpenAI SDK 绑定 Responses API 与 OpenAI 托管;Claude Agent SDK 绑定 Claude Code 生态与本地运行。"框架免费"的代价是部署路径的锁定——评估框架时,把它的商业化路径也当成一条选型维度。

五、决策表与决策流程:照着抄

三层逻辑拆完,直接给结论。按你的场景对号入座:

你的场景推荐路线理由
复杂生产工作流:审批、多步数据管道、需要断点恢复与审计LangGraph显式状态机 + checkpoint,唯一把"流程确定性"当一等公民的路线
单 Agent 编码/研发助手,Claude 系模型Claude Agent SDK循环内置、MCP 一等公民、与 Claude Code 生态同源
快速原型 / OpenAI 系模型 / 需要 handoff 的轻量多 AgentOpenAI Agents SDK上手最快,agent/handoff/guardrail 原语简洁
演示级多角色协作 / 非技术团队搭原型CrewAI角色声明式,最接近"搭积木"的体验
多供应商、强中立、要自己掌控一切自研最小循环(本文代码就是起点)三层逻辑全部可控,代价是要自己写可观测与恢复

决策流程一张图:

生产级复杂工作流
需要审计/恢复

原型 / MVP

锁定 OpenAI

锁定 Claude

多供应商 / 不确定

强工程团队

弱工程团队

开始选型

项目阶段?

LangGraph

模型策略?

OpenAI Agents SDK

Claude Agent SDK

团队能力?

自研最小循环

CrewAI(先跑通再换)

选型完成

六、实战避坑指南:高频问题速查表

序号遇到的报错或现象背后的真正原因一句话解决办法
1Agent 无限循环调工具烧 token循环缺 max_steps 硬闸或终止条件模糊每个循环显式设步数上限 + 预算熔断
2换模型供应商后框架大面积报错框架与模型供应商存在隐性绑定(特性/语义)选型顺序:先定模型策略,再定框架
3长期记忆换框架要重写把长期记忆绑死在框架内置 memory 模块长期记忆走外部系统 + MCP,保持可替换
4生产事故后无法回放定位状态没有 checkpoint,出问题只剩日志生产工作流选带状态持久化/回放的路线
5CrewAI 搭的 demo 上生产后调试无门角色式框架控制流黑盒,中间态不可见生产化前迁移到图式或自研,demo 只当 demo
6多 Agent 编排越做越像"分布式单体"把微服务思维平移到 Agent 上(见第 04 篇)回到五个拆分信号,不满足就拆回单 Agent

结语

选框架的底层逻辑只有三层:运行循环(控制流归代码、模型还是框架)、记忆系统(工作记忆/会话状态/长期记忆三层生命周期,前两层框架管、第三层自己管)、工具协议(MCP 统一了工具,绑定风险转移到模型供应商与部署路径)。把这三层对照你的项目阶段和团队能力,决策表一填就完事——记住:框架选错的最大成本不是迁移代码,而是在错误的方向上把团队的经验曲线爬了一遍。

一张图总结全文:

Agent框架选型·思维导图总结

知识要点文字回顾:① 框架的本质是约束不是功能,同功能三种写法:图式/循环式/角色式;② 生产工作流要确定性 → 图式;原型要速度 → 循环式;演示要角色 → 角色式;③ 长期记忆别绑框架,外部系统 + MCP 接入;④ MCP 统一了工具协议,绑定风险在模型供应商与部署路径;⑤ 选型顺序:模型策略 → 项目阶段 → 团队能力 → 框架。

《大模型效率拆解》连载专栏五篇至此收尾:Flash 五板斧(省钱)、推理强度(省推理 token)、单卡压缩术(省硬件)、多 Agent 反共识(省架构复杂度)、框架选型(省迁移成本)——贯穿的一条主线是:2026 年做 AI 应用,拼的不再是"用什么模型",而是把效率当系统性问题来设计。后续新系列正在筹备,关注 CSDN 主页 第一时间看到。

你现在用的是哪个框架?换过框架吗、因为什么换的?评论区聊聊,我挨个回。 本文框架信息截至 2026 年 10 月,各框架迭代极快,有变化评论区提醒我。

参考资料(正文观点来源):State of AI Agents 2026 报告、LangGraph / OpenAI Agents SDK / Claude Agent SDK / CrewAI 官方文档、Langfuse 与多份 2026 横向对比、Anthropic 多 Agent 官方指南(第 04 篇判据的延续)。

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain&#39;s apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath(&#39;DeepLearnToolbox&#39;));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand(&#39;state&#39;,0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W&#39;); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand(&#39;state&#39;,0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = &#39;sigm&#39;;%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, &#39;Too big error&#39;);```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand(&#39;state&#39;,0)sae = saesetup([784 100]);sae.ae{1}.activation_function = &#39;sigm&#39;;sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)&#39;)% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = &#39;sigm&#39;;nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, &#39;Too big error&#39;);```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x&#39;,28,28,60000))/255;test_x = double(reshape(test_x&#39;,28,28,10000))/255;train_y = double(train_y&#39;);test_y = double(test_y&#39;);%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you&#39;ll get around 1.2% errorrand(&#39;state&#39;,0)cnn.layers = { struct(&#39;type&#39;, &#39;i&#39;) %input layer struct(&#39;type&#39;, &#39;c&#39;, &#39;outputmaps&#39;, 6, &#39;kernelsize&#39;, 5) %convolution layer struct(&#39;type&#39;, &#39;s&#39;, &#39;scale&#39;, 2) %sub sampling layer struct(&#39;type&#39;, &#39;c&#39;, &#39;outputmaps&#39;, 12, &#39;kernelsize&#39;, 5) %convolution layer struct(&#39;type&#39;, &#39;s&#39;, &#39;scale&#39;, 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, &#39;Too big error&#39;);```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, &#39;Too big error&#39;);%% ex2 neural net with L2 weight decayrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex3 neural net with dropoutrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex4 neural net with sigmoid activation functionrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);nn.activation_function = &#39;sigm&#39;; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex5 plotting functionalityrand(&#39;state&#39;,0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = &#39;softmax&#39;; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand(&#39;state&#39;,0)nn = nnsetup([784 20 10]); nn.output = &#39;softmax&#39;; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值