AI Agent架构从零拆解:模型、规划、记忆与工具四要素 先说结论把大模型从“对话框”变成“代理人”核心不是模型本身而是围绕模型搭一套“能规划、能记事儿、能动手干活”的框架。这篇帖子准备从零拆解AI Agent的架构不堆名词尽量让刚接触的朋友也能看懂顺便给想动手实践的人留一条能直接照做的路径。标题里有一个词值得琢磨为什么是“代理人”而不是“助手”因为助手是你问一句、它答一句主动权在你手里代理人是你交代一个目标它自己拆解步骤、自己调用工具、自己根据结果调整方案最后把结果交给你。ChatGPT这类产品背后是“大模型”而Agent是“大模型 规划 记忆 工具”的完整组合体相当于给模型装上了手和脚还给了它一张任务清单和一本笔记本。这篇文章适合谁想理解Agent底层逻辑的产品经理、刚入门大模型开发的同学、想在自己项目里集成Agent能力的程序员以及单纯好奇“AI到底怎么自主干活”的爱好者。我会从最朴素的概念讲起逐步拆到代码级别最后给出踩坑记录。全文不依赖特定平台也不绑定某一家厂商的API思路通用。1. 从“对话框”到“代理人”到底多了什么1.1 对话系统的本质一次性的“文本续写”先看最基础的对话系统。你输入一段文字大模型本质上是在做一件事根据已有的文本预测下一个最合理的token可以理解为词语碎片。它没有目标没有计划更没有“完成一件事”的概念。你问“今天天气怎么样”它生成“今天晴转多云”——这个回答是它根据海量语料统计出来的最可能续写而不是它去查了气象数据。这就是为什么早期聊天机器人经常“一本正经地胡说八道”。它的所有能力都局限在“生成文本”这一件事上哪怕它给你写了一个“帮你订机票”的回复模板它也没法真的去调用订票接口。1.2 Agent新增的三项关键能力“代理人”要能独立完成任务需要三样东西规划能力把大目标拆解成有序的小步骤。比如“帮我策划一场团建”要拆成“确定人数和预算”、“筛选场地”、“生成日程表”、“输出方案文档”。记忆能力短期记忆保证多轮对话里不丢失上下文长期记忆让它能记住用户偏好、历史任务结果下次交互时直接调用。工具调用能力通过函数调用或API请求让模型能操作外部系统比如搜索引擎、计算器、数据库、订票平台。这是让AI从“嘴上说”变成“手上做”的关键一步。1.3 一个通俗类比刚毕业的新员工把Agent比作一个刚入职的新员工。大模型本身是这个员工的“脑子”基础知识扎实反应快但没经验、没权限、没人脉。你要让他“搞定一份市场调研报告”他不能光靠脑子想需要自己拆解报告框架规划、问你要过往项目资料短期记忆、查阅公司知识库长期记忆、调用数据分析工具工具、遇到数据缺失再调整方案反思循环。AI Agent的架构就是给这个“新员工”配齐工作手册、笔记本、电脑和上级的授权。四者缺一他就退化成“脑子好但干不了活”的实习生。2. 核心架构逐层拆解模型、规划、记忆、工具2.1 模型层Agent的“大脑硬件”模型层是整个系统的地基负责理解语言、生成推理、输出决策。当前主流方案是调用大模型API选择的维度主要有三个推理能力Agent在执行过程中经常需要多步推理比如“用户要订周五去杭州的票——先查天气——再查高铁——再查酒店——组合方案”。模型推理能力弱中间某一步就会“断片”。上下文长度一次任务涉及的历史对话、工具返回结果、中间步骤都可能很长。上下文窗口太小早期的信息会被截断Agent就像金鱼一样只有七秒记忆。函数调用/工具格式支持这是最容易被忽略的一点。好的Agent框架依赖模型能稳定输出结构化的工具调用指令比如输出一个JSON格式的“调用订票接口”指令。如果模型没有针对工具调用做过微调输出的格式经常是坏的解析器直接报错。实操层面我的建议是不要盲目追求参数量大的模型。一些轻量模型在特定任务上表现并不差关键是做评测。准备一套只有20条任务的小数据集每条任务包含“用户指令、期望调用工具、期望参数”跑一遍看准确率再决定用哪个模型。2.2 规划层从“目标”到“步骤清单”规划层解决的是“每一步做什么”的问题。目前行业内有三种主流的规划模式ReAct模式推理行动循环模型先生成一句思考Reasoning再生成一个行动Action观察行动结果Observation再进入下一轮思考。这种模式最直观像人一样“想一步、做一步、看一步”。Plan-and-Execute模式先计划后执行模型先把整个任务的步骤一次性列出来形成一份计划书然后逐步执行。适合任务结构清晰的场景比如报表生成、定时任务。反思/自我修正模式在执行完一轮之后让模型自己评估结果是否满足目标不满足就重试或换方案。常见做法是加一个“Reflection”提示词让模型对比目标输出和当前输出的差距。实际项目中三种模式经常混合使用。我的经验是复杂任务用ReAct作为主循环在每一步内嵌Plan-and-Execute来细化子任务最后加一层自我修正兜底。规划层的一个坑是“过度规划”。模型可能列出20步实际只需要5步。解决办法是限制最大迭代次数并制定简单的终止条件“当所有子任务都标记为完成或者达到最大步数结束循环”。2.3 记忆层短期、长期与工作记忆Agent的记忆分三层对应不同的存储介质和使用周期短期记忆上下文窗口存放当前任务的对话记录和中间结果通常就是prompt里拼接的内容。缺点是有长度上限超出后要么截断要么做摘要压缩。长期记忆外部存储存放在向量数据库或普通数据库里包括用户偏好、历史任务、领域知识。使用时通过相似度检索把相关内容拉回上下文窗口。工作记忆状态缓存存放当前任务的变量比如“已经订好了酒店”、“出行人数是4人”保证在多个步骤之间传递状态。长期记忆最常见的技术方案是“向量化 相似度检索”。大致流程把历史文本切片用embedding模型转成向量存入向量数据库新任务进来时把任务描述也转成向量在数据库里做余弦相似度搜索找到最相关的几条记录拼进提示词里。这里有一个容易踩的坑不要把所有历史都存下来也不要只存向量。历史记录量一大向量检索会命中很多噪音反而干扰模型。建议加一层过滤逻辑比如按时间衰减、按任务类型过滤甚至人工设定“重要记忆”标记。2.4 工具层Agent的“双手”工具层是把大模型从“纸上谈兵”变成“动手执行”的关键。一个工具本质上是一个函数有名字、有描述、有参数列表、有执行后的返回结果。Agent通过模型生成的结构化指令来调用它。工具设计有三个原则描述要极其清晰工具描述是写给模型看的不是写给用户看的。比如“search_product(name: str, category: str None) - list”描述要写成“在商品数据库中搜索商品返回商品列表name是商品名称category是商品分类可选”。模型会根据描述来决定是否调用描述含糊模型就会乱用。粒度要适中工具太粗一个“do_everything”函数模型不知道怎么拆解工具太细一个“add_two_numbers”函数模型步骤太多容易出错。经验标准一个工具完成一件原子任务一次调用能拿到一个完整结果。错误处理要内置工具执行失败时返回信息必须包含错误原因而不是空结果。否则模型会拿“空结果”当成“正常结果”继续往下推理。比如“查无此人”和“数据库连接失败”是两种完全不同的状态后者应该触发重试逻辑。3. 组件协同一条任务从下发到完成的完整流程很多人理解Agent架构时最大的困惑是“这些组件到底是怎么配合的”。我画一条完整的任务链路用“给团队订团建餐厅”为例。第一步用户输入“周五晚上团队8个人订一家能容纳我们的川菜馆人均预算150以内。”意图识别与任务解析模型层 规划层模型把输入解析成结构化任务人数8人、时间周五晚、菜系川菜、预算人均150。并初步规划步骤搜索餐厅 - 筛选符合条件的 - 查看预订情况 - 生成预订方案。搜索餐厅工具层Agent调用search_restaurant(cuisine川菜, capacity8)工具。返回5家店铺。筛选与决策规划层 模型层模型对比返回结果检查人均价格和评分选出2家符合条件的。检查预订信息工具层调用query_availability(restaurant_id, time周五 19:00, party_size8)。其中一家已满另一家有位置。生成预订方案模型层模型生成一段自然语言总结并附带一个结构化预订请求restaurant_id、时间、人数。确认执行工具层 状态缓存调用create_reservation(...)返回预订成功信息写入工作记忆。汇报结果模型层生成最终汇报“已为您预订XX川菜馆周五19:008人桌人均145元预订号xxxx。”这条链路里模型、规划、工具、记忆四个组件各司其职缺一环就断。没有工具层模型只能“建议你去吃川菜”没法真的订上没有记忆层步骤5之后模型就忘了之前选的哪家店没有规划层模型可能第2步就跳到第6步直接乱套。4. 手把手搭一个最小可运行的Agent框架理论说再多不如动手跑一遍。下面我用Python写一个极简Agent核心循环不含第三方Agent框架只依赖大模型API和两个模拟工具。代码是简化版目的是让理解架构生产环境直接套框架也行但核心循环是一样的。4.1 定义工具集# 模拟工具层 def search_restaurant(cuisine: str, capacity: int) - list: 模拟搜索餐厅返回列表 fake_db [ {id: 1, name: 蜀香居, cuisine: 川菜, price_per_person: 120, capacity: 10}, {id: 2, name: 辣味鲜, cuisine: 川菜, price_per_person: 160, capacity: 8}, {id: 3, name: 巴适小馆, cuisine: 川菜, price_per_person: 140, capacity: 6}, ] return [r for r in fake_db if r[cuisine] cuisine and r[capacity] capacity] def create_reservation(restaurant_id: int, time: str, party_size: int) - str: 模拟创建预订 return f预订成功餐厅ID {restaurant_id}时间 {time}人数 {party_size}工具函数search_restaurant里加了容量过滤这是第一步筛选返回结果里包含人均价格供模型第二步筛选。4.2 构建模型指令与循环tools [ { name: search_restaurant, description: 按菜系和人数搜索合适的餐厅, parameters: { type: object, properties: { cuisine: {type: string, description: 菜系}, capacity: {type: integer, description: 就餐人数} }, required: [cuisine, capacity] } }, { name: create_reservation, description: 为指定餐厅创建预订, parameters: { type: object, properties: { restaurant_id: {type: integer, description: 餐厅ID}, time: {type: string, description: 预订时间}, party_size: {type: integer, description: 人数} }, required: [restaurant_id, time, party_size] } } ] def agent_loop(user_input: str, max_steps: int 5): messages [{role: user, content: user_input}] for step in range(max_steps): # 调用大模型传入工具定义 response llm_call(messages, toolstools) assistant_message response[message] messages.append(assistant_message) # 判断是否要调用工具 if assistant_message.get(tool_calls): for tool_call in assistant_message[tool_calls]: result execute_tool(tool_call[name], tool_call[arguments]) messages.append({ role: tool, tool_call_id: tool_call[id], content: result }) else: # 没有工具调用说明任务结束输出最终回复 return assistant_message[content] return 已达到最大步数任务结束。这个循环的核心逻辑只有三行调模型 - 如果有工具调用就执行并回传结果 - 如果没有就返回最终答案。所有Agent框架不管多复杂核心都是这个“模型-工具-模型”的闭环。4.3 一个实测的小例子我用模拟的模型响应走一遍流程真实环境换成大模型API即可用户输入“周五晚上8个人找一家川菜馆”第一轮模型生成search_restaurant(cuisine川菜, capacity8)执行后返回2家餐厅蜀香居和辣味鲜巴适小馆因为只有6个座位被过滤。第二轮模型看到两家结果判断“蜀香居人均120更符合预算”生成create_reservation(restaurant_id1, time周五 19:00, party_size8)。第三轮执行成功模型生成最终回复“已为您预订蜀香居周五19:008人位人均120元。”整个过程里模型自己完成了“决定调用哪个工具、传什么参数、根据结果做下一步判断”这三个动作没有任何人来编写if-else逻辑。这就是Agent的核心价值用自然语言作为控制流模型充当“决策者”代码只负责执行。4.4 如果不用框架直接写有什么代价上面这套代码能跑但生产环境你会遇到一堆问题模型偶尔输出非法JSON、工具返回异常导致死循环、上下文一长就超token限制、没有重试机制一失败就崩溃、没有日志导致排错困难。所以我个人的建议是教学理解用上面的纯手写版本生产环境直接基于成熟框架二次开发因为框架把错误重试、上下文管理、并发调度、日志追踪这些脏活累活都封装好了。但不管用什么框架你对“模型-工具-模型”这个闭环的理解越深用起来越顺手。5. 入门最容易踩的六个坑及解决方案5.1 模型上下文被塞爆Agent每一步都会把历史记录、工具返回结果拼进messages几轮交互后上下文迅速膨胀。我见过初学者跑一个任务第三次循环就因为token超限直接报错。解决方案对工具返回的长文本做摘要只保留关键信息回传。历史消息做截断只保留最近几轮。对大段中间推理过程做压缩最终答案重新让模型润色。5.2 工具调用格式不稳定有些模型没针对函数调用微调过输出不是规范的JSON而是“我建议你调用search_restaurant(川菜, 8)”。解析器一看直接崩。解决方案选模型时优先选明确支持工具调用的版本。解析错误时不要硬刚把“输出格式不符合要求”作为Observation回传给模型让它重新生成。这一步非常有效模型会自动纠正格式。5.3 死循环模型反复调用同一个工具比如模型明明已经拿到搜索结果还继续调用搜索函数或者调用参数完全一样造成死循环。解决方案设置最大迭代次数同时在每次工具调用前检查“该工具该参数是否已经调用过”如果重复强制打断并要求模型换一种方式。5.4 工具返回结果被误读工具返回“查询结果为空”模型可能理解为“系统出错了”也可能理解为“确实没有数据”导致后续推理方向跑偏。解决方案工具返回值里显式增加status字段区分“成功但无数据”、“成功且有数据”、“失败/错误”。模型对明确的状态字段理解准确率高得多。5.5 记忆与当前任务混淆长期记忆系统里存了“用户上次团建去了日料店”这次用户说“换个口味”模型可能因为检索到旧记忆推荐了一堆日料店。解决方案在检索阶段加入“时间敏感度过滤”——越靠近当前时间的记忆权重越高同时允许用户指令显式覆盖旧记忆比如“不要根据以往偏好这次想吃辣的”。5.6 过度设计框架选型过重入门阶段最常见的问题不是技术难度而是“想太多”。有人一上来就上分布式任务队列加向量数据库加日志平台结果小任务都没跑通光调试架构就花了一周。我的原则先跑通最小闭环再按需加组件。最小闭环是“模型 两个工具 五步循环”跑通之后再考虑加记忆、加规划器、加并发。每一步加组件都要确认它解决了明确的痛点而不是为了“架构完整”而堆砌。6. 工具选型参考自研框架与现成框架怎么选很多人纠结“要不要用LangChain 这类框架”我的建议按项目阶段来判断阶段推荐方案理由学习理解手写核心循环能把每个环节的机理吃透原型验证轻量框架 手写工具快速验证业务逻辑生产环境成熟框架 严格评测稳定性、错误处理、监控补齐现成框架最大的价值在于四件事对话线程管理、工具解析与重试、上下文自动压缩、成本追踪。这些功能自己写也不难但没必要在生产环境重复造轮子。唯一的提醒是不要被框架绑架。框架的抽象层级越高你对底层行为越失控。关键时刻回到底层循环本身排查问题比在框架文档里翻半天更快。7. 进阶方向与实践路径建议如果读完前面的内容你已经能跑通一个最小Agent恭喜入门了。接下来的进阶方向我按优先级排序复杂规划器尝试把ReAct模式换成Plan-and-Execute对比两种模式在复杂任务上的成功率差异。多Agent协作拆成“任务拆解Agent”、“执行Agent”、“质量检验Agent”让每个Agent只做一件事。多Agent系统真正的难点不在代码而在“任务交接”和“冲突仲裁”。记忆系统升级给长期记忆加上时间衰减、重要度评分甚至用另一个Agent定期整理记忆库。评测体系这是最容易被忽略但最值得投入的。准备一个固定的任务集50~100条每次改代码后全量跑一遍记录成功率、平均步骤数、平均耗时、token消耗。没有评测你根本无法判断改动是变好还是变坏。我个人在实际项目中的经验是Agent开发里最耗时间的往往不是写代码而是调提示词和调工具描述。同一个工具描述从“搜索餐厅”改成“在本地餐厅数据库中执行搜索支持菜系、人数、价格过滤返回符合条件且容量足够的餐厅列表”模型的调用准确率可能从60%涨到90%以上。先调描述再改代码多数时候是对的路径。另外分享一个小技巧调试Agent时把每一轮的“思考文本”和“工具调用参数”完整打出来。不要只打印最终结果。中间过程能告诉你模型是怎么想的是在哪一步开始跑偏的。我见过太多人只看最终输出发现结果不对但完全查不到原因就是因为中间过程被日志系统吃了。Agent这个方向还在快速演进今天的架构认知大概率会在两年后被刷新。但“模型规划记忆工具”这四个组件的基本划分以及“模型做决策、代码做执行”的核心思想短期内不会变。先把这篇的基础打牢后续学什么新框架都会很快上手。