news 2026/10/24 4:45:58

AI Agent技术架构详解:从规划层到编排层的完整实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI Agent技术架构详解:从规划层到编排层的完整实现

最近经常有人问我,AI Agent到底该怎么搭才不算“玩具”。概念图看了不少,真到自己动手写一个能跑的Agent,还是容易一头雾水。我过去半年一直在做Agent方向的落地项目,从最早的单轮工具调用,到后来跑多步骤任务分解、记忆检索、多Agent协作,踩了不少坑。这篇文章把AI Agent的核心技术架构拆开来讲,尽量绕开花哨名词,讲清楚每一层到底负责什么、怎么实现、有哪些边界条件。正在做Agent开发或者准备选型的同学,应该能从里面拿到一些能直接用的东西,而不是只收获一堆新名词。

1. 先厘清Agent到底是什么,再谈架构

1.1 Agent不是“模型加提示词”那么简单

很多人会把“调用大模型API”和“Agent”画等号,这是最常见的误解。单次调用模型,本质是“输入一段文本,输出一段文本”,模型不会主动决定下一步做什么。而Agent是一个闭环系统:模型只是决策引擎,系统还要有任务拆解、外部工具调用、结果反馈、状态记忆和自我修正。

这么说吧,普通API调用像是“问路”,你问一句,模型答一句,答错了你也不知道。Agent更像“开车上路”,有导航规划路线,有方向盘调整方向,有仪表盘显示状态,遇到堵车还会绕路。模型只负责“判断下一步打多少方向”,但整个车能开到哪里,取决于架构把判断、执行、反馈、记忆这几个环节串得多顺畅。

所以讨论Agent技术架构时,先要跳出“提示词技巧”的层面,把注意力放在“循环”上。Agent的本质是一个循环系统:模型根据当前状态决定下一步动作,系统执行动作并更新状态,再把更新后的结果交给模型继续判断,直到目标完成或达到终止条件。

1.2 架构拆解的整体视角:核心五层

我习惯把Agent架构拆成五个层次,理解起来比较顺手:

  • 规划层:负责任务分解、制定执行步骤、决定下一步动作,是Agent的“大脑”。
  • 记忆层:负责保存对话历史、领域知识、操作结果,分为短期上下文和长期存储。
  • 工具层:把外部能力封装成可调用的接口,包括API、代码解释器、数据库、浏览器等。
  • 执行与反馈层:真正调用工具、等待结果、把执行结果结构化成模型能继续理解的内容。
  • 编排与调度层:维护整个循环的状态机,控制循环什么时候开始、什么时候暂停、什么时候结束,负责多Agent之间的协作。

五层之间不是堆叠关系,而是互相配合。规划层需要记忆层提供上下文,规划结果要通过工具层变成行动,执行结果又要通过反馈层流回记忆层,整个循环由编排层驱动。后面几节会逐一展开每一层的核心设计,以及我在实际项目里碰到的问题。

2. 规划层:Agent的决策中枢

2.1 任务分解与ReAct范式

规划层要解决的核心问题是“下一步该做什么”。最简单有效的范式是ReAct,也就是Reason与Act交替进行。模型不是直接输出最终答案,而是先输出一段思考过程,再输出一个具体动作,然后观察动作结果,再继续思考。这个过程把推理过程显式地写在上下文里,比直接让模型“一步到位”要稳定得多。

我在实际项目里明显感受到,一旦任务稍微复杂,比如“总结这批文档并生成周报”,直接让模型一次输出完整结果,经常丢三落四。而改成ReAct循环后,模型会先“扫描文档目录”,再“逐篇阅读”,最后“汇总生成周报”,每一步都有中间产物,出了问题也知道是哪一步断的。

规划层还需要任务分解能力。复杂目标会被拆成子任务树,比如“做一个市场分析报告”拆成“收集数据”“分析趋势”“撰写报告”三个子任务,每个子任务再细化成可执行的操作。拆得越细,每一步模型需要做的判断越简单,成功率越高,代价是token消耗和循环轮数都在增加。所以要控制拆解粒度,不要让一个简单任务被拆成几百个碎步骤。

