AI

AI 智能体框架怎么选:从任务拆解到最小流程

选框架最怕的场景不是“功能不够”,而是代码写到一半发现状态管不住、循环停不下来、换个模型就要重写一遍。同一个任务——比如“读取一封客户邮件,判断意图,必要时查知识库,然后起草回复”——在 LangGraph、模型厂商原生 Agents SDK 和 LlamaIndex 里,写法差别其实不在 API 长什么样,而在于它默认替你管了什么、又默认不管什么。下面先把这个任务拆成三类需求,再给出选型判断和一条最小可运行路径。

先看同一个任务会撞上哪三类需求

把“邮件意图判断 + 知识库检索 + 起草回复”拆开,会发现它同时包含三种性质不同的工作:

  • 流程编排:先分类意图,命中“退款/故障”才去检索,检索为空要重试或转人工,最后才生成回复。这是控制流问题,核心是状态、分支和循环。
  • 原生工具调用:分类和起草都要调用模型,检索要调用向量库,可能还要调用工单系统。这是“模型能不能稳定地按格式发起调用”的问题。
  • 文档检索:把产品文档切片、建索引、按语义召回,并把召回片段塞进上下文。这是数据管道问题,和编排是两件事。

三类需求权重不同,答案就不同。控制流复杂、分支多、需要中途持久化和人工介入的,编排框架更省事;只是线性地把几个工具串起来、且已经绑定某家模型,原生 SDK 往往够用;任务八成时间花在“从自有文档里找依据”,检索框架的收益最大。

同一个任务拆分为流程编排、工具调用与文档检索三类需求的示意图

三个框架各自默认替你管什么

LangGraph:把智能体写成显式状态机

LangGraph 的定位是把智能体建模成显式状态机——子图嵌套、并行分支合并、基于中间结果动态路由、细粒度检查点,都是它的一等公民。当“控制流本身才是难点”时,显式图结构比对话式的隐式循环更好调试:你能看到每一步之后状态长什么样,也能在任意节点中断、恢复、注入人工确认。

代价是你要自己定义状态结构、节点函数和边条件,前期样板代码比“一行 agent 调用”多。但如果任务里有重试、有分支、有需要落库的中间结果,这部分投入很快回本。

模型厂商原生 Agents SDK:极简,但复杂逻辑自己扛

以 OpenAI Agents SDK 为代表的原生方案是刻意保持极简的:复杂路由、持久状态和长时间编排通常交给应用代码自己处理。这种设计对“简单的交接链”很合适——几个工具、一条主流程、不需要跨会话记忆,写起来最快,和自家模型的工具调用格式贴合度也最高。

需要留意的两点:一是绑定,深度依赖某家平台意味着换模型时改动面可能不小;二是能力边界,一旦出现分支逻辑或需要持久化状态,你实际上是在应用层手搓一个编排层,这时不如直接换框架。

LlamaIndex:检索优先的智能体开发

LlamaIndex 起家于检索框架,后来演进出完整的智能体平台。如果智能体的主要工作是查询、推理并基于自有数据生成,它在索引、召回、上下文拼装这条链路上的成熟度最高,知识密集型问答、文档助手、研究类助手是它的主场。反过来,如果你的瓶颈在复杂控制流而不是检索质量,它的编排表达能力未必比 LangGraph 顺手。

选型决策表

判断维度LangGraph原生 Agents SDKLlamaIndex
控制流复杂度高:分支、循环、并行、子图低:线性交接为主中:以检索链路为中心
状态与持久化内置检查点,可中断恢复需自行实现支持,但更偏数据侧
工具调用需自行定义节点与工具边界与自家模型贴合最紧支持,围绕检索组织
文档检索需接入外部检索组件需自行拼装最强项
厂商绑定较低,模型可替换较高较低
调试方式逐步查看状态快照依赖平台日志侧重检索命中与上下文

一句话版本:控制流是难点选 LangGraph,检索是难点选 LlamaIndex,两者都不难、只想快点跑通且已绑定模型选原生 SDK。

最小可运行流程:状态、节点、流转条件

不管选哪个框架,先把这三样写清楚,代码只是翻译。

状态(State):定义一个贯穿全程的字典,至少包含 email_text、intent、retrieved_docs、draft、retry_count、needs_human。所有节点只读写这个结构,不靠隐式全局变量。

