这两年AI智能体Agent几乎成了程序员圈子里最绕不开的关键词。无论是自媒体的入门帖还是技术社区的高赞分享大家都在说同一件事大模型本身很强但要让模型真正“干活”光靠对话是不够的。想做一个能自动检索资料、调用外部工具、独立完成闭环任务的程序就必须有一套清晰可控的架构方案。今天要聊的“AI智能体五层架构”就是我在多个实际项目里反复验证过的一套路子。五层分别指感知层、记忆层、规划层、工具层和执行层。每一层各管一段从接收用户请求开始理解输入、组织上下文、制定计划、调用能力、执行动作最后再把结果反馈回用户。这篇内容适合两类人一类是刚学完大模型基础、准备上手做Agent的初级开发者另一类是已经在写Agent但感觉系统不太稳定、想找地方做架构优化的程序员。文章会用项目实战的视角去拆解每一层尽量少讲虚的。1. 为什么是五层AI智能体的架构全景早期我做Agent的时候思路特别简单写一个很长的System Prompt把所有指令、背景、可用工具的描述都塞进去然后循环让模型调函数。刚开始Demo跑得挺顺可一旦切换场景、加几个工具马上就崩——模型开始频繁遗忘指令工具调用错误率上升改一处逻辑要连带改好几个文件。后来我意识到这本质上不是模型的问题而是架构的问题。1.1 分层要解决的三类核心问题第一类是复杂度治理问题。一个完整的Agent项目往往牵扯模型交互、上下文窗口管理、外部API调度、沙箱执行、校验重试等多个环节。所有逻辑揉在一个循环里代码会迅速膨胀到没法维护的状态。分层之后每层只关心一件事相当于把一个巨型类拆成几个可独立替换的模块。第二类是演进边界问题。今天你可能用某个大模型API明天可能因为成本或效果原因切到另一个模型。今天你用的是本地向量库明天可能想换成外部知识库服务。这些变化如果都耦合在同一个函数里每次切换都是一次大手术。分层的价值就是把变化隔离在某一层内部其他层通过稳定的接口对接即可。第三类是测试和定位问题。不分层的Agent一出bug你只能从头到尾人工推演一遍时间成本极高。分层后每一层都可以单独做单元测试感知层测解析是否准确记忆层测召回是否相关规划层测拆解是否合理工具层测参数是否合规执行层测结果校验是否可靠。1.2 五层架构的总览与边界我把五层职责画成一张表方便后面展开讲解。这张表也是我给团队做技术方案时最常用的底稿。层级核心职责关键组件典型产出感知层接收并标准化用户输入文本解析、意图识别、实体抽取结构化请求对象记忆层管理短期上下文与长期知识滑动窗口、向量索引、摘要缓存组装好的上下文片段规划层拆解目标并生成执行策略任务分解器、推理循环、反思机制有序的子任务计划工具层连接外部能力和数据工具注册表、参数校验器、API适配器带参数的可执行函数调用执行层运行动作并校验结果沙箱环境、超时控制、断言检查任务结果与状态回传边界划分有一条核心原则相邻层只依赖接口不依赖实现。记忆层不知道模型最后是怎么规划的规划层也不知道工具层背后的API是REST还是本地进程。这样一来替换任何一层都不会引发连锁溃败。1.3 层与层之间到底怎么流转数据整个架构的流转方向是纵向的。用户输入先进感知层感知层把“零散的提问”转成“结构化的请求”比如用户说“帮我看下这个仓库的测试覆盖率为什么降了”感知层会输出一个包含目标、对象、范围、约束字段的任务对象。接下来进入记忆层它会根据任务对象去检索相关的历史对话、文档片段、仓库元信息拼装出模型需要的上下文。规划层拿到完整上下文后会把“计算测试覆盖率下降原因”这个大目标拆成若干个可执行小步骤比如先读取CI配置、再定位最近的提交记录、最后对比覆盖率报告。工具层根据规划结果把“读取CI配置”映射成具体的函数调用和参数。执行层去真实环境里跑命令、操作数据再把结果返回给规划层继续判断如此循环直到任务完成。整个过程类似一个“感知-思考-行动-观察”的循环五个层各司其职数据有来有回最终才形成可靠的智能体闭环。2. 逐层拆解从感知到执行的完整链路这一部分我挑重点讲。每一层都会聊到原理解释、实现方案、参数选择逻辑和落地时最容易被忽视的细节。2.1 第一层感知与输入解析感知层再难本质上就是两件事听懂用户想干什么以及检查系统能不能接住这个请求。先说听懂。现在大模型的能力很强但感知层不能一上来就把所有原始输入直接扔给模型处理否则很多脏数据、无效指令会白白消耗上下文窗口还可能诱导模型跑偏。我的习惯是设置一层“前置预处理”包括格式标准化、超长截断、敏感字段过滤、明显意图快速分类等。比如用户上传一个压缩包感知层会先解压、检查目录结构再把文件列表交给规划层而不是直接把二进制内容塞进对话。再说系统接不接得住。很多Agent部署到生产后才发现用户可能会连续多次提问单次输入长度超过模型阈值用户可能用方言、语音转写文本有噪音用户甚至会对系统提出“帮我修改数据库里的数据”这类越权指令。感知层要把这些边界兜住属于能力范围之外或权限不足的任务直接在入口明确拒绝或者转人工而不是放任它一直执行到最后。在工程实现上我建议感知层维持一个“结构化输入模板”。一个标准的AgentRequest对象至少包含这些字段AgentRequest: - raw_input: 原始文本或消息 - parsed_intent: 识别出的意图标签 - entities: 抽取出的关键实体路径、文件、时间范围等 - permissions: 当前用户或会话的权限级别 - constraints: 额外的处理约束超时、预算、输出格式要求感知层输出质量决定整个系统的下限。这里没有特别复杂的算法更多是规则和模型的组合简单明显的指令用正则和关键词快速路由复杂、模糊的请求交给模型做意图抽取。我见过不少项目在感知层省事结果用户问一句“看看昨天的情况”被系统理解成两个完全不相关的任务最后整个链路都跟着出错。2.2 第二层记忆与上下文管理记忆层是五层里面工程细节最密的环节也是最容易出性能问题的地方。它要解决的核心矛盾是模型上下文窗口有限但Agent运行时需要的信息量可能远超窗口限制。可以把记忆拆成短期记忆和长期记忆两类。短期记忆面向当前会话负责保存最近几轮对话、当前任务中间结果、模型已经说过的关键结论长期记忆面向跨会话负责存放已经沉淀下来的知识比如产品文档片段、历史问题解决方案、用户偏好、代码库检索索引。短期记忆最常用的是“滑动窗口摘要压缩”的双层方案。滑动窗口保留最近K轮完整对话保证模型对近期内容有精确理解超过K轮但重要的信息用一个大模型把关键结论浓缩成摘要塞进窗口顶部。窗口Size怎么定我一般根据模型上下界限定假设模型上限是128K Token我会让短期记忆最多占50%左右剩下空间要留给检索回来的长期信息、工具返回结果和模型系统提示词。写代码的时候我会在记忆层记一个“上下文占用率”指标一旦接近上限就触发压缩策略而不是等到模型报错再处理。长期记忆最常见的载体是向量数据库加语义召回。流程是把文档或历史消息切成小块做Embedding后写入索引需要时把当前问题也做Embedding用相似度检索返回TopK个片段。这里有两个参数特别关键一个是TopK我通常从5调到10再根据效果看召回准确率有没有明显下降另一个是相似度阈值低于0.7的片段基本跟主题无关宁可不要也别强行塞进上下文否则会引入噪音。记忆层还有一个容易被忽略的工程问题记忆污染。早期我犯过一个错误把工具执行报错的原始日志也写进长期记忆结果后面几次任务模型都被那段错误日志干扰反复尝试已经失败过的方案。现在我会对所有写长期记忆的内容做一次质量筛选错误信息、临时状态、无明确结论的内容一律不写入只有经过校验的完整结论才允许沉淀。2.3 第三层规划与决策规划层是智能体“变聪明”的关键也是判断一个Agent是不是“真智能”而不是“高级搜索”的分水岭。先说最主流的一种规划范式也适用于多数任务拆解目标循环执行。模型拿到一个总目标后先把它拆解成若干有序子任务然后逐个执行每执行完一个子任务拿到观察结果再决定下一步动作。这个范式对应到我前面说的“感知-思考-行动-观察”循环业界通常称为ReAct。本质上就是一边推理一边行动把思考过程显式地写在上下文中让每一步决策都有可追溯的依据。在实现上我会给规划层定义一个“计划状态机”包含待执行、执行中、已完成、已失败、已中止几种状态。每轮循环规划层先看当前状态再决定是继续拆解、调用工具还是结束任务。这里要特别说一个必须设置的约束最大轮数和最大预算。模型在开放式任务里很容易陷入“自我感动式的深挖”一个问题能追十几轮Token消耗很快但产出并不增长。我现在都会在规划层顶部加一个预算标签比如“最多执行8轮工具调用超时或超预算强制进入总结阶段”。规划质量的高低很大程度上取决于反馈的质量。我做项目时发现模型第一次给出的计划往往不够好但如果能在执行失败后让它看到“为什么失败、现在的可用信息是什么、换什么方法重试”第二次规划通常会有明显改善。这个机制叫反思。实践里我会把上一次计划的错误原因、失败信息的摘要、当前的环境状态都转成结构化文本交给模型重新生成新计划。用过之后任务总轮数平均少了30%左右。这层最容易踩的坑有两个一个是拆解粒度太粗子任务本身仍然复杂到无法一次性执行另一个是完全相反拆解粒度太碎导致工具调用出现大量重复前缀浪费大量Token和延迟时间。我一般拿“工具一次调用能否在一个可预测的步骤内完成”作为拆分粒度的判断标准能就拆到这里不能就继续往下拆。2.4 第四层工具调用与外部能力扩展工具层可能是程序员上手最快的一层因为它的本质是接口对接。但越是看起来简单的地方越容易埋雷。工具层的基础能力是函数调用Function Calling。从原理上讲这一步并不神秘模型本身不会直接执行代码它只是根据工具描述生成一个结构化的调用参数JSON。比如工具层注册了一个“读取文件”的函数模型分析问题后输出{ function: read_file, parameters: { path: docs/architecture.md, start_line: 1, end_line: 200 } }真正执行“读文件”这个动作的是代码不是模型。模型只负责“决定调用谁、参数怎么给”执行权永远在系统手里这是个非常重要的边界。既然模型靠“工具描述”来决定调用谁那么工具描述写得够不够好就直接决定了模型的选型准确率。我见过一个团队的工具描述写的是“处理文档”结果模型在需要汇总PDF内容时反复选择这个工具实际上这个工具只能转换格式根本不具备理解能力。工具描述应该包含四块内容这个工具到底是干什么的、什么场景下用、什么场景下千万别用、参数每个字段是什么含义。一份好描述看似多写了几十个Token却能大幅降低选错工具的概率。工程上还建议做一层“工具注册表”每个工具实例维护一份标准信息包括唯一名称、版本号、描述、参数JSONSchema、调用地址、超时时间、权限等级。新增一个工具不需要改规划层、执行层的代码只要在注册表里添一条记录即可。我在项目里甚至做了一个工具启用开关生产环境通过配置下发来决定哪个工具对哪个会话可见避免模型在无关场景里乱调函数。工具层安全上的细节必须提一下。外部输入拼命令行、拼URL是高风险行为所有由模型生成的参数都必须经过白名单校验和格式校验路径要检查是否越界命令要检查是否命中了被禁止的执行体。不要相信模型生成的参数绝对合法必要的时候让执行层跑在沙箱里。2.5 第五层执行、校验与反馈闭环执行层是最后一道关卡但它绝对不是“简单调用一下代码”那么轻松。执行层真正要学会的是两件事安全稳定地执行动作以及严格校验结果是否真的可用。先说执行环境。对Agent这种可能执行任意命令、操作文件、请求外部服务的程序来说沙箱几乎是默认选择。一个典型的最小沙箱配置是独立的容器环境、网络策略默认拒绝出网、文件系统只挂载必要目录、CPU和内存设置限制、单轮命令最大运行时长默认120秒。这个配置不是越严格越好而是尽量在“足够隔离”和“足够好用”之间取平衡。如果一个Agent的主要任务是写代码、跑测试那执行环境至少得能装依赖、能编译限制太死会直接导致Agent什么都干不了。执行完成不代表任务成功这是我要反复强调的地方。工具返回一个退出码为0的结果并不等于结果正确。实际项目中我遇到过很多次“命令执行成功但结果是错的”的情况构建成功但产物缺少关键模块检索到一批文档但跟用户问题完全无关数据表更新成功但波及了不该触碰的行。所以执行层必须叠加校验逻辑包括断言式检查、输出关键词校验、跨数据源交叉对比甚至在关键环节引入人工确认。执行层还需要完成一个容易被忽视的动作把执行结果往回写形成闭环。结果要拆成“执行摘要”和“完整结果”两个粒度执行摘要进入短期记忆供规划层直接判断完整结果进入长期记忆或外部存储供后续审计、追溯和检索使用。我自己做项目时每次工具调用结束后都要生成一条规范化的观测记录包括调用时间、模型选择、参数摘要、执行状态、结果摘要这为后面调试和复盘省了大量时间。3. 一个Agent的完整生命周期跑通五层协作只看理论很难建立体感我用一个真实做过的场景来串联整个架构。假设现在要做一个面向大型代码仓库的“代码仓库智能助手”功能是支持用户用自然语言提问系统帮忙检索源码、分析逻辑、执行构建并输出结论。这个Demo虽然不算特别复杂但五层都能完整覆盖。3.1 场景设定与需求拆解先看用户侧需求。代码仓库智能助手要接住三类典型问题第一类是“查事实”比如问某个函数在哪里定义、被谁调用第二类是“做分析”比如问某个模块最近的改动是否引入风险第三类是“执行操作”比如触发一次构建或者给分支创建合并请求。这三种任务的复杂度完全不同感知层要做的就是把用户这句话准确归类。我的方案是让感知层走一条混合路由包含明确路径、标识符的提问先走规则抽取命中“查找”、“定位”这类词就走检索类意图表述模糊的则用模型做一次轻量分类输出结构化的请求对象。只在感知层花很少的代价就能避免后续把三类任务全部塞给同一套规划模版。3.2 五层在场景中的具体配置与参数这一段的配置可以直接作为参考底稿。记忆层在这个场景里的核心是代码库语义索引。我把仓库里的核心文档、模块说明、README、关键接口注释都做了分块和向量化分块大小按512个Token左右切重叠量控制在32个Token保证一个完整函数说明尽量不要被割裂。召回时TopK设8相似度阈值0.72。会话级短期记忆用一个容量为4000 Token的循环缓冲区“亲测”这个量能承载大约12到15轮正常问答的上下文超过之后就要触发摘要压缩。规划层设置最大拆分深度为6层最大执行轮数为10轮。遇到“检查最近三周的回归风险”这种大任务第一轮规划只拆出“列出提交记录、查看文件变更列表、读取CI报告、调用差异分析工具”四个一级子任务然后逐个展开执行。每个子任务完成后规划层都要把观察结果精简成一句话摘要追加到计划追踪单里。我习惯把追踪单放在上下文的最前面让模型每次都能快速看到当前进度不至于迷路。工具层在这个场景里注册了五类工具代码检索、文件读取、Git操作、构建执行、报告生成。每个工具都要配JSONSchema比如Git操作工具的参数要校验分支名是否包含非法字符构建执行工具要额外标注环境标签并限定只能在预置沙箱容器内运行。新仓库接入时只需要在配置中心加一条仓库元信息和对应的索引路径不改任何Agent代码。执行层统一做成一个带状态回调的执行器。每个工具返回时按照标准结构收拢ToolResult: - status: success / failed / timeout / rejected - data: 核心结果或错误摘要 - logs: 一段可选原始输出截断到2000 Token内 - duration: 执行耗时 - risk: 是否需要人工复核当构建执行器发现测试失败时status为failedlogs截断后写入短期记忆完整日志写到本地审计目录规划层随即决定是读取详细失败原因还是换一条路径重试。整个反馈回路非常清晰。3.3 一次完整交互的链路跟踪拿“帮我看下这个仓库的测试覆盖率为什么下降了”这个提问来走一遍。用户提交请求感知层标准化输入并识别出意图属性分析类型、目标对象为测试模块、时间范围因为没有指定默认最近一次发布。记忆层根据这个请求先从会话缓冲区里找历史提交记录再从向量索引里召回三份跟测试覆盖率相关的文档拼装成一个约800 Token的上下文包。规划层拿到上下文后生成计划先读取CI配置确认覆盖率统计口径再调Git操作工具查看最近提交然后定位提交中涉及测试用例改动的文件最后调用报告工具生成一份变更对比。工具层解析计划按顺序从注册表取出函数参数校验通过后交给执行层。执行层在沙箱容器里运行命令读取CI配置成功Git记录拉取成功覆盖率的差值和相关文件列表也拿到了。规划层做一次结果判断后认为目标已经达成直接跳过“报告生成”这个可选项开始组织最终答案。最后输出给用户的回复包含下降原因、相关提交、建议关注的文件清单同时把“覆盖率下降原因”的关键结论写入长期记忆下次再被问起就能直接命中。这个完整的链路走完大概需要12秒总Token消耗不到9000。如果架构不清晰同样的任务可能需要在一次长上下文里塞入所有仓库信息不仅慢结果还不稳定。五层架构在这里的价值体现得非常直观。4. 工程实现要点把架构落到代码聊完链路这一节讲代码层面怎么组织。我不会贴一个超大而全的实现那种代码读者基本不会真的去运行。这里介绍的是如何按五层架构组织工程以及几个核心数据结构的设计思路。4.1 分层代码组织与接口设计工程组织的核心思路是“每层一个包层间全靠消息”。我这里的实践方式是定义一套统一的消息对象各层之间不调用对方的内部方法只传递消息。类似这样dataclass class AgentMessage: msg_id: str # 链路追踪ID src: str # 来源层如 perception dst: str # 目标层如 planner msg_type: str # request / response / event payload: dict # 负载内容 created_at: float每层暴露的接口尽量控制在两三个方法。比如感知层对外提供一个process(raw_input) - AgentMessage记忆层提供recall(context) - AgentMessage和store(message) - AgentMessage规划层提供一个plan(message) - AgentMessage工具层提供resolve(message) - AgentMessage执行层提供run(message) - AgentMessage。这样做最大的好处是后续切模型、换向量库、加工具都不需要动消息结构。配置驱动使用时我会把模型名称、Embedding维度、窗口大小、工具启用列表全部收敛到一个YAML配置里避免把这些参数散落在业务代码中。4.2 几个核心数据结构的设计第一个要设计的是会话状态它负责记录整个会话的进度和状态。一个精简定义类似dataclass class SessionState: session_id: str request: AgentMessage plan: list[dict] # 子任务计划列表 step_index: int # 当前执行到第几步 context_trace: list[str] # 简要上下文轨迹 total_tokens: int status: str第二个是记忆索引结构。它封装了写入、查询、更新三部分纯外部依赖通过适配器替换。写入时检查内容质量查询时返回带相似度分数的候选片段更新时允许对已存记忆打标签。第三个是工具注册表。它的核心不是存一个函数指针就完事而是要保存完整的调用元信息。设计工具类时我会包含四个方法描述生成、参数校验、执行前钩子、执行后回调。参数校验尤其重要可以在模型给参数但还没真正执行前把所有非法情况拦截。4.3 可观测性与调试方法Agent系统调试难度远高于普通接口原因是它的行为包含模型推理的不确定性。我的做法有三个可追踪、可回放、可统计。可追踪是在每个AgentMessage上带traceId日志系统按traceId聚合这一条链路的所有环节出现任何异常可以直接看到是哪一层丢的。可回放是记录每一轮的关键输入输出摘要存成JSONL出问题后可以拿着这条链路反复调整模型提示词或参数做对比。可统计是给规划层、工具层、执行层各埋一个计数器关注核心指标比如规划轮数分布、工具调用成功率、参数校验拒绝率、上下文占用率。这些指标能很快暴露架构瓶颈上下文占用率长期在80%以上说明该扩短期记忆或优化压缩策略工具调用成功率偏低则多半是描述写得不准或工具本身不稳定。我认为任何一个Agent工程在写复杂功能之前都应该先把这套可观测性基础设施搭好。它相当于给整个五层架构装了一个仪表盘没有仪表盘的Agent就像闭眼开车极其危险。5. 常见问题与避坑指南这一部分直接把我在实践中遇到的高频问题列成速查表再附上一些有价值的经验总结。5.1 高频问题速查表现象大概率原因排查方向处理方案模型频繁选错工具工具描述含糊或场景说明不足检查工具注册表中的描述质量重写工具描述补充使用场景和禁用场景上下文很快塞满短期记忆窗口过大或检索TopK过大查看上下文占用率指标缩小窗口、调低TopK、提高摘要压缩频率任务执行多轮后跑偏规划层没有及时收敛查看该轮计划状态和预算标签设置最大轮数、增加反思机制、强制进入总结工具调用了但结果无效校验机制缺位复查执行层的ToolResult状态分布增加断言和输出关键词校验长期记忆里全是垃圾写入前没有质量筛选检查记忆写入钩子增加质量评分、过滤失败日志与临时状态新增工具后原有任务变慢工具数量过多干扰模型判断查看工具层可见性配置按会话场景限制可见工具列表5.2 几个值得记住的实操心得第一先跑通“严重受限”的最简闭环再逐步放开能力。很多人上手就做能力大而全的Agent结果上线后连最基础的流程都走不稳。正确做法是先只开放1个工具、锁死最大轮数等这个极简闭环跑顺了再一层一层加能力。我自己每次重构Agent也都是这么做的能省下大量调试时间。第二模型选型和架构要分开考虑。架构稳定了模型可以随便换但模型能力强弱直接决定规划层和记忆压缩这两块的上限所以升级模型时优先观察这两个环节的效果变化。反过来如果你发现模型表现不稳先不要急着换更贵的模型可以在记忆层、规划层做优化往往成本更低。第三工具参数校验要极其严格。模型生成参数天然有随机性即使上下文很长它仍可能突发生成非法路径、非法命令、极端数值。所有进入执行层的参数都要当成“外部输入”看待路径做越界检查、命令做黑名单检查、大小范围做上下限检查。这一条守住整个Agent系统的安全底线才是稳的。第四给Agent留“人工确认点”。不是所有任务都需要无人值守地自动执行到底。凡是结果会造成不可逆影响的操作比如修改数据库、合并代码分支、发送外部消息我都会在执行层设置一个人工确认步骤。多一次确认可能只多几秒时间但能挡住一大批严重事故。第五复盘每一个失败的轨迹。Agent每次跑偏都是宝贵的调试素材我会把失败链路的输入、计划、执行结果、错误消息完整保留定期用这些数据改进提示词、工具描述和校验规则。很多前期反复出现的坑如果当时不记录下来之后换一个场景会以类似形式再次出现。说到底五层架构不是某种教科书里高深的理论而是一套从实践里长出来的工程框架。它把Agent系统从一团难缠的“提示词杂烩”拆成了每个程序员都能独立掌控的五块积木。你不需要一次就建一个完美的系统只要记住每一层在解决什么问题、层和层之间的接口怎么定就能在项目迭代中不断把系统修得越来越稳。接下来哪怕你再去做多智能体协作、复杂工作流编排这套分层思想依然能帮你快速找到问题出在哪个环节。
阅读完成 · 觉得有帮助?