2.2 规划器的实现细节与常见陷阱

实现规划器有两种路线。一种是用提示词让模型隐式规划,每条消息都让模型输出“下一步动作”,灵活但不可控。另一种是显式规划,先让模型输出完整计划,再逐步执行并标记计划状态,类似Plan-Track-Revise。我推荐复杂场景用显式规划,原因很简单:可观测性更好,计划挂在状态列表里,哪一步完成了、哪一步失败了,一眼就能看到。

规划层常见的坑有几个。第一,模型输出的计划与实际执行不一致,比如计划写“先查数据”,实际执行却直接去写报告。解决办法是在每次循环里让模型先输出一个计划步骤ID,系统校验它是否在未完成的计划列表里,不在就打回。第二,规划过长导致上下文被计划占满,没有空间装真正的执行结果。解决办法是对计划做精简,只保留当前步骤和后续几步摘要,不保留完整的千字计划。第三,执行失败后模型不知道回溯,总是按原计划继续,越走越偏。所以规划层必须允许修订计划,发现当前步骤连续失败两次,就要暂停并重新生成后续计划。

3. 记忆层:让Agent不“失忆”

3.1 短期记忆与上下文窗口管理

Agent的短期记忆基本就是当前对话上下文。但大模型上下文窗口是有限的,Agent跑几十轮之后,历史消息很容易撑爆窗口。这里不能简单“删掉前面的消息”,否则模型会丢失关键信息。我常用的做法是三级管理:

  • 保留最近几轮完整消息,保证对话连贯性。
  • 对更早的历史做摘要,把长对话压缩成一段“截至目前的关键结论”。
  • 与当前任务无关的细节直接丢弃,不占空间。

具体操作时,摘要不是一次性把所有历史塞给模型让它总结,而是在每一轮结束后,增量更新摘要。比如新完成一步,就把这一轮的goal、action、result浓缩成一句话追加到摘要里。这样短期记忆的维护成本很低,上下文也不会无限制膨胀。

3.2 长期记忆与检索增强的取舍

长期记忆解决的是“跨会话”和“跨任务”的知识复用。最常见的实现是把历史任务的关键信息写入向量库,需要时做相似度检索。但这里有个容易被忽视的问题:检索返回的是片段,不是完整事实,片段如果不准确,反而会把模型带偏。

我把长期记忆分成三类来管。一类是用户偏好和配置,比如“用户喜欢简短回复”“周报模板用那个固定的”,这类数据用结构化存储,检索时直接精确读取,不走向量。一类是任务结果沉淀,比如上次任务生成的报告摘要,这类数据适合向量检索,但检索时一定要带上来源和可信度标签。还有一类是临时笔记,比如模型中途发现的线索,这类数据优先级最低,检索时甚至可以忽略。

长期记忆最大的坑是“记忆污染”。检索出来的内容跟当前任务只是表面相关,模型却当成可靠事实写进答案,最后产出垃圾。我的解决办法是给记忆条目打标签,包括时间、来源任务、可信度评分;检索后先让模型判断“这段记忆是否与当前问题冲突”,冲突就用当前输入作为最高优先级,必要时把记忆内容降级为“参考线索”而不是“事实依据”。

4. 工具层:Agent的手和脚如何接上世界

4.1 工具注册、工具描述与函数调用

Agent不可能只在脑子里转,真正干活要调用工具。工具层不是简单把API地址发给模型,而要做一套完整的注册机制。每个工具要声明:名称、功能描述、输入参数规范、输出格式、权限级别、超时时间。模型看到的是这些工具的结构化描述,而不是底层代码。

目前主流的实现方式是函数调用(Function Calling)。模型收到用户问题和工具列表后,输出一个结构化的调用意图,比如“调用天气查询接口,参数城市等于北京”。系统解析这个结构,找到对应的工具,执行后再把结果返回给模型继续处理。