节点(Node):拆成四个纯函数——classify_intent、retrieve_docs、draft_reply、escalate。每个节点输入状态、输出状态增量,内部逻辑尽量不依赖外部可变状态,方便单测。

流转条件(Edge):分类后按 intent 分支;检索后判断 retrieved_docs 是否为空,为空且 retry_count < 2 则回到检索节点并把计数加一,超过上限走 escalate;否则进入起草。

纯文本
def route_after_classify(state):
    if state["intent"] in ("refund", "bug"):
        return "retrieve"
    return "draft"

def route_after_retrieve(state):
    if state["retrieved_docs"]:
        return "draft"
    if state["retry_count"] < 2:
        return "retrieve"      # 回到检索节点,计数在节点内自增
    return "escalate"

这段逻辑在任何框架里都能照搬,区别只是“把它写成图的边”还是“写成 if-else”。如果它在你眼里已经是一张图,LangGraph 的表达会更接近你的心智模型;如果只是两个 if,原生 SDK 就够了。

包含分类、检索、重试循环与转人工分支的最小智能体流程图

跑通之后,用同一批邮件样本回放一遍,重点看三件事:意图分类错在哪几条、检索为空时重试是否真的收敛、转人工的触发是否符合预期。这三项稳定了,再考虑加并行分支或换模型。

用四个指标判断值不值得采用

框架能不能留下来,不看宣传页,看这四项在你项目里的实际表现:

  • 结果准确性:同一批测试样本下,分类和草稿的通过率是否稳定,换模型后是否明显抖动。
  • 失败恢复:进程中断、模型超时、检索报错之后,能否从检查点继续,而不是从头再跑一遍。
  • 调试难度:出错时能不能定位到具体节点和当时的输入状态。如果只能看到一坨日志,排错成本会随流程变长而快速上升。
  • 后续维护成本:加一个分支、换一个模型、多接一个数据源,需要改动的文件数量和回归测试范围。

这四项里,失败恢复和维护成本最容易被低估。一个流程在 demo 阶段跑得再顺,只要没有可恢复的状态,上线后每次超时都意味着用户重来一次。

落地时容易踩的坑

循环没有上限。检索为空就重试,是最常见的死循环来源。务必在状态里放计数器,并在路由条件里显式判断上限,而不是指望模型自己“想通”。

状态里塞了不可序列化的对象。一旦需要持久化或跨进程恢复,状态必须是可序列化的。把数据库连接、客户端实例放进状态,检查点就会失败。正确做法是节点内部按需创建,或通过依赖注入传入。

工具描述写得含糊。工具调用的成败很大程度取决于函数名和参数说明是否精确。参数缺省值、单位、取值范围都要写清楚,否则模型会猜。

过早追求多智能体。单流程能解决的问题,拆成多个智能体协作只会增加调试面。先在单图里把状态和分支跑顺,确有需要再拆子图。

忽略检索质量去调编排。如果草稿答非所问的根因是召回不准,改多少条边都没用。先看检索命中,再看流程。

怎么开始

拿你手上真实的一个小任务,按上面的方式写出状态字段、四个节点和两条流转条件,先用最熟悉的框架跑通,记录下每次改动需要碰几个文件。跑上两三轮之后,你对“控制流难还是检索难”会有自己的判断,那时再回头看选型表,答案通常已经很清楚。框架只是把已有逻辑翻译成代码,先想清楚逻辑,再挑翻译方式。

热门话题

52okp 是一名关注人工智能、开源软件与效率工具的技术内容创作者,长期实践 Stable Diffusion、ComfyUI、AI 智能体、MCP、Codex 和各类开源项目。通过实际安装、配置与测试,整理可复现的操作教程、问题排查方法和工具使用经验。

登录用户才能发表评论! 登录账户

取消回复

评论列表 (3条):

加载更多评论 Loading...

延伸阅读:

该用 LLM 还是 AI 智能体:按任务判断并搭最小流程

很多人第一次把大模型接进工作流时都会纠结同一个问题:这件事到底该写个普通提示词调用 LLM,还是干脆搭一个 AI 智能体...

52okp
2026-10-15

用 Eigent 搭建本地化文档处理智能体:从 Docker 部署到任务编排

如果你所在团队既要用 AI 智能体自动处理合同、报表、会议纪要这类敏感文档,又不放心把原文上传到第三方云端,那 Eige...

52okp
2026-10-16
    返回顶部