首页/新闻资讯/正文详情

从零手搓生产级Agent:RAG、记忆管理与工具编排实战

发布时间:2026/9/26 19:37:01 来源:云帆数科 栏目:资讯中心
从零手搓生产级Agent:RAG、记忆管理与工具编排实战
Agent 这个词在过去一年里被用得太泛了。打开任何一个技术社区满屏都是三行代码搭建你的第一个 Agent但真到了要把一个 Agent 从 demo 推进到能扛住真实流量、能稳定跑在业务链路里的时候绝大多数人会发现手里那套东西根本不够用。我自己从最早用 LangChain 拼一个能查天气的玩具到后来做带 RAG 检索、带记忆、带工具编排的工程化 Agent中间踩的坑足够写一本小册子。这篇东西不打算再给你灌一遍什么是 Agent的概念而是想把我从零手搓一个 Agent 的完整路径摊开讲——从最小可运行内核到 RAG 知识库接入再到记忆管理、工具编排、错误处理这些真正决定能不能上生产的部分。适合已经写过一点 LLM 调用、想把 Agent 做扎实的开发者也适合那些被各种框架绕晕、想搞清楚底层到底在发生什么的人。1. 先把 Agent 的内核剥到只剩一个循环1.1 为什么我不建议一上来就用重型框架很多人学 Agent 的第一反应是打开 LangChain 或者某个 Agent 框架的文档照着 example 抄一遍。抄完能跑但一旦出问题就完全不知道从哪下手。我早期也是这样一个 chain 套一个 chain报错信息翻三页都找不到根因。后来我强迫自己把框架全删掉只用最原始的 LLM API 手写一遍才发现 Agent 的本质简单到有点反直觉它就是一个思考—行动—观察的循环英文里常说的 ReAct 模式Reasoning 加 Acting。这个循环用伪代码表达大概是这样while not done: thought llm.think(context, tools) if thought.is_final_answer: return thought.answer action thought.action observation execute(action) context.append(observation)就这么点东西。所有框架做的事情无非是在这个循环外面包了一层工具注册、一层记忆管理、一层错误重试。你把这个循环亲手写一遍后面用任何框架都能一眼看穿它在干什么。我个人的经验是手搓一遍内核花不了两天但省下来的调试时间是以周计的。1.2 最小可运行内核需要哪几个零件一个能跑起来的最小 Agent我总结下来需要四个零件LLM 调用层、工具注册表、上下文管理器、循环控制器。这四个缺一不可但每个都可以做到极简。LLM 调用层负责和模型对话这里要注意的是Agent 场景下你几乎一定要用支持 function calling 或者 tool use 的模型接口因为纯文本解析工具调用太脆弱了。工具注册表就是一个字典把工具名映射到具体的函数和它的参数 schema。上下文管理器管的是消息历史什么时候追加、什么时候截断、什么时候压缩。循环控制器就是上面那个 while 循环加上最大轮次限制和终止条件判断。我第一版内核大概两百行代码跑起来能查天气、能算数、能根据结果继续追问。虽然简陋但每一个环节我都清楚它在干嘛。这个清楚在后期排查问题时价值巨大。1.3 工具调用的 schema 设计是最容易翻车的地方工具注册看着简单但 schema 设计是新手翻车重灾区。我见过太多人把工具参数写成一大坨自由文本然后指望模型自己解析结果模型十次有三次传错格式。正确做法是用严格的 JSON Schema 描述每个参数的类型、是否必填、取值范围。举个例子一个查询订单的工具参数不要写成传入订单信息而要写成{ name: query_order, description: 根据订单号查询订单状态仅在用户提供了明确订单号时调用, parameters: { type: object, properties: { order_id: { type: string, description: 订单号通常是 16 位数字 } }, required: [order_id] } }注意 description 里那句仅在用户提供了明确订单号时调用这种约束性描述能显著降低模型乱调工具的概率。我实测下来把工具描述写清楚比换一个更强的模型带来的提升还明显。这是很多人忽略的细节模型选得好不如 prompt 和 schema 写得准。2. 让 Agent 真正有用的是 RAG而不是模型本身2.1 为什么裸 Agent 在真实业务里几乎没法用一个只会调用几个工具的 Agent在 demo 里很惊艳但放到真实业务里立刻露怯。原因很简单模型不知道你的业务知识。你问它公司报销流程它要么编一个要么说不知道。这时候就需要 RAG也就是检索增强生成把外部知识库接进来。RAG 的核心思路是用户提问时先从知识库里检索出最相关的若干片段把这些片段作为上下文塞给模型让模型基于这些真实材料回答。这样既解决了模型不知道私有知识的问题又大幅降低了幻觉。我做过对比同一个问题不带 RAG 的 Agent 回答准确率大概三成接上 RAG 之后能到八成以上差距非常明显。2.2 向量检索这条链路每一步都有讲究RAG 最经典的实现是向量检索。整条链路是文档切分、向量化、存入向量库、查询时向量化问题、相似度检索、返回 top-k 片段。听起来顺理成章但每一步都有坑。文档切分这块最忌讳的是按固定字数硬切。我早期就是每 500 字切一段结果经常把一句话、一个表格从中间切断检索出来的片段语义不完整。后来改成按语义边界切比如按段落、按标题层级切再对超长段落做二次切分效果好了很多。切分粒度也要权衡切太碎单段信息量不够切太大检索精度下降还浪费 token。我一般把单段控制在 300 到 800 字之间。向量化就是选一个 embedding 模型把文本转成向量。这里要注意查询和文档必须用同一个 embedding 模型否则向量空间对不上检索结果会莫名其妙地差。这个坑我踩过换了文档侧的模型忘了换查询侧排查了半天。2.3 向量库选型别一上来就上重型方案关于向量库检索需要什么数据库这个问题我的建议是分阶段。个人项目或者数据量在十万条以内直接用 FAISS 或者 Chroma 这种轻量库就够了本地跑零运维。数据量上到百万级、需要多租户或者高并发再考虑 Milvus、Qdrant 这类专业向量数据库。方案适用规模部署成本我的使用场景FAISS十万级以内极低纯本地库原型验证、个人知识库Chroma十万级以内低可本地可服务小项目快速起步Qdrant百万级中需独立部署中等规模生产Milvus千万级高集群运维大规模生产我个人的路径是先用 Chroma 把链路跑通等数据量和并发真的上来了再迁移。过早引入重型向量库运维成本会拖垮你的开发节奏。2.4 Rerank 是提升检索质量性价比最高的一步光靠向量相似度检索召回的结果里经常混着一些看起来像但实际不相关的片段。这时候 Rerank 就派上用场了。它的做法是先用向量检索召回一个较大的候选集比如 top 50再用一个专门的 rerank 模型对这 50 条做精细打分选出真正最相关的 top 5 给模型。为什么这步有效因为向量检索是粗筛它把语义压缩成向量快但不够准rerank 模型是精排它直接对问题和候选片段做交叉编码慢但准。两者结合既保证了速度又保证了质量。我实测下来加了 rerank 之后最终喂给模型的上下文相关性提升非常明显回答质量跟着上一个台阶。这一步的投入产出比在整个 RAG 链路里是最高的。3. Agent 的记忆管理短期、长期和它们各自的坑3.1 上下文窗口不是记忆别搞混了很多人以为把对话历史全塞进上下文窗口就是有记忆了。这是误解。上下文窗口是有限的而且塞得越多模型注意力越分散还越贵。真正的记忆管理要解决三个问题什么该记、什么该忘、怎么在需要时想起来。我把 Agent 的记忆分成两层短期记忆和长期记忆。短期记忆就是当前这轮任务相关的对话和中间结果任务结束就清掉。长期记忆是跨会话需要保留的信息比如用户的偏好、历史决策、重要事实。这两层的管理策略完全不同。3.2 短期记忆的核心是压缩和裁剪短期记忆的挑战在于一个复杂任务可能来回几十轮上下文很快就爆了。我的做法是分层处理最近几轮对话原样保留保证连贯性更早的对话做摘要压缩把关键信息提炼成几句话中间的工具调用结果如果已经用过且不再需要直接丢弃。这里有个技巧摘要不要等上下文满了才做而是每积累若干轮就主动压缩一次。这样每次压缩的量小信息损失也小。我一般每 5 到 8 轮做一次滚动摘要。另外工具返回的超长结果比如一整个网页的内容不要原样塞进上下文先做一次提炼只保留和当前任务相关的部分。3.3 长期记忆要考虑写入和召回两个方向长期记忆的工程实现本质上是另一套 RAG。写入方向要把值得记住的信息抽取出来向量化后存进记忆库。召回方向在每轮对话开始时根据当前问题去记忆库里检索相关记忆塞进上下文。这里最容易出问题的是什么值得记。如果什么都记记忆库很快就被噪音淹没如果记得太少又起不到作用。我的经验是只记三类东西用户的明确偏好、已经确认的事实、重要的决策结论。模糊的、临时的、可以从别处推导出来的都不记。注意长期记忆的写入一定要做去重和冲突检测。我遇到过用户改了偏好但旧偏好还在记忆库里导致 Agent 行为矛盾的情况。写入新记忆时先检索是否有相关旧记忆有的话做更新而不是简单追加。3.4 记忆安全是个容易被忽视的维度Agent 记忆里可能存着敏感信息如果被恶意输入诱导泄露后果很严重。我现在的做法是记忆写入前做一次敏感信息过滤召回时做一次权限校验确保当前会话有权访问这条记忆。另外要防止提示注入攻击通过污染记忆来长期影响 Agent 行为。这块展开能写一整篇核心原则就是记忆是数据数据就要有边界和权限。4. 工具编排与错误处理决定 Agent 能不能上生产4.1 工具不是越多越好而是越清晰越好新手常犯的错是给 Agent 塞一大堆工具觉得能力越强越好。实际上工具一多模型选择困难调用错误率飙升。我现在的原则是单个 Agent 的工具数量控制在 10 个以内超过就拆分或者做工具分组。更重要的是工具之间的边界要清晰。如果两个工具功能有重叠模型就会犹豫、乱调。我遇到过查询用户和搜索用户两个工具功能几乎一样结果模型每次都在两个之间随机选。后来合并成一个问题立刻消失。工具设计要像好的 API 设计一样职责单一、命名清晰、文档准确。4.2 工具执行失败是常态不是异常在 demo 里工具总是成功在生产里工具失败是家常便饭网络超时、接口限流、参数错误、权限不足。如果 Agent 没有错误处理能力一次工具失败整个任务就崩了。我的做法是给每个工具调用包一层错误处理捕获异常、把错误信息结构化、返回给模型让它决定下一步。关键是错误信息要写得让模型能理解并采取行动。比如不要返回Error 500而要返回订单查询服务暂时不可用建议稍后重试或改用其他方式获取订单信息。模型拿到这种信息往往能自己调整策略。def safe_execute(tool_name, params): try: result tools[tool_name](**params) return {status: success, data: result} except TimeoutError: return {status: error, message: 工具超时可重试} except ValidationError as e: return {status: error, message: f参数错误{e}请检查后重新调用} except Exception as e: return {status: error, message: f工具执行失败{e}}4.3 循环终止条件必须设死Agent 的 while 循环如果没有硬性终止条件遇到模型反复调用同一个工具、或者陷入死循环就会无限跑下去烧钱还出不来结果。我见过最夸张的一次一个 Agent 因为工具一直返回错误模型一直重试跑了两百多轮才被手动掐掉。我的终止条件设了三层最大轮次限制比如 15 轮连续相同工具调用检测如果连续三次调同一个工具且参数相同强制终止总 token 预算限制超过就停。这三层任何一层触发都要给用户一个明确的失败反馈而不是静默卡死。4.4 可观测性出问题时你得知道发生了什么Agent 跑在生产里最怕的是出问题查不到原因。所以从第一天起就要把可观测性做进去每一轮的输入、模型的思考、工具调用、返回结果、耗时、token 消耗全部结构化打日志。我一般会记录成一个 trace一个任务对应一条完整链路。有了这个 trace排查问题就是回放。模型为什么做了这个决策、哪一步开始跑偏、哪个工具拖慢了整体一目了然。这块投入在早期看着多余但一旦上量没有它你寸步难行。5. 从能跑到好用工程化的几个关键决策5.1 什么时候该引入框架什么时候该自己写手搓内核是为了理解但真做项目不可能什么都自己写。我的判断标准是如果框架能帮你省下的是重复造轮子的活比如工具注册、消息管理、多模型适配那就用如果框架要接管你的核心逻辑让你没法控制细节那就谨慎。LangChain 这类框架适合快速验证想法但它的抽象层比较厚出问题时排查链路长。我现在的做法是核心循环自己写外围的模型适配、向量库客户端、工具 schema 校验用成熟库。这样既控制了复杂度又不重复造轮子。5.2 多 Agent 编排别为了炫技而上现在很流行多 Agent 协作一个负责规划、一个负责执行、一个负责审核。听起来很美但我的经验是绝大多数场景单 Agent 加好工具就够了。多 Agent 带来的通信开销、状态同步、错误传播问题往往超过它带来的收益。真要用多 Agent我建议从主从模式开始一个主 Agent 负责拆解任务和调度若干子 Agent 负责执行具体子任务。这种结构简单、边界清晰。等这个模式跑顺了再考虑更复杂的对等协作。上来就搞一堆 Agent 互相聊天大概率是一地鸡毛。5.3 成本控制是工程化绕不开的坎Agent 比普通 LLM 调用贵得多因为它一轮任务可能调用十几次模型。成本控制我主要靠三招一是缓存相同或相似的查询结果缓存起来避免重复调用二是模型分级简单任务用小模型复杂推理才用大模型三是上下文精简前面说的记忆压缩和工具结果提炼本质上都是在省钱。我算过一笔账一个没做任何优化的 Agent单次任务成本可能是优化后的五到十倍。这个差距在量小的时候无所谓量一大就是生死线。5.4 评测没有评测就没有迭代Agent 好不好不能靠感觉。我现在的做法是维护一个评测集里面是真实场景的问题和期望结果。每次改动 prompt、换模型、调检索参数都跑一遍评测集看准确率、成功率、平均轮次、平均成本这些指标的变化。没有评测集你的所有优化都是盲猜。我早期就是凭感觉调改了半天不知道是变好了还是变坏了。有了评测集之后每次改动都有数据支撑迭代速度完全不一样。评测集不用一开始就很大几十条真实 case 就能起步关键是持续积累。6. 一些踩坑之后才明白的事6.1 模型能力不是瓶颈工程细节才是我一开始总想着换个更强的模型就能解决问题后来发现大部分问题根本不在模型。检索召回不准、工具描述含糊、上下文塞了无关信息、错误处理缺失这些工程细节才是决定 Agent 表现的关键。同一个模型工程做得好和做得差效果能差出好几倍。所以别老盯着模型排行榜先把工程链路打磨好。6.2 提示词要当代码来管理Agent 的提示词不是随便写几句话它是核心逻辑的一部分。我现在把提示词单独抽出来做版本管理改动走 review配合评测集验证。这样每次改动都可追溯、可回滚。把提示词散落在代码各处是后期维护的噩梦。6.3 用户预期管理比技术本身更重要Agent 再强也有边界。如果用户以为它无所不能一旦遇到它答不了的信任就崩了。所以我在产品层面会明确告诉用户 Agent 能做什么、不能做什么遇到不确定的情况主动说这个我不确定建议你核实一下。坦诚反而能建立信任。技术做得再好预期管理没做好用户体验照样差。6.4 安全边界要从设计阶段就考虑Agent 能调用工具、能访问数据这意味着它的权限边界必须清晰。哪些工具它能调、哪些数据它能碰、什么操作需要人工确认这些要在设计阶段就定死而不是出了事再补。尤其是涉及写操作、涉及敏感数据的场景一定要有确认机制和审计日志。这块我踩过坑早期一个 Agent 能直接改数据库现在想想都后怕。从零手搓一个 Agent最难的从来不是让它跑起来而是让它跑得稳、跑得准、跑得起。内核那两百行代码两天就能写完但围绕它的检索、记忆、编排、错误处理、评测、安全才是真正花时间的地方。我自己的体会是把每个环节都搞明白原理比堆砌框架和工具重要得多。你对手里这套东西理解得越透遇到问题时就越不慌。这个领域变化很快但底层的那些工程原则短期内不会变。