这里有一个关键细节:工具描述写不好,模型就选不对工具。不要只写“get_data”,要写清楚“get_data:根据日期范围获取销售明细数据,返回字段包括日期、金额、订单数;参数start_date和end_date是必填”。我见过太多次模型选中错误工具,不是模型笨,而是工具描述写得太模糊,让模型靠猜。描述里加上参数格式示例和典型使用场景,选择准确率会明显提升。

4.2 工具选择策略与安全边界

当工具数量超过20个时,让模型每次在所有工具里选一个,非常容易选错。我的经验是需要做个前置路由。可以按业务域分成几组,比如数据类工具组、内容生成工具组、系统操作工具组,先让模型判断当前任务属于哪一组,再在组内选具体工具。分组之后,每组工具数量控制在5到7个,模型选择压力小很多。

安全边界是工具层不能妥协的部分。凡是涉及发送消息、删除数据、修改线上配置、扣费这类敏感操作,一定要加人工审批环节。系统不能直接让Agent调用这些工具,而是生成一个待审批事件,推送给用户,用户确认后才执行。这里要注意,审批不是只拦一次,而是每次敏感操作都要拦。有些Agent第一轮通过了审批,后续轮次模型又试图自动调用相同工具,如果系统放行,风险极高。

工具调用还要考虑异常处理。网络超时、返回格式不合法、权限不足,这几种情况都要反馈给模型,但反馈信息要简洁。我在反馈时不会把一长串JSON错误堆给模型,而是转成一句话:“工具调用失败:目标接口返回403,可能没有权限,建议更换查询方式”。模型拿到这个反馈就能做出有效调整,而不是看着一堆日志发呆。

5. 行动与反馈层:从决策到闭环

5.1 执行器的分类与观测回传

规划层决定“做什么”,工具层提供“能做什么”,真正动手的是执行层。执行器可以是API客户端,也可以是代码解释器、浏览器自动化脚本、数据库查询器。不同执行器有不同的适配重点。API客户端要做参数校验和响应解析;代码解释器要注意运行时隔离,不能让Agent生成的代码直接跑在宿主机上;数据库查询器要限制查询超时和返回行数,防止一次查询拖垮数据库。

执行结果回传给模型时,不能简单把原始返回内容丢回去。要做两层加工:第一层,提取核心结果,把长文本摘要成模型最关心的信息;第二层,标注执行状态,包括成功、失败、超时、部分成功。模型拿到“查询成功,共返回3条数据,第一条月份1月金额10万”这种结构化内容,比拿一屏幕原始JSON要可靠得多。

我踩过一个坑:工具返回了大量数据,比如查询了一张1000行的表,直接把全部数据塞进上下文,不仅token爆炸,模型还会迷失在细节里,抓不住重点。后来我改成“自动摘要+按需下钻”的策略:默认只返回统计信息和前几条示范数据,模型如果需要更多细节,再调用专门的“分页查询”工具继续取数。这样既省token,又保持可控。

5.2 反思与自我修正机制

Agent不能一路莽到底,必须有反思机制。反思的本质是让模型在每次动作完成后,评估“这个动作有没有达成预期目标”,如果没有,分析原因并调整下一步计划。常见做法是self-refine,也就是让模型扮演执行者和批评者两个角色。

我通常在循环里加入一个轻量反思步骤:每进行2到3步,就生成一条反思摘要,判断当前进度是否合理。比如任务要求“找出最近一个月销售下滑的原因”,Agent第一轮查了总销售额数据,发现下滑20%,第二轮执行者是“直接生成结论”,这时候反思应该发现:还没有拆解渠道和品类数据,直接下结论太草率,应该补充查询。有了这一步,Agent的质量立刻上一个台阶。

反思也要防走火入魔。模型在失败后反复自我修正,有时候会绕进死胡同,同一个错误改来改去,消耗大量token就是不换方向。所以反思步数必须设上限,建议同一目标尝试3次仍无进展,就触发人工求助,或者切换另一种完全不同的工具组合。记住,反思的目的是止损,不是让Agent在错误路上越走越远。

6. 编排与调度:多步骤流程的黏合剂

6.1 单Agent循环与状态机设计

