1. 先搞清楚Agent到底是什么,以及五个难度级别凭什么这么排
大模型Agent这个话题,最近两年已经被聊烂了。但真去落地做过的开发者应该都明白,网上那些"10分钟做一个Agent"的教程,和你实际生产环境里跑得稳、跑得住、能交付的Agent,完全是两码事。
我见过不少人,第一天兴冲冲接了一个大模型API,写了两段提示词,跑通了一次问答,就觉得自己已经"会做Agent"了,结果一上真实场景,各种问题全炸出来:格式不稳定、上下文越跑越乱、工具调用循环死锁、多任务协作互相踩脚,最后整个系统变成一坨没法维护的黑盒。
说句实在话,Agent开发真正难的从来不是"调通一次",而是"稳定地跑持续的正确的事"。它不是一个单点的算法问题,而是Prompt、结构化输出、工具调用、状态管理、上下文管理、任务编排、自我修正这一串问题叠在一起的系统工程。
这篇文章我想用我自己实战中反复打磨出来的一个框架,把大模型Agent设计的复杂度分成了五个难度级别:L1提示词封装、L2结构化输出、L3多步推理与工具调用、L4多Agent协作、L5自反思与持续进化。
这么分不是为了搞等级鄙视链,而是让你能清楚地判断:我现在做的这个系统,到底处在哪个级别?我接下来的瓶颈在哪?我应该在哪里投入精力?
而且,每个级别都有它特有的坑,这些坑你光看文档是根本看不见的,非踩过一遍才知道疼。这篇文章主要就是来聊这些的,每个级别我会把设计思路、踩坑实录、可落地的方案全部拆开讲。
如果你是刚开始接触大模型Agent的开发者,建议你从L1读到L5,知道前方有什么在等着你;如果你已经在某个级别上卡了一段时间,可以直接跳到对应章节找答案。
2. L1级别:提示词封装式Agent,入门者的第一个陷阱
2.1 这个级别在做什么
L1级别的Agent,本质上就是"带着提示词的大模型API调用"。
你在系统里写一段系统提示词,把大模型设定成一个客服、一个助手、一个文档分析员,然后把用户的问题拼进去,调一次接口,把返回结果直接展示出来。很多教程里讲到的"角色扮演""Prompt模版"基本都是这一类。
它的核心价值在于:让大模型在一个限定范围内输出,比直接用通用对话效果要稳定得多。比如你做一个人事政策问答Agent,系统提示词里写清楚"你是一名HR助理,只能回答与考勤、薪酬、假期相关的问题,其他问题一律拒绝",大模型就会在这个边界内输出,不会跑偏去聊天气或者写诗。
用起来好像很省事,但这里面的隐患,要到规模变大、业务逻辑变复杂之后才暴露出来。
2.2 踩坑总结:你以为的"聪明"其实全是水分
第一个坑,叫"提示词越写越长,行为越来越怪"。
很多开发者做L1 Agent,发现输出不理想就开始往提示词里加规则。今天加一条"如果用户问这个,你必须这样说",明天加一条"你必须先分析再回答",后天又加一条"禁止使用'很抱歉'这个说法"。提示词从100字堆到1000字,结果模型开始频繁地自相矛盾,有时候遵守新的指令就忘了旧的指令,有时候把所有指令都当成废话。
我自己有一次做模拟项目X的时候,提示词里写了二十多条规则,结果模型在这些规则之间不断打架,回复质量反而比只有三条核心规则的时候差了一大截。
第二个坑,是"上下文污染"。
L1级别的Agent如果把聊天历史全部塞给模型,不做任何裁剪、摘要、筛选,对话一旦变长,模型就会被早期的信息带偏,甚至根本"忘记"用户在对话开头提的核心需求。
第三个坑更隐蔽,叫"你以为模型在按你的逻辑走,其实它只是装得像"。
L1级别的Agent本质上没有真正的"思考"能力,它只是根据提示词和概率在生成内容。你问它"你确定吗",它会说"我确定";你问它"要不要再检查一遍",它会说"好的我检查了一遍,没有问题"。它完全可以一本正经地编造一个它根本没有做过的检查过程。
第三个坑的本质就是幻觉问题,这在L1级别是没有手段根治的,AI没有推理链条,它只是完成了输入到输出的映射。
2.3 L1级别完整方案参考
如果你确实要做L1级别的Agent,我的建议是做到这三点:
第一,提示词写"角色+边界+输出格式+兜底话术",四要素就够了,不要堆砌几十条行为规则。核心内容按照这个思路:
你是一名企业内部IT支持助手。 你只能回答与办公电脑、网络、软件授权相关的问题。 如果你无法确认答案,明确告诉用户"这个问题我需要帮你转人工处理"。 回答时使用简洁的步骤式说明。第二,给聊天历史设定一个滑动窗口。只保留最近几轮对话,更早的内容让模型做一段摘要后再保留摘要。这个方案虽然是L2级别的思路,但从L1阶段就值得开始做。
第三,在代码里加入基础的关键词过滤和重复提问检测,不要直接把模型的输出当成最终答案。比如用户连续问同一个问题两次,模型给了两个不一样的答案,这就是个警告信号。
3. L2级别:结构化输出与格式控制,真正的分水岭
3.1 为什么非要把输出绑进JSON
L1级别最大的问题是输出不可控:AI说的是自然语言,但你的下游业务代码需要的是字段、结构化数据、可执行参数。
你让模型"告诉我今天的天气",你得拿正则表达式去抠它回答里的温度、风力、湿度,一不小心就抠错。所以L2级别核心解决的事就一件:让模型的输出变成严格的、符合预设结构的数据。
用技术术语说叫"结构化输出",大白话讲就是——让模型输出JSON,并且保证这个JSON里有哪些字段、字段是什么类型、哪些必填哪些可选,全都定义好。
为什么这件事是分水岭?因为它意味着大模型从"聊天工具"变成了"能接入业务逻辑的组件"。你的代码可以吃了模型输出的JSON然后做下一步工作,而不是围着字符串解析打转。
3.2 解析与校验的真相
L2级别避不开的坑,就是"模型输出看似有JSON的形状,实则全是雷"。
我实测过的典型问题至少有以下几类:
- 模型在JSON外面包了
json代码块标记,直接json.loads直接报错 - JSON里字符串值没有正确转义,出现了换行符、引号、反斜杠,导致解析失败
- 字段缺失:模型觉得"这个字段不重要",直接不输出
- 字段类型不对:你定义了
temperature是number,模型输出了字符串"24.5度" - 多了一个你schema里根本没定义的字段,下游代码用反射校验的时候直接炸
所以L2级别做结构化输出,绝对不能只靠提示词里写一句"请输出JSON格式",必须有三重保障:提示词写清楚schema、API参数层面启用JSON输出约束(如果模型支持)、代码侧做严格校验和重试机制。
我在某个图像处理Demo里就用过一个很典型的例子,要求模型输出:
{ "scene_type": "indoor", "objects": [ {"name": "chair", "confidence": 0.95} ], "summary": "室内场景,包含一把椅子" }实际收到的输出,经常是scene_type字段给了"这是一个室内场景"这种带有语气词的描述,或者objects数组里混入了模型自己编造的不存在物体。没有一层严格校验逻辑,这些脏数据就会一路流到下游业务里,排查起来比前端报错痛苦一百倍。
3.3 L2级别完整方案参考
第一,定义好你的JSON Schema文件,同时让它作为提示词的一部分发给模型。能明确标类型的地方就明确标,"description"里甚至可以写枚举值。
第二,解析时做三层防护:先剥离可能的Markdown代码块标记,再做JSON解析,最后做类型与必填字段校验。校验失败时,不要傻等重试,要带着上一次的"报错信息"回传给模型让它自行修正,这一招在实践中能把成功率从70%拉到95%以上。
第三,设置最大重试次数和兜底输出。模型连续几次都输出垃圾时,直接返回一个预设的"我暂时无法处理,请联系人工"的JSON,而不是把异常抛给用户。
我的个人建议是千万不要跳过L2直接去搞复杂功能。凡是你在生产环境里跑过的Agent,结构化输出这一关做不扎实,后面每一层都会因为底层数据不干净而连环爆炸。
4. L3级别:多步推理与工具调用,Agent开始长"手脚"
4.1 ReAct循环的本质
L3级别的Agent,才开始有"手脚"——它能调用你自己的函数、API、数据库查询,而不是光靠嘴回答。
核心框架就是业界常说的ReAct模式。简单解释:模型在思考的时候,不是直接给出最终答案,而是循环执行"思考→行动→观察→再思考"这个链路。比如用户问"帮我查一下上个季度的销售额",Agent先"思考"需要查询销售数据,于是"行动"调用查询接口,拿到结果后"观察"到数据,再生成回答。
架构上看,就是把L2的可信输出,拼上一个"工具路由层"。系统要预先注册一批工具,每个工具都有名称、描述、参数schema。模型通过它的推理能力,自主决定用哪个工具、传什么参数。这也是很多AI Agent框架(不管是开源的还是自研的)的核心玩法。
L3级别最有价值的地方,是它把大模型从"只说不做"变成了"边说边做",应用范围一下子宽了。实际操作下来,这个级别的难度也陡然上升,因为模型每一次工具调用都是一次"试错",系统要处理好这些试错,而不是放任它。
4.2 上下文爆炸与循环失控
L3级别在我眼里,是五个级别里坑最多的一个。
第一个坑是"上下文爆炸"。ReAct每一步的思考、行动、观察结果都要塞进上下文里。一个任务走3步循环还挺清爽,走10步、20步,上下文就几万字了。token费用蹭蹭涨,人还能接受,但最要命的是模型在超长上下文里很容易"忘记"最开始的任务目标,然后自己在后面自说自话。
第二个坑是循环失控。模型调用一个工具,拿到结果发现不满足预期,于是再调用、再失败、再调用……就这么原地打转。我在某跨平台系统上排查过一个故障,Agent在循环里重复调了同一个查询接口12次,把后端接口QPS都拖高了,才被监控告警发现。根本原因是循环终止条件写得太宽松,模型永远有机会"再试一次"。
第三个坑是工具调用参数错误。模型照着schema填参数,看起来格式没错,但语义错了。比如查天气的时候把城市填成"北京",但你的系统里定义的是城市代码101010100,模型填了个中文名,你的接口直接报错。这种问题靠JSON校验发现不了,必须靠工具本身做入参语义校验。
4.3 L3级别完整方案参考
做一个L3级别的Agent,我认为最少要落地这几件事:
第一步,设计工具注册表。每个工具必须包含name、description、input_schema、handler、timeout字段。其中description是最容易忽略但其实最重要的——模型读你的工具描述,跟人读说明书一样,描述写得含糊,模型就不知道该不该选它。
第二步,设置全局最大循环次数。这个参数是保命用的,我一般设置为5到8次。一个任务走超过8步还没出结果,大概率是模型陷入了无效循环,直接终止并触发降级策略。
第三步,上下文管理器必须上线。可以每次循环结束后,把已经完成的子步骤做一次摘要,而不是把所有中间过程全部原样存着。相当于给Agent配了一个"笔记员",专门负责整理思路。
第四步,给关键工具加"前置校验器"。在工具handler里先做入参语义校验,不合法直接返回一个明确的错误信息,让模型看到错误后调整自己的参数再试一次,而不是傻傻地用错误参数反复调用同一个工具。
核心代码逻辑我习惯这么写:
async function runAgent(task, tools, maxSteps = 6) { let context = [{ role: "user", content: task }]; for (let step = 0; step < maxSteps; step++) { const response = await llm.complete({ tools, context }); if (response.finalAnswer) return response.finalAnswer; const toolCall = response.toolCall; const result = await executeTool(toolCall); context.push({ role: "tool", content: JSON.stringify(result) }); } throw new AgentLoopTimeoutError(); }这个骨架看着简单,生产环境里要在里面塞进去的东西,比你想象的多得多。
5. L4级别:多Agent协作与编排,从跑通到跑得像样
5.1 为什么需要多个Agent
到L4级别,就不只是单个Agent在干活了,而是多个Agent分工协作,像一个小团队一起完成复杂任务。
举个例子,做一个"自动项目周报生成系统"。你当然可以让一个Agent一手抓到底——让它去拉代码提交记录、汇总工作内容、检查数据异常、最后写周报——但在实际场景里,一个Agent自己又要做检索、又要做判断、又要写文档,效果通常不理想,因为每一步它是用同一套思路在做,出了问题非常难定位。
更合理的做法是拆开:一个Agent负责扫描代码仓库,一个Agent负责分析数据指标,一个Agent负责审核内容质量,最后一个Agent负责汇总写作。每个Agent职责边界清晰,各自调各自的工具,输出通过消息协议互相传递,最后由主Agent统一收口。
这种架构最大的好处是:可调试、可替换、可并行。某一个Agent行为异常,直接定位到那个模块;某一步逻辑要换实现方案,只改对应的Agent就行,这比动一个巨型Agent安全得多。
5.2 协作中的三个坑
多Agent协作是这个级别最有技术含量的部分,三个坑我必须重点讲。
第一个坑是"死锁式的相互依赖"。Agent A要等Agent B的结果才能继续,而Agent B的逻辑又要求Agent A先完成某一步,两边互相等,系统直接卡死。这不是并发层面的死锁,而是流程设计上的依赖环路。解决办法是在编排层做依赖图检查,或者干脆给每个Agent设定超时和降级策略——等不到就自动跳过,用默认值继续。
第二个坑是"消息协议混乱"。多个Agent之间传递数据,各方对数据格式的理解不一致。Agent A输出的是Markdown文本,Agent B却期望结构化JSON,于是只能靠关键词硬抠,抠不出来就出错。我见过的多Agent系统爆炸,至少一半是"数据传递格式不统一"造成的。
第三个坑是"角色漂移"。职责定得好好的Agent,在协作过程中逐渐被人格化干扰,比如负责数据检索的Agent也开始参与文案写作。这不是它变聪明了,而是它接收的上下文里混入了太多上游传递的无关信息,模型权重被带偏了。真正稳定的多Agent系统中,每个Agent的上下文范围要严格"隔离",只放它职责范围内的信息。
5.3 L4级别完整方案参考
我会把多Agent做成一套"编排器+执行器+消息总线"的结构。
编排器负责拆解任务、生成每个子任务的动作清单、监控所有Agent的执行状态。执行器也就是具体的Agent,只做自己那一块工作。消息总线统一管理Agent之间的信息传递,所有消息都有type、from、to、payload字段,便于追踪。
一个简单的消息协议长这样:
{ "type": "task_result", "from": "data_analyzer", "to": "report_writer", "payload": { "sales_total": 125000, "trend": "up", "period": "2024-Q3" } }每个Agent只负责填充自己的payload,不越界。编排器也不去理解每个Payload的业务含义,它只管消息路由。这样整个系统的复杂度就被拆开了,出了问题也能快速定位是哪个Agent产生了脏数据。
关于Agent数量的控制,我的经验是:能用2个Agent解决的问题绝不用3个,不到万不得已不搞超过5个Agent的协作链路。多Agent系统每多一个参与者,消息基数就会指数级增长,最后有一大半系统开销都在做无效的消息转发。
6. L5级别:自反思与持续进化,可遇不可求的终极玩法
6.1 从"做对"到"越做越好"
前面四个级别解决的都是"把事做对",L5级别着眼于"把事越做越好"。这个级别的Agent要具备两个核心能力:自我反思能力和经验积累能力。
所谓自我反思,不是让模型在回答前简单说一句"让我想想",而是在每一轮任务执行结束后,额外启动一次"复盘"。模型回顾自己这次任务的全过程,分析哪些环节处理得不好,哪些决策是错的,哪些地方值得改进,并且把反思的结果沉淀下来,用于指导下一次执行。
坦白说,市面上大多数声称自反思的Agent,做的都是表面功夫。真正深层的反思,是把反思结果变成可执行的修正行为。比如模型发现自己上一次在查询数据时喜欢多传无用参数,那它下一步的行动策略里就加上一条"不带多余参数",这才是有效的反思。
我自己很喜欢的做法是:给Agent配一个"反思提示词",在每轮完成文章输出后,自动生成一道复盘问题列表,让模型对照着逐一自查,并把自查结果存回记忆库。相当于每次工作完做一次复盘,攒下来的经验就是它自己的"私有文档"。
6.2 让Agent学会积累经验
L5级别也很考验记忆系统的设计。
我在某个长期维护的系统里,是这样设计记忆库的:核心启动区、不常用的旧记忆放归档区、失败案例单独放一个区域。每个区域使用不同的召回策略,比如用户开始新任务时,先把"通用的工作方法论"和"过去相似的案例摘要"注入上下文,而不是把整堆历史记录全倒给模型。
记忆要"精炼",不要"照搬"。模型一次会话的原始日志不适合直接当记忆存下来,它里面夹杂了大量中间步骤,直接存只会污染后续上下文。一定要先做摘要化提取,把"任务目标→采取的动作→取得的成果→踩过的坑"提炼成几条简短记录再入库。
L5级别的另一个难点是评估。如何判断一个Agent"进化得好不好"?在L4级别你可能只需要看任务完成率,但到了L5级别,你还要跟踪每次迭代之后的表现曲线。如果不建立一套指标(比如一次通过率、返工次数、平均执行时长),你就无法判断你做的反思和记忆机制到底是在帮助它,还是在干扰它。
6.3 L5级别完整方案参考
如果要从零搭一个带自反思能力的Agent,我建议的最小闭环是四条链路:
先把"执行链路"跑起来,再在上面加"反思链路"。反思链路不在主流程里,而是在主流程结束后异步触发。启动反思时,把本次任务的执行记录摘要发给模型,让它输出"存在的问题+改进建议"。
然后把"改进建议"转成"策略标签",存进记忆库。下次执行同类任务时,系统在上下文里注入与任务类型匹配的策略标签,其他无关的就不注入,保持上下文清爽。
最后加上"人工监控反馈"闭环。捡一个简单的办法,在反思产出之后,允许业务方对反思质量进行投票推荐。被投了"有质量"的记录优先召回,投了"没价值"的逐渐降权。这相当于是让人类对Agent的记忆做质量把关,比让模型自己评价自己可靠多了。
7. 五个级别的实战对比与避坑速查表
我把五个级别放在一起做个快速对照表,这个表我在团队内部做分享时用过很多次,挺实用:
| 级别 | 核心能力 | 主要挑战 | 失败的最典型迹象 | 最小可用方案 |
|---|---|---|---|---|
| L1 提示词封装 | 限定范围问答 | 上下文污染、规则堆叠 | 回答开始自相矛盾 | 角色+边界+输出格式提示词 |
| L2 结构化输出 | 输出可用JSON数据 | 格式不稳定、脏数据 | 下游解析频繁报错 | Schema+三层解析校验+重试 |
| L3 工具调用 | 多步推理与工具调用 | 循环失控、上下文膨胀 | Agent原地反复调用同一工具 | 循环上限+上下文压缩+工具校验 |
| L4 多Agent协作 | 多Agent分工协作 | 消息混乱、角色漂移 | 多个Agent互相等待或抢数据 | 编排器+消息总线+依赖图 |
| L5 自反思进化 | 复盘与经验沉淀 | 评估不清晰、记忆污染 | 反思后表现反而下降 | 反思链路+记忆库+人工反馈 |
再单独整理一份避坑速查表,都是我自己踩过之后觉得最值得反复提醒的:
| 症状 | 常见原因 | 解决方案 |
|---|---|---|
| 模型答非所问 | 提示词规则过载 | 精简到四要素,删除自相矛盾规则 |
| JSON解析失败 | 模型输出带Markdown标记或字符串未转义 | 先剥离标记,再解析,再加校验重试 |
| Agent反复调用同一工具 | 循环终止条件失效 | 加最大步数上限并设置退化策略 |
| Confirmation失败但无报错 | 工具错误信息模糊,模型看不懂 | 错误信息要写明"期望什么,实际得到什么" |
| 多Agent互相等待 | 流程依赖成环 | 编排层做依赖检查,加超时跳过 |
| 反思之后表现变差 | 记忆库被无效信息污染 | 建立摘要化记忆+人工反馈降权机制 |
这张表每个场景我都实际见过,最后再啰嗦一句:你在照着表排查问题的时候,尽量从自己系统的日志和调用链里找到对应的证据,而不是凭感觉猜。比如怀疑上下文爆炸,就去数每次调用请求的token数,用数据确认之后再做优化,改哪儿心里才有底。
8. 写在最后:从L1到L5,真正值钱的是避坑经验
做Agent开发这两年,我自己最大的体会是:这行不缺"跑通"的教程,缺的是"从坑里爬出来"的记录。果断入坑的需求千篇一律,坑底的泥各有各的黏法。
当你把L1到L5这几个难度级别从头梳理一遍,你会发现大多数项目的真正瓶颈,根本不是模型不够聪明,而是工程化能力跟不上。上下文管理、结构约束、状态控制、流程编排、经验沉淀,每个环节都是锻造轮子的一部分,你跳过的每一个基础细节,都会在后续的某个版本迭代里等你回来补课。
拿我自己来说,刚上手的时候我也跳过L2直接去搞L3的工具调用,结果被脏数据整得痛不欲生。后来回到L2老老实实把Schema和校验机制做好,L3的循环才慢慢稳定下来。这种"基础不牢,地动山摇"的道理,在Agent开发里体现得淋漓尽致。
所以,如果你手上的Agent项目正在某个级别反复翻车,不要急着上更高级的玩法,先回到当前级别把根基打扎实,再用更高一级的设计思路来做增量。这种"层级式前进"的策略,看起来慢,实际上是走完全程最短的路径。
希望这篇破万字的长文能让你少走一些我走过的弯路。如果看完对某一级别的落地细节还有疑问,欢迎在评论区带上你的场景和遇到的具体报错来聊,我看到都会回复。