相关推荐

Android Studio Windows安装避坑指南:Gradle与SDK配置详解
Android Studio Windows安装避坑指南:Gradle与SDK配置详解

1. 为什么 Android Studio 的安装从来不是"下一步下一步"那么简单如果你在网上搜"Android Studio下载和安装(Windows版)",大概率会看到一堆截图教程,从头到尾就是"点这里、点那里、点Next"。但真正… · 2026/9/26 19:36:55

Cursor系列(1):Cursor安装、虚拟环境与 TaoToken 配置骨架
Cursor系列(1):Cursor安装、虚拟环境与 TaoToken 配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 19:36:43

一张丑图胜千言:用Cursor调试DirectX 12着色器时,我重新认识了多模态
一张丑图胜千言:用Cursor调试DirectX 12着色器时,我重新认识了多模态

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 19:36:43

普通人要 OpenClaw 有什么用?从 skill 到 amazon Scraper APIs 的 Python 配置骨架
普通人要 OpenClaw 有什么用?从 skill 到 amazon Scraper APIs 的 Python 配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 20:21:08

固定电话正则校验实战:从规则到代码,避开线上常见坑
固定电话正则校验实战:从规则到代码,避开线上常见坑

做前端表单的人,迟早会遇到一个需求:校验用户填的固定电话。你搜索“JS固定电话正则”,网页里跳出来一大串表达式,复制到项目里,测试“010-12345678”,通过了。结果上线第二天,用户反馈“0755 1… · 2026/9/26 20:21:02