整个Agent的运行核心是编排层维护的循环。最简单的实现是while循环:只要任务未完成且步骤数小于上限,就执行“让模型生成下一步决定-调用工具-回传结果”。但生产环境不能写这么简陋的循环,要设计成状态机。

我的状态机至少有这几个状态:IDLE(空闲)、PLANNING(规划中)、RUNNING(执行中)、WAITING_INPUT(等待用户输入)、TOOL_CALL(工具调用中)、END(结束)。每个状态定义清晰的进入条件和退出条件。比如状态是TOOL_CALL时,系统必须要在超时时间内收到工具返回,否则进入异常分支,把超时信息反馈给模型重新决策。状态机的优势在于可控:可以随时暂停、恢复、打断,还能记录每一步的状态变迁日志,排查问题非常方便。

状态机还需要支持事件驱动,不一定是模型每走一步都同步等结果。有些耗时操作,比如“上传文档并解析”,可以先把任务挂起,等回调事件再继续。这样Agent不会傻等一个长时间任务,整体吞吐量高很多。我们在实际项目里用事件总线传递“工具完成”“用户回复”“审批通过”这类事件,Agent根据事件状态唤醒对应会话。

6.2 多Agent协作与人工介入点

复杂任务往往不靠一个Agent从头做到尾,而是多个Agent分工协作。多Agent架构主要有几种模式。一种是管道模式,上游Agent产出结果,下游Agent继续加工,比如“数据分析Agent”把数据整理好,“报告Agent”再负责写作。一种是主从模式,一个主控Agent负责任务拆解和调度,把子任务分给不同专家Agent,再汇总结果。还有一种是群聊模式,多个Agent在共享消息通道里讨论,适合头脑风暴类任务,但容易发散,收敛成本高。

多Agent协作最要紧的是消息规范。所有Agent之间的通信必须走结构化消息,至少包含消息类型、发送方、接收方、内容、关联任务ID。不能用卡通对话式文本随意传递,否则下游Agent无法稳定解析。我见过一个跨Agent项目,上游Agent输出“我把结果放这里了”,下游Agent完全不知道“这里”在哪。

人工介入点是编排层必须预留的。关键决策前后、敏感工具调用前、连续失败恢复后,都要设计暂停点。人工介入不是弹个提示框就完了,要把当前上下文、候选方案、决策背景完整展示给用户,让用户能快速理解并做出选择。一个好的介入设计,能救回大量原本注定失败的Agent任务。

7. 极简Agent循环的实操实现

7.1 代码骨架:一个可运行的规划-工具-反思循环

理论讲再多,不如动手跑一个最小实现。下面我用Python写一个不依赖特定框架的极简Agent循环,核心是让模型输出“思考-动作-输入”的JSON结构,系统解析后执行工具并回传结果。这里使用抽象的llm.chat接口,你可以对接任意大模型服务。

import json import re from typing import Any, Callable # 工具注册表:名称 -> 处理函数 TOOL_REGISTRY: dict[str, Callable[..., str]] = {} def register_tool(name: str): def decorator(func: Callable[..., str]): TOOL_REGISTRY[name] = func return func return decorator # 一个极简工具示例:查当前时间戳 @register_tool("get_current_time") def get_current_time() -> str: import datetime return datetime.datetime.now().isoformat() def build_system_message() -> str: tools_desc = "\n".join( f"- {name}: {getattr(func, '__doc__', '无描述')}" for name, func in TOOL_REGISTRY.items() ) return ( "你是AI Agent。你必须按以下格式输出:\n" '{"thought": "你的思考", "action": "工具名", "action_input": "参数"} \n' "或者当任务完成时输出:\n" '{"thought": "总结", "finish": "最终答案"} \n\n' "可用的工具:\n" + tools_desc ) def run_agent( user_goal: str, llm: Any, messages: list[dict] | None = None, max_steps: int = 8, ) -> str: if messages is None: messages = [{"role": "system", "content": build_system_message()}] messages.append({"role": "user", "content": user_goal}) for step in range(max_steps): response = llm.chat(messages=messages, temperature=0.2) content = response.strip() # 尝试解析模型输出 try: data = json.loads(content) except json.JSONDecodeError: messages.append({ "role": "user", "content": "你的输出不是合法JSON,请重新严格按格式输出。" }) continue # 判断是否结束 if "finish" in data: messages.append({"role": "assistant", "content": content}) return data["finish"] action = data.get("action") action_input = data.get("action_input", "") thought = data.get("thought", "") if action not in TOOL_REGISTRY: messages.append({ "role": "user", "content": f"工具 {action} 不存在,可选工具是:{list(TOOL_REGISTRY.keys())}" }) continue # 执行工具并捕获异常 try: observation = TOOL_REGISTRY[action](action_input) except Exception as exc: observation = f"工具执行失败:{exc}" messages.append({"role": "assistant", "content": content}) messages.append({ "role": "user", "content": f"行动结果:{observation}\n请继续思考下一步。" }) return "达到最大步骤数,任务未完成。" # 使用示例(伪代码): # llm = YourLLMClient() # answer = run_agent("现在几点?帮我查一下", llm)

