AI Agent 这个词这两年几乎被说烂了,但真正动手搭过的人都知道,从"能跑通一个 Demo"到"能稳定干活的生产级 Agent",中间隔着的坑比想象中多得多。我前后折腾过七八个不同形态的 Agent 项目,有跑在本地做知识检索的,有接进 CI/CD 流水线做自动化运维的,也有给业务团队做中台能力输出的。踩过的坑包括但不限于:工具调用参数格式对不上、多轮对话上下文爆炸、工作流编排死循环、模型网关路由报错、检索召回率上不去。这篇就把我从零构建高效 AI Agent 的完整思路拆开讲,从架构分层、Workflow 编排、LLM 选型与网关、RAG 知识库、到部署运维和常见故障排查,尽量把每个"为什么这么设计"讲透。适合已经了解 LLM 基本概念、想真正落地一个 Agent 的开发者,也适合正在做技术选型的团队参考。
1. 先想清楚 Agent 到底比一条 Prompt 强在哪
很多人搭 Agent 的第一步就错了——上来就选框架、拉代码、调 API,结果做出来的东西本质上就是"一个带了几次函数调用的 Prompt 模板",根本谈不上 Agent。所以在动手之前,得先把 Agent 的核心价值想明白。
1.1 Agent 的本质是"带反馈回路的决策循环"
一条普通的 Prompt 是单向的:你给输入,模型给输出,结束。而 Agent 的核心区别在于它有一个循环:观察当前状态 → 决定下一步动作 → 执行动作 → 观察结果 → 再决定。这个循环让它能处理那些"一步说不清楚、需要多步才能完成"的任务。
举个具体的例子。你让普通 Prompt"帮我查一下这个订单为什么延迟发货",它只能基于你给的信息瞎猜。但一个 Agent 可以:先调用订单查询工具拿到订单状态,发现卡在仓库环节,再调用库存系统查这个 SKU 的库存,发现缺货,再调用补货记录查最近入库时间,最后综合给出结论。这中间每一步的输入都依赖上一步的输出,这就是反馈回路的价值。
理解这一点之后,你在设计 Agent 时就会自然地问自己:我的任务需要几步?每一步的输入从哪来?失败了怎么回退?这三个问题答不上来,说明你还没到该写 Agent 的时候,先把业务流程理清楚。
1.2 什么任务适合 Agent,什么任务纯属杀鸡用牛刀
不是所有任务都值得上 Agent。我见过太多团队为了"用上 AI"硬把简单任务包装成 Agent,结果复杂度飙升、稳定性下降、成本翻倍。判断标准其实很简单:
| 任务特征 | 适合方案 | 原因 |
|---|---|---|
| 单轮问答、文本生成、分类 | 直接调 LLM | 无需多步决策,Agent 只会增加延迟和成本 |
| 固定流程、步骤明确 | Workflow 编排 | 流程确定就不需要模型来"决策",用代码编排更稳 |
| 步骤数不定、依赖中间结果 | Agent | 需要模型动态决定下一步 |
| 需要调用多个外部系统 | Agent + 工具层 | 工具调用是 Agent 的核心能力 |
| 高并发、低延迟要求 | 缓存 + 小模型 | Agent 的多轮循环天然慢,不适合硬扛延迟 |
我个人的经验是:能用 Workflow 解决的,绝不上 Agent。Workflow 是确定性的,可测试、可回放、可监控;Agent 是概率性的,调试成本高一个数量级。只有当任务的步骤数真的无法预先确定时,才值得引入 Agent 的决策循环。
1.3 高效的两个维度:快和省
标题里说"高效",这个词得拆开看。高效包含两层意思:响应快和成本省。这两者在 Agent 场景下经常是矛盾的——你想让 Agent 更聪明,就得多轮推理、多调工具,延迟和 token 消耗都上去了。
所以高效 Agent 的设计目标不是"最强",而是"够用且划算"。具体来说,我会关注这几个指标:单次任务的 LLM 调用轮数、平均 token 消耗、端到端 P95 延迟、工具调用成功率。这几个数字决定了你的 Agent 能不能真正上线跑起来,而不是停留在 Demo 阶段。
2. 分层架构:把 Agent 拆成能独立测试的几块
我踩过最大的一个坑,就是早期把所有逻辑塞在一个大函数里——Prompt 拼接、工具调用、结果解析、错误处理全混在一起。结果就是改一处崩三处,加个工具要动半个文件。后来痛定思痛,把 Agent 拆成了清晰的分层,维护成本立刻降下来。
2.1 五层结构:从入口到模型
我现在搭 Agent 基本遵循这个分层,你可以根据自己的场景增减:
- 接入层:负责接收请求、鉴权、限流、会话管理。这一层不碰任何 AI 逻辑,就是个标准的 Web 服务。
- 编排层:Agent 的大脑,决定"下一步做什么"。可以是代码写死的 Workflow,也可以是模型驱动的决策循环。
- 工具层:所有外部能力的封装,数据库查询、API 调用、文件操作都在这。每个工具是一个独立的、可测试的函数。
- 模型层:LLM 的调用封装,包括 Prompt 模板、模型路由、重试、降级。
- 记忆层:短期对话上下文和长期知识库,前者用会话存储,后者用向量库或知识图谱。
这么分的好处是:每一层都能单独测试和替换。比如你想换个模型,只动模型层;想加个工具,只动工具层;想改决策逻辑,只动编排层。层与层之间通过明确的接口通信,不会互相污染。
2.2 编排层:Workflow 和 Agent 不是二选一
很多人以为 Workflow 和 Agent 是对立的,其实它们是互补的。我的做法是外层用 Workflow 保证确定性,内层用 Agent 处理不确定性。
比如一个"处理用户工单"的流程:接收工单 → 分类 → 如果是简单问题直接模板回复 → 如果是复杂问题交给 Agent 处理 → 人工审核 → 归档。这个外层流程是固定的,用 Workflow 编排;而"复杂问题处理"这个节点内部,步骤数不确定,就交给 Agent 自由发挥。
这样设计的好处是,大部分请求走的是确定性路径,又快又稳;只有真正需要智能决策的部分才付出 Agent 的成本。实测下来,这种混合架构能把平均延迟降低 40% 以上,因为简单请求根本不会触发多轮推理。
2.3 工具层设计:让模型"看得懂"每个工具
工具层是 Agent 和外部世界交互的桥梁,设计得好不好直接决定 Agent 能不能用。我总结了几个硬性要求:
第一,每个工具的描述必须精确到模型能理解。不要写"查询数据",要写"根据订单号查询订单的当前状态,返回状态码和预计发货时间"。模型是靠描述来决定调不调、怎么调的,描述模糊它就会乱调。
第二,参数 schema 要严格。用 JSON Schema 定义每个参数的类型、是否必填、取值范围。我遇到过太多次模型传了个字符串但工具期望数字,或者少传了必填参数导致调用失败。严格 schema 能在调用前就拦住大部分错误。
第三,工具要幂等。Agent 可能因为重试或决策失误重复调用同一个工具,如果工具不幂等,就会产生重复下单、重复扣款这种灾难。所有写操作工具都要带幂等键。
第四,返回结果要精简。工具返回给模型的内容不是给人看的,是给模型看的。一个查询返回 500 行数据塞进上下文,既浪费 token 又干扰模型判断。我的做法是工具内部先做聚合和截断,只返回模型决策需要的关键字段。
3. Workflow 编排:把不确定性关进确定性的笼子
Workflow 编排是高效 Agent 的骨架。它决定了请求怎么流转、哪些步骤并行、失败了怎么处理。这块做得好,Agent 的稳定性和可观测性都有保障。
3.1 状态机还是 DAG,怎么选
Workflow 编排有两种主流模型:状态机和有向无环图(DAG)。
状态机适合有明确状态流转的场景,比如订单处理:待支付 → 已支付 → 发货中 → 已签收。每个状态有明确的进入条件和退出动作,逻辑清晰,容易做权限控制和审计。
DAG 适合步骤之间有复杂依赖的场景,比如数据处理流水线:A 和 B 可以并行,C 依赖 A 和 B 的结果,D 依赖 C。DAG 能自动识别哪些步骤可以并行,提升吞吐。
我的经验是:业务流程用状态机,数据处理用 DAG。两者也可以结合,外层状态机管业务流转,每个状态内部用 DAG 管具体计算。选错了模型,后面会越写越别扭。
3.2 并行、重试、超时:三个必须提前设计的机制
Workflow 里最容易忽略的就是异常处理,等到线上出问题才补,代价很大。这三个机制我建议在编排层一开始就设计好:
并行:能并行的步骤一定要并行。比如 Agent 需要同时查三个系统的数据,串行调用要 3 秒,并行只要 1 秒。但要注意并行步骤之间的依赖,别把有依赖的步骤并行化了。
重试:LLM 调用和外部 API 都可能偶发失败,重试是必须的。但重试要区分错误类型——网络超时可以重试,参数错误重试多少次都没用。我一般用指数退避,重试 2-3 次,超过就降级。
超时:每个步骤都要设超时,尤其是 LLM 调用。模型偶尔会卡住不返回,没有超时机制整个 Workflow 就挂在那了。超时时间根据步骤重要性设,核心步骤给长一点,辅助步骤短一点。
3.3 一个真实的编排踩坑:循环依赖导致死锁
说个我踩过的坑。早期做的一个 Agent,工具 A 的返回结果会触发工具 B,工具 B 的结果又可能触发工具 A,结果在某些输入下形成了循环,Agent 一直在两个工具之间来回调用,token 烧了一大堆,任务永远完不成。
后来我加了三道防线:最大轮数限制(比如最多 10 轮)、重复调用检测(同样的工具+参数连续调用两次就中断)、全局超时(整个任务超过 60 秒强制结束)。这三道防线加上之后,再也没出现过死循环。
提示:Agent 的循环一定要有硬性上限,不要指望模型自己"意识到"该停了。模型没有全局视野,它只看得到当前上下文,很容易陷入局部循环。
4. LLM 选型与网关:别把鸡蛋放一个篮子里
模型是 Agent 的心脏,但选型不是"哪个最强用哪个"这么简单。延迟、成本、稳定性、合规性都要考虑,而且生产环境几乎不可能只依赖一个模型。
4.1 模型分层:大模型决策,小模型干活
我的做法是模型分层:复杂决策用大模型,简单任务用小模型。
具体来说,Agent 的"思考"环节——决定下一步做什么、怎么拆解任务——用能力强的大模型;而"执行"环节——比如把工具返回的结构化数据转成自然语言、做简单的意图分类——用小模型就够了。这样能在保证效果的前提下大幅降低成本。
实测数据:一个中等复杂度的 Agent 任务,如果全程用大模型,单次成本假设是 1;分层之后,只有约 30% 的调用走大模型,其余走小模型,综合成本能降到 0.4 左右,而任务成功率几乎没变化。
4.2 模型网关:统一入口,屏蔽差异
生产环境里你可能会用到多个模型——不同厂商的、不同版本的、本地部署的。如果每个调用点都直接写死某个模型的 API,换模型时就是灾难。所以模型网关是必须的。
网关的核心职责有三个:
- 统一接口:所有模型调用走同一套 API,上层代码不关心底层是哪个模型。
- 路由策略:根据任务类型、成本预算、当前负载决定用哪个模型。
- 故障转移:某个模型不可用时自动切到备用模型。
我遇到过好几次模型服务临时不可用的情况,报错信息类似"无法连接到模型服务""provider rejected the request schema"。有网关的话,这些故障对上层是透明的,自动切到备用模型,用户几乎无感知。没有网关的话,就是线上事故。
4.3 本地部署还是调 API:算一笔账
这是绕不开的问题。我的判断标准是看数据敏感度和调用量。
数据敏感的场景,比如涉及内部知识库、客户隐私的,优先考虑本地部署,数据不出内网。调用量大的场景,本地部署的边际成本低,长期看更划算。但本地部署有门槛:需要 GPU 资源、需要运维、模型更新要自己跟。
调用量小、数据不敏感的,直接调 API 最省事,按量付费,不用管运维。我一般建议团队先用 API 快速验证,等业务跑通了、调用量上来了,再评估要不要转本地。
| 维度 | 本地部署 | 调 API |
|---|---|---|
| 数据安全 | 高,数据不出内网 | 依赖服务商合规 |
| 初期成本 | 高,需 GPU 和运维 | 低,按量付费 |
| 边际成本 | 低 | 随调用量线性增长 |
| 模型更新 | 自己维护 | 服务商负责 |
| 延迟 | 可控,取决于硬件 | 受网络和服务商影响 |
| 适合场景 | 高敏感、高调用量 | 快速验证、低调用量 |
5. RAG 与知识库:让 Agent 有据可依
Agent 光有推理能力不够,还得有知识。RAG(检索增强生成)是给 Agent 补充外部知识的主流方案,但做好 RAG 的难度被严重低估了。
5.1 朴素 RAG 为什么经常不好用
最朴素的 RAG 就是"文档切块 → 向量化 → 检索 top-k → 塞进 Prompt"。听起来简单,实际用起来召回率经常惨不忍睹。原因有几个:
切块策略太粗暴。按固定字数切,经常把一句话、一个表格、一段逻辑切得七零八落,检索出来的片段语义不完整。我的做法是按语义边界切——段落、章节、表格作为切块单位,再根据长度做二次合并。
只做向量检索不够。向量检索擅长语义相似,但对精确匹配(比如产品型号、专有名词)不敏感。所以我现在基本都用混合检索:向量检索 + 关键词检索,两路结果融合排序。
缺少重排序。检索出来的 top-k 里,真正相关的可能排在第 8 位。加一个重排序模型(rerank),把最相关的提到前面,效果提升很明显。
5.2 从 RAG 到 GraphRAG:什么时候需要知识图谱
普通 RAG 处理的是"片段级"的知识,适合"这个产品的参数是什么"这类问题。但有些问题需要跨多个文档、多个实体做推理,比如"这个供应商的哪些产品受这次原材料涨价影响",普通 RAG 就力不从心了。
这时候可以考虑GraphRAG——把知识组织成实体和关系的图谱,检索时沿着关系做多跳推理。代价是构建成本高,需要做实体抽取、关系抽取、图谱维护。我的建议是:先用普通 RAG,遇到跨文档推理的瓶颈再考虑 GraphRAG,不要一上来就上图谱,投入产出比不划算。
5.3 知识库的更新与版本管理
知识库不是建一次就完事的,业务在变,知识就得更新。这块我踩过的坑是:没有版本管理,更新后效果变差无法回滚。
现在的做法是:每次知识库更新都打版本号,检索时记录用的是哪个版本,效果监控按版本对比。如果新版本效果下降,能快速回滚到旧版本。另外,更新要做增量,不要全量重建——全量重建一次可能几小时,期间服务不可用。
6. 部署与 DevOps:让 Agent 真正跑在生产环境
Demo 跑通只是开始,部署到生产环境才是真正的考验。Agent 的部署和传统服务有不少差异,得专门设计。
6.1 容器化与资源隔离
Agent 服务我基本都用容器部署,好处是环境一致、扩缩容方便。但要注意几点:
模型调用是外部依赖,容器本身不需要 GPU(除非你本地部署模型)。所以 Agent 服务的容器可以很轻量,主要吃 CPU 和内存。
工具调用可能很重。如果某个工具要跑数据分析、要调大文件,得给它单独的资源配额,别让它拖垮整个服务。
会话状态要外置。Agent 是有状态的(对话上下文),容器本身是无状态的,所以会话状态必须存到外部存储(Redis 之类),这样容器才能随意扩缩容。
6.2 可观测性:Agent 的日志和传统服务不一样
传统服务的日志是"请求进、响应出",Agent 的日志要复杂得多:每一轮 LLM 调用、每一次工具调用、每一个决策点都要记录。不然出了问题根本没法排查。
我现在的做法是给每个任务分配一个 trace ID,所有相关的 LLM 调用、工具调用、中间状态都挂在这个 trace 下。排查问题时,拿 trace ID 一查,整个决策链路清清楚楚。这块可以参考分布式追踪的思路,把 Agent 的一次任务当成一个 trace。
关键要记录的字段:每轮调用的输入输出、token 消耗、耗时、工具调用参数和结果、决策理由(如果模型输出了的话)。这些数据不仅能排查问题,还能用来分析成本、优化 Prompt。
6.3 灰度发布与效果监控
Agent 的效果是概率性的,改个 Prompt 可能让一部分场景变好、另一部分变差。所以不能全量发布,必须灰度。
我的做法是:新版本先放 5% 流量,对比核心指标(任务成功率、平均轮数、用户满意度)和旧版本。指标不降才逐步放量。如果指标下降,立即回滚。
效果监控要自动化,不能靠人工看。我会设几个告警阈值:任务成功率低于基线、平均轮数异常升高、工具调用失败率上升、P95 延迟超标。任何一个触发就告警。
7. 常见故障排查:那些让我熬夜的报错
最后分享几个我实际遇到过的故障和排查思路,都是血泪教训。
7.1 模型服务连接失败:先分清是网络还是配置
报错"无法连接到模型服务"是最常见的。排查顺序是:先确认网络通不通(能不能 ping 通、能不能建立连接),再确认配置对不对(API 地址、密钥、模型名),最后确认服务商侧是不是有故障。
我遇到过一种情况:配置全对,网络也通,但就是连不上。最后发现是请求体格式不对,服务商直接拒了。所以看到连接类报错,别只盯着网络,请求格式也要检查。
7.2 工具调用参数错误:schema 是最后一道防线
模型传错参数是高频问题。我的经验是:不要指望模型每次都传对,要用 schema 严格校验。校验失败时,把错误信息返回给模型,让它重新生成参数。通常重试一两次就能对。
另外,参数描述要写清楚。我见过模型把"日期"参数传成"今天"这种自然语言,就是因为描述里没说明要传 ISO 格式。描述里给个例子,能大幅降低出错率。
7.3 上下文爆炸:token 超限的几种解法
多轮对话跑久了,上下文越来越长,最后超过模型的最大 token 限制。解法有几种:
- 滑动窗口:只保留最近 N 轮对话,老的丢掉。简单但会丢失早期信息。
- 摘要压缩:把早期对话用模型总结成一段摘要,保留摘要丢掉原文。信息保留得更好,但多一次模型调用。
- 关键信息提取:把对话中的关键实体、决策提取成结构化数据,只保留这些。适合任务型对话。
我一般用摘要压缩 + 关键信息提取的组合,实测能在保留 90% 有效信息的前提下把上下文压缩到 30%。
7.4 检索召回率低:从切块和检索策略两头查
RAG 效果差,先查两头:切块是不是把语义切碎了,检索策略是不是太单一。我一般的排查顺序是:先看检索出来的 top-k 内容,人工判断相关性;如果切块有问题就调切块策略,如果切块没问题就加混合检索和重排序。
有个容易被忽略的点:查询改写。用户的原始问题往往不适合直接检索,比如"这个咋弄"这种口语化问题。先用模型把问题改写成适合检索的形式,召回率能提升不少。
8. 我踩过的几个非技术坑
技术之外,还有几个坑值得说说。
过度追求自动化。早期我总想让 Agent 全自动完成所有事,结果发现有些环节人工介入反而更快更准。现在的做法是:Agent 处理 80% 的常规情况,剩下 20% 的边界情况转人工,整体效率反而更高。
忽视 Prompt 的版本管理。Prompt 也是代码,改了要记录、要测试、要能回滚。我早期 Prompt 改了就改,出了问题都不知道是哪次改坏的。现在所有 Prompt 都进版本控制,每次改动都有记录。
低估了冷启动。Agent 上线初期效果往往不如预期,因为知识库不全、Prompt 没调优、工具没打磨。这时候要有耐心,持续迭代,别指望一上线就完美。
成本失控。Agent 的 token 消耗很容易失控,尤其是循环调用的时候。一定要设预算上限,单任务、单用户、单天的 token 消耗都要有上限,超了就降级或拒绝。
搭一个能用的 Agent 不难,搭一个高效、稳定、可维护的 Agent 才是真功夫。核心就一句话:把不确定性关进确定性的笼子里——能用代码确定的就别交给模型,必须交给模型的部分就加好边界、监控和降级。这套思路我在多个项目里验证过,从知识检索到流程自动化都能套用。后续如果要做多 Agent 协作,这套分层和编排的思路同样适用,只是编排层会更复杂一些,需要考虑 Agent 之间的通信和任务分配。