Substrate 区块链开发框架详解:从状态机到应用链的模块化实践
Substrate 区块链开发框架详解:从状态机到应用链的模块化实践

过去半年里,我花了不少时间在 Substrate 上,尤其是给不同业务方搭定制化的应用链,期间被问得最多的就是一句话:“Substrate 到底是什么?它是一条链还是一个框架?”每次我都得从状态机讲到 Runtime 再讲到 p… · 2026/9/26 20:20:49

Substrate不是AI Agent框架:区块链与Agent技术栈的本质区分
Substrate不是AI Agent框架:区块链与Agent技术栈的本质区分

1. Substrate不是AI Agent框架,而是区块链底层构建平台的误读源头最近在多个技术社区和招聘JD里反复看到“Substrate”和“Agent”被混为一谈——有人问“Substrate怎么集成AI Agent”,也有人把gVisor、Kubernetes Device Plugin和Substrate全塞进同一份… · 2026/9/26 20:20:49

AI短剧工业化流水线:从剧本到成片的全链路控制
AI短剧工业化流水线:从剧本到成片的全链路控制

1. 这不是“一键生成”,而是真正能落地的AI短剧生产流水线最近三个月,我帮七家不同背景的团队落地了AI短剧项目——有刚转型的新媒体公司、有做儿童内容的教育品牌、也有想试水IP孵化的独立创作者。他们共同的问题不是“能不能做”,而是“怎么… · 2026/9/26 20:20:49

PyTorch实战:非线性函数拟合全流程解析与调参指南
PyTorch实战:非线性函数拟合全流程解析与调参指南

1. 项目概述:为什么拿这个简单函数练手看到“基于 PyTorch 实现非线性函数拟合(拟合 yx^32x^2)”这个任务,可能有人觉得太简单了,不就是个三次多项式吗?但恰恰是这个“简单”,让它成了我接触到的… · 2026/9/26 20:20:41

数据库课后习题答案别硬背:当测试用例集刷,效率翻倍
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍

简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21

OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40

向下兼容与向上兼容:接口设计中的兼容性策略与工程实践
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践

一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码