这段代码看起来很简单,但它包含了一个Agent循环的全部关键元素:系统提示词给出动作规范、工具注册表暴露外部能力、解析与校验防止模型乱来、执行结果回传形成闭环、最大步数控制止损。

7.2 运行要点与关键参数调节

实际跑这个循环,你会发现几个问题立刻浮现。第一,模型输出的JSON经常不标准,有时候会把完整格式包在Markdown代码块里,所以解析时要做容错处理,去掉多余的```标记,甚至用正则找到第一个{到最后一个}。第二,temperature不能设太高,我一般设置在0.2以下,否则模型会输出花哨但不稳定的计划。第三,动作参数是字符串,工具函数需要自己解析成typed参数,这里可以补充一个参数Schema校验模块,防止模型传错格式。

还有两个运营级参数。一个是max_steps,它决定了单个任务最多循环多少轮,我建议首次调试设成5,因为大部分简单任务5步内能完成,如果超过了,更可能是规划层或工具层出了问题,而不是模型能力不够。另一个是上下文长度预算,每轮循环都会增加两条消息,所以循环轮数越多,上下文越大,要在循环里做消息压缩。上面代码没有展示压缩逻辑,实际部署时我建议在步骤数超过6后,把早期消息折叠成摘要,否则很快撞上模型窗口上限。

跑通这个最小循环之后,可以逐步加功能:加工具描述、加反思步骤、加状态机、加多Agent消息协议。我最初也是从这种骨架开始,一点点把生产级的公共模块搭起来的。没有这个骨架,直接套用重型框架,出了问题你根本不知道该看哪一层。

8. 生产环境里的高频问题与排查思路

8.1 高频问题速查表

实际生产环境中,Agent跑起来之后的坑远多于写Demo时的坑。我整理了一张速查表,覆盖我遇到过的高频问题:

问题现象可能原因排查思路
Agent循环不停,token费用飙升缺少终止条件或模型总在重复动作检查max_steps、任务完成判断逻辑;同一动作连续出现两次时主动打断
上下文长度超限报错循环轮数太多或工具返回大段数据增加消息摘要,限制工具返回行数,设置按步骤压缩上下文的策略
模型调用错误的工具工具描述含糊或工具数量过多重写工具描述,加入典型场景示例;拆分工具分组,先路由再选择
工具调用一直失败参数格式不匹配、权限问题、网络超时记录失败原因并回传模型;增加参数校验层;对超时工具做重试和降级
Agent说完成了,但结果不对缺少验证器,模型产生幻觉增加目标验证节点,用程序判断产物是否满足条件;必要时人机确认
多Agent之间消息理解错误消息格式不规范、缺少任务ID统一消息协议,强制带任务上下文;通信内容只用结构化字段
问题被模型绕回原路反思机制设计不当增加“连续失败N次则切换方案”规则;引入外部观察者介入

8.2 我惯用的排查套路与观测建议

排查Agent问题,我第一件事永远是看trace。所以从第一天起就不要裸奔,每个Agent任务要输出结构化日志,里面至少包含:全局唯一的trace_id、当前步骤号、模型输入的上下文长度、模型输出的动作、工具名、工具入参、工具返回摘要、耗时和成本。没有这些信息,Agent出了问题就跟查一个没有日志的服务一样痛苦。

其次是复现能力。Agent不是纯确定性程序,模型输出的概率性导致同一个任务每次结果都不同。我在本地会准备一组固定的测试用例,覆盖正常场景、边界场景、失败场景,每次修改架构后把整组用例跑一遍,记录每一条的通过率和平均步数。通过率变化最能反映架构改动是好是坏。

最后,我强烈建议在架构里埋一个“外部评估器”。不要只依赖模型自己判断任务是否成功,尤其是生成类任务,比如“写一份方案”,模型自己说“写完了”不等于方案符合要求。外部评估器可以用规则检查必含要素,也可以调用一个更便宜但维度不同的模型来打分。评估结果反馈到循环里,比纯靠模型自信要可靠得多。

根据我个人经验,Agent架构做得再复杂,真正决定能否落地的其实是“边界控制”。控制循环轮数、控制上下文长度、控制工具权限、控制失败重试次数,这些看起来不性感的细节,恰恰是生产级Agent和Demo Agent的分水岭。如果你刚开始搭Agent,别急着上多复杂的设计,先跑通一个带完整日志、带步数上限、带人工介入的最小闭环,然后再一层层加规划、记忆、反思和多Agent协作。这个顺序稳定可靠,少走弯路。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/24 4:45:57

当内容被“漂白”:AI写作时代如何守住真实底线?

开篇:当"漂白"成了内容行业的新手艺鸡爪加工行业里有句老话——好的泡发鸡爪不需要双氧水。真正新鲜的原料,清水泡足时间,口感自然脆爽。但总有些商家图省事,用双氧水把发黄发黑的鸡爪一泡,白是白了&#xf…

作者头像 李华
网站建设 2026/10/24 4:45:56

PFC2D 5.0热力耦合机制:温度如何实时软化接触刚度并触发岩石热损伤

简介:本资源是一套面向岩石力学研究者与工程仿真初学者的PFC2D5.0热力耦合专项实践代码包,聚焦于空心圆盘岩样在轴心受热条件下的热损伤演化模拟,解决离散元方法中温度场-应力场双向耦合建模难、案例复现门槛高的实际问题。压缩包共10个文件&…

作者头像 李华
网站建设 2026/10/24 4:45:53

含储能微网双层能量管理模型:MPC日前调度与日内滚动实现

这段时间我把手头那个含储能微网的双层能量管理模型用MATLAB完整搭了一遍,核心控制器是模型预测算法(MPC)——上层做日前调度,下层做日内滚动修正。这个模型的目标很朴素:在电价、光伏、负荷都不完全确定的情况下&…

作者头像 李华
网站建设 2026/10/24 4:44:32

STM32 HAL库外部中断与回调函数踩坑笔记:从按键失灵到稳定处理

做嵌入式这一年多,我对外部中断的认识,是被一个“按键偶尔没反应”的现象逼出来的。很多教程会把STM32的HAL库外部中断讲得很轻松:配置一下GPIO、开一下NVIC、写个回调函数就完事了。可真到项目里你会发现,中断进不进得来是一回事…

作者头像 李华
网站建设 2026/10/24 4:44:01

SpringBoot集成Thymeleaf模板引擎完整实战指南

1. 为什么要在SpringBoot项目里用Thymeleaf先聊聊我自己的经历。做Java后端这几年,刚开始写页面用的还是JSP,后来前后端分离慢慢流行,大家张口闭口就是Vue、React。但实际做项目时你会发现,并不是所有场景都适合搞前后端分离。后台…

作者头像 李华
网站建设 2026/10/24 4:42:42

Android本地TensorFlow Lite图像分类Demo全链路实践

简介:这份资源是一个面向 Android 开发者和机器学习入门者的完整工程 demo,演示如何在手机端借助 TensorFlow Lite 加载训练好的模型完成图像分类推理。适合已具备基础 Android 开发能力、希望把深度学习模型真正部署到移动设备上的学习者,用…

作者头像 李华