尧图精选

Agent-Native系统设计实战:把智能体作为架构核心

🕒 发布时间:2026/9/28 16:40:59 📁 来源:尧图网络
过去一年里我经手了不少LLM应用项目从简单的问答机器人到复杂的多工具业务系统过程中有个词出现频率越来越高agent-native。这个词听起来很高级但拆开看就是一句话把智能体当作系统的头等公民来设计而不是把它塞进旧架构里当一个外挂模块。这篇文章我想用做项目的视角把这个概念讲透顺便分享一些落地时真正用得上的经验和坑。这篇内容不是概念科普也不是框架广告而是围绕怎么判断一个系统是不是agent-native怎么从零搭一个agent-native系统哪些地方最容易翻车这三件事来写的。适合正在做LLM应用开发、想从传统RAG或workflow方案往Agent方向迁移的工程师也适合刚接触这个领域、想建立整体判断框架的产品和技术负责人。1. agent-native到底在说什么1.1 从能用到以智能体为中心native这个词在软件工程里其实有很明确的历史含义。就像cloud-native不是说把虚拟机搬到云上而是从架构设计的第一天就按云的弹性、不可靠网络、水平扩展这些特性来设计系统一样agent-native也不是说给现有系统加一个Agent模块而是整个系统的数据结构、权限模型、交互协议、运行机制从底层就是围绕Agent如何思考、如何行动、如何被约束来设计的。举个具体的例子。传统SaaS系统里用户通过表单提交一个请求后端走一个定义好的状态机每一步都是人写死的分支逻辑。这时候你往里面塞一个Agent充其量是替用户填了表单或者把用户意图映射到某个固定的API调用上。这不算agent-native。真正的agent-native系统用户直接提交一个目标比如把这周的异常订单汇总成报告发给财务并抄送相关销售负责人系统里的Agent自己去拆解步骤、调工具、判断中间结果、必要时问人最后把目标闭环掉。两者的差别不是有没有用大模型而是决策权放在哪里。传统架构里决策权在开发者写的流程代码里agent-native架构里决策权在Agent的运行循环里开发者负责设计边界、提供工具、定义护栏。这是一次非常本质的权力转移。1.2 别把这三件事混为一谈很多人在讨论agent-native时会把它跟另外几个概念搅在一起这里先花点时间掰清楚。第一agent-native不是workflow自动化。传统RPA和工作流引擎是剧本式的每个分支、每个条件都是预设的好处是结果可控坏处是遇到剧本没覆盖的情况就死掉。agent-native是目标式的Agent自己规划路径绕过障碍甚至在计划失败时换一条路。两者的边界在于如果你的业务流程能用一张流程图完整画出来那你根本不需要agent-native如果画不出来或者画出来之后维护成本已经超过开发成本那才是Agent真正该上场的地方。第二agent-native不是chatbot换皮。对话机器人解决的是交互入口问题它的核心是意图识别和话术生成。agent-native解决的是目标执行问题核心是行动能力。很多对话机器人背后的状态机比普通Web应用还死板它只是在对话层套了一层LLM跟以Agent为中心设计相去甚远。判断标准很简单用户能委托给系统一个多步骤任务并且系统能在无人干预的情况下推进执行这才算迈进了agent-native的门槛。第三agent-native不是传统软件LLM接口。在传统系统里加一个/agent/ask接口让LLM帮你生成一段SQL或者一个JSON响应这只是把模型当成了一个组件。agent-native关心的是你的数据库表结构是不是为Agent的任务和轨迹设计的你的权限模型能不能支撑Agent在每一步动作上做细粒度检查你的日志系统能不能还原Agent每一步的思考依据这些问题的答案才决定了一个系统是不是真的agent-native。为了更直观我列一张对比表。对比维度传统应用 LLMAgent-Native用户如何触发能力点击、表单、命令直接提交目标系统主动性的来源代码分支写死Agent自主规划并调用工具状态保存在哪里数据库业务表Agent任务表 轨迹记录 记忆层能力扩展方式发版 加API注册新工具 / 新技能失败可控性确定性流程失败点明确概率性决策需靠护栏和观测兜底迭代重心逻辑代码和页面工具质量、提示词策略、评估集这张表不是要否定传统架构而是明确告诉你如果你的系统还在用表单驱动API编排的逻辑那加再多的LLM调用也只是装饰不是agent-native。2. 为什么现在才谈agent-native从架构演进看必然性2.1 三代LLM应用的演进逻辑我习惯把LLM应用的架构演进分成三个阶段这样比较容易理解agent-native为什么会在这个时间点出现。第一代是Prompt Engineering阶段。那时候大家觉得大模型万能把问题写清楚就能得到答案。这个阶段的核心边界是上下文窗口模型能力完全取决于输入质量业务逻辑基本没有谁都能用谁也做不深。第二代是RAG Function Calling阶段。为了解决幻觉和实时性问题人们开始把外部知识库接进来把业务能力包装成函数给模型调用。这个阶段第一次把模型和工具连接起来但流程依然是开发者写死的先做意图识别再决定走检索还是调接口最后生成回复。模型的作用被限定在几个预设的节点里像是一个能力很强的零件但整个机器还是人设计的。第三代就是Agentic系统也就是agent-native真正站稳脚跟的阶段。模型不再只被当作零件而是成了运行时的核心调度器。它决定调用哪些工具、按什么顺序调用、调用失败后怎么办、是否需要向用户确认整个规划-行动-观察的循环由模型和一套运行时共同驱动。这已经是完全不同的软件形态你不可能在旧架构上打补丁打出来必须从设计理念上重来。2.2 四个逼着大家走向agent-native的现实压力理论演进是一回事真正推动行业转向agent-native的是四个非常现实的压力。第一个压力是工具数量爆发。一个中等规模的企业内部系统可能有几十上百个API接口和数据库操作。用人工编排的方式把这些API串成业务流程逻辑复杂度和维护成本是指数级上升的。这时候更合理的方式是把每个API描述成Agent能理解的工具让Agent自己按需组合。开发者写一个工具描述的成本远低于写一条完整业务流程的成本。第二个压力是任务复杂度上升。真实的用户请求从来不是查个天气这种单步任务而是帮我对比三个供应商的报价把低于预算的挑出来顺便看看他们过往交付记录这种多实体、多步骤、多条件判断的复合任务。这类需求在传统系统里要写很长的胶水代码而且换个问法就又要改。Agent天然适合这类开放式任务。第三个压力是交互模式的改变。用户越来越希望直接说我要什么而不是去学习你的系统怎么操作。这意味着产品逻辑要从命令式交互转向目标式交互。一旦产品层开始支持目标式交互后端就必须有一个能承接目标、拆分任务、执行动作的运行时这个运行时本质上就是agent-native架构。第四个压力是生产环境的失败容忍度在降低。LLM应用早期大家还能容忍一些玩具Demo但一旦接入生产业务就要求每一步可观测、可回滚、可审计。传统黑盒式的模型调用完全不合格你必须有一个围绕Agent设计的日志系统、轨迹回放机制、人工审批节点。这些机制不是附加功能而是架构的组成部分只能在agent-native的设计框架里自然生长出来。四个人压力看下来你会发现agent-native不是某个公司的营销词而是LLM应用复杂度到一定阶段后工程上自然收敛出的答案。3. 一个agent-native系统长什么样核心组成与设计要点3.1 五大核心模块我在实际项目中总结下来一个完整的agent-native系统无论用什么框架底层都离不开五个模块。缺了任何一个系统要么跑不起来要么不敢跑。运行时Runtime是整个系统的心脏。它维护Agent的执行循环负责把模型输出的文本解析成可执行的动作再把动作的结果回传给模型。这个循环没有高级技巧但工程上最容易在细节上翻车比如怎么处理模型输出格式不稳定、怎么控制循环次数、怎么处理工具调用超时。后面我会专门展开讲。工具注册中心Tool Registry是Agent能力的边界。每个工具都包含名称、描述、参数Schema、执行函数、权限要求。这里的原则是模型能看到的工具描述决定了Agent能力的上限所以工具描述的质量直接等于系统能力的质量。很多项目一开始把工具描述写得很随意结果Agent经常选错工具这本质上不是模型问题而是你的说明书写得太烂。记忆层Memory管理Agent的状态。它分两块一块是短期工作记忆也就是当前任务上下文里放得下的信息另一块是长期记忆比如从历史对话中沉淀的用户偏好、业务规则、已完成任务的摘要等。设计记忆层最忌讳的是什么都往上下文里塞要像人工作一样跟当前任务相关的放桌面暂时用不到的归档到抽屉里。权限与合规层Guardrails是agent-native系统敢于上生产的底气。Agent每执行一步动作之前都要过一遍校验规则。比如这个工具当前用户有没有权限调用这个操作是一次只读查询还是写操作金额超过多少必须人工确认这套东西在传统系统里是散布在业务代码里的在agent-native里必须收敛成统一的一层否则你根本没法追责。可观测性栈Observability解决的是它到底干了什么的问题。每个Agent运行实例都要记录完整的轨迹模型每步的思考内容、选择的工具、传入的参数、返回的结果、消耗的token数、耗时。这些数据一方面是用来排查问题另一方面是用来迭代提示词和评估集。我见过太多团队倒在这一步Demo能跑但一出错就是黑盒完全没法定位。3.2 数据模型应该怎么设计传统业务系统的数据模型是围绕人怎么操作来设计的有用户表、订单表、流程实例表。agent-native系统的数据模型多了一个核心实体就是任务。这个任务不是传统的工作流实例而是Agent运行时的真实映射。我一般至少会为Agent维护下面这三类数据dataclass class AgentTask: task_id: str goal: str # 用户提交的原始目标 plan: list[AgentStep] # 模型生成的步骤计划 status: str # pending / running / need_human / done / failed current_step: int created_at: str updated_at: str dataclass class AgentStep: step_id: int tool_name: str # 本步骤打算调用哪个工具 parameters: dict # 入参 expected_result: str # 模型预判这个步骤会得到什么 actual_result: dict # 实际执行后拿到的结果 status: str # pending / running / succeeded / failed / skipped retry_count: int我特别强调两个字段。一个是expected_result让模型在调用工具前先描述一下它预期得到什么这个字段在后续对比实际结果时很有用能帮助系统判断模型是不是规划偏了。另一个是retry_count几乎所有Agent都会遇到工具调用失败允许模型重试但必须限制次数防止它在一个错误动作上反复打转。任务之外还要有轨迹表记录Agent每一步的思考原文和行动结果。这个表主要用于调试和审计。我给客户的建议是轨迹表只append不update每个Agent运行实例从头到尾是一条完整的记录流这样出问题才能回放。至于长期记忆一般用向量库存语义化的摘要加上一张结构化的用户偏好表就够了不需要搞得很复杂。3.3 记忆与状态的取舍逻辑记忆设计是agent-native系统里最考验功力的一环。我的经验是一个原则能用结构化数据表达的就不要塞进上下文需要模型感知的才放进上下文。打个比方。短期记忆就像你的桌面长期记忆像档案柜。正常人在桌上放当前任务需要的文件做完一个任务就归档清理不会让桌面积累十年份的打印纸。但很多Agent系统真的会让上下文里堆积十几个工具的执行结果、几十轮对话历史、还有一堆系统提示词最后模型根本不知道该重点看哪部分效果急剧下降。实操中我的做法是每完成一个步骤立即把执行结果做一个结构化摘要存到任务表或数据库里只把摘要放回上下文。比如Agent调了一个查询订单详情的工具返回了50行数据模型不需要逐行阅读它需要的是这50行数据里有3笔异常订单金额分别为XXX。这个摘要工作可以让模型自己做也可以配合一些规则抽取。做完之后上下文长度就控制住了模型注意力也更集中。4. 落地实操从零开始搭一个agent-native最小系统4.1 技术选型什么时候用框架什么时候自己写搭agent-native系统第一步就是技术选型。我把市面上的方案分成三条路。用LangChain / LangGraph这类通用Agent框架。适合你还在探索阶段、需要快速验证想法的情况。这个框架生态成熟内置了大量工具接入和记忆方案但坑也很明显就是抽象层级太多出了问题很难定位到底是框架的问题还是你代码的问题。我自己在复杂生产项目里用LangGraph的时候会尽量只依赖它的核心图执行能力其他都自己封装。用LlamaIndex这类数据相关的Agent框架。如果你的场景强依赖私有数据比如企业内部知识库问答、文档分析LlamaIndex在数据接入和检索这层的抽象做得很好。但它的Agent能力相对偏薄复杂多工具编排还是会回到LangGraph或者自己写的路上来。完全自己写一个ReAct循环。很多人觉得这很笨但我恰恰建议**如果你的核心业务对稳定性要求很高、或者你要做的是通用平台而不是单一场景Demo最少先把核心循环自己写一遍。**因为只有亲手实现过模型输出解析、工具调用、结果回填这条完整链路你才能理解框架帮你做了什么、掩盖了什么出问题的时候你才知道从哪里下手排查。选型判断表可以这么用场景推荐方案理由快速验证Agent ideaLangGraph 少量自定义迭代快社区方案多企业内部知识问答LlamaIndex 自研工具层数据接入成熟复杂业务系统 / 多工具平台自研核心循环 框架只做辅助控制力强利于长期维护多Agent协作自研通信层 LangGraph做底层编排通信协议不能受框架限制4.2 核心执行循环的骨架代码如果不借助任何框架一个agent-native系统最核心的循环就是观察-思考-行动的无限重复。我把这个循环写成极简伪代码每一行都能解释清楚。def agent_run(task: AgentTask, tool_registry, llm, max_steps10): # 维护对话上下文初始放系统提示词和用户目标 messages build_initial_messages(task.goal) completed False for step in range(max_steps): # 1. 让模型基于现有信息做决策 response llm.chat(messages) # 2. 解析模型的回复它可能是在说话也可能是想调用工具 action parse_action(response) # 3. 如果模型认为任务已结束就退出 if action is None: completed True break # 4. 从注册中心找工具做权限和参数校验 tool tool_registry.get(action.tool_name) check_permission(task.user_id, tool) validated_params validate_schema(action.parameters, tool.schema) # 5. 执行工具把结果变成模型能读的文本 raw_result tool.execute(validated_params) observation summarize_result(raw_result) # 6. 把模型这步的思考、动作、观察结果都写回上下文 messages.append({ role: assistant, content: response }) messages.append({ role: tool, tool_call_id: action.tool_call_id, content: observation }) # 7. 同步记录轨迹方便审计和排查 record_trace(task.task_id, step, response, action, observation) return completed这个骨架看起来简单工程上真正的难点在三个地方。一个是parse_action你要处理模型偶尔输出不符合格式的情况。另一个是validate_schema这一步是防幻觉的关键模型编参数的情况比你想象的多必须用JSON Schema之类的东西硬校验。还有是summarize_result我之前提过工具返回冗长结果时一定要压缩之后再喂回给模型不然上下文很快爆掉。很多成熟的Agent框架本质上都是这个循环的工程化包装。理解了这一层你就不会对框架产生依赖感因为你知道它内部跑的就是这些事。4.3 工具描述的质量直接决定系统智商我在实际项目中反复验证过一个观点**在agent-native系统里工具描述的重要性远高于模型本身的选型。**同一个模型给一份精心设计的工具描述和给一份随便应付的描述任务成功率能差出一大截。以查询机票价格这个工具为例。糟糕的描述是这样的{ name: search_flight, description: 查询机票价格, parameters: { type: object, properties: { from: { type: string }, to: { type: string } } } }这个描述的问题在于参数语义模糊模型不知道from要的是城市名还是机场三字码缺少时间参数模型就不知道该填哪一个没有说明返回格式模型拿到结果后可能不知道怎么解读。Agent会在这个工具上反复出错。一份合格的描述至少应该包含这几个要素{ name: search_flight_price, description: 查询指定日期、指定航线的最低价和经济舱/商务舱价格。当用户询问机票、航班、出行费用时使用。注意from/to必须是IATA机场三字码如北京首都国际机场是PEK。, parameters: { type: object, properties: { from: { type: string, description: 出发地IATA机场三字码例如PEK }, to: { type: string, description: 目的地IATA机场三字码例如SHA }, date: { type: string, description: 出发日期格式YYYY-MM-DD }, cabin: { type: string, enum: [economy, business, first], description: 舱位等级默认economy } }, required: [from, to, date] }, returns: { description: 返回结果包含最低价、所属航司、直飞或中转信息价格单位为人民币元 } }看到差别了吗好的工具描述本质上是给模型一份用户手册告诉它什么时候用、怎么填参数、拿到结果后是什么意思。写工具描述时我有个心法**假设使用者是一个聪明但没有业务背景实习生你写的说明书要让他能独立完成工作。**用这个标准去衡量大多数项目的工具描述都远不合格。5. 我踩过的坑agent-native开发避坑手册5.1 上下文窗口爆炸Agent越来越迟钝很多团队会在项目运行一周后发现自己接入的模型输出质量明显下降延迟也在涨。排查之后发现是上下文越攒越长。Agent执行了二十多个步骤每一步的工具返回结果都原封不动塞在上下文里甚至还有几轮跟用户的闲聊模型已经分不清重点了。解决这个问题我有一套组合拳。第一工具返回结果一定要做结构化摘要而且是保留结论、丢掉明细的摘要。第二把对话历史做分段管理超过一定轮数就把早期的内容压缩成摘要必要时把原始记录存到数据库里备查。第三如果任务特别长考虑引入小模型做摘要、大模型做决策的分层让最贵的模型始终只看到最相关的信息。5.2 Agent在同一件事上反复打转这是Agent开发里最经典的问题它在一个工具上反复调用参数还几乎一样就是期待下一次能拿到不同的结果。比如用户问有哪些未处理的工单Agent调用了三次查询接口但用户其实想要的是未处理且超过三天的工单而Agent就是没理解这个隐含条件。我给的应急方案是三层。第一层硬性设置最大步数达到上限强制结束并转人工。第二层在运行时做相似调用检测如果某个工具被连续调用两次且参数高度相似就打断Agent提示它你已经执行过类似操作请先分析结果再决定下一步不要重复调用。第三层也是最根本的开发者在设计任务时要把目标拆解得更细致关键约束要写进系统提示词里。比如上面那个工单案例就应该在初始消息里明确未处理且超过三天是核心条件。5.3 工具参数幻觉我之前说过模型生成参数时会一本正经地编造不存在的值。最常见的情形是一个枚举参数模型给了一个不在枚举里的值一个日期参数模型给了一个不存在的日期一个ID参数模型自己脑补了一个不存在的编号。这个坑的根治方案只有一个**每个工具调用都必须经过严格参数校验校验不通过就返回明确错误信息给模型让它修正。**千万不要图省事让参数直接透传进去执行否则Agent的错误会被不断放大。我一般会在工具执行函数外面包一层统一调用代理在代理里做JSON Schema校验、权限校验、频控校验。这一层是agent-native系统里绝对不能省的。5.4 多Agent协作通信比执行更难做到后面很多项目会引入多Agent架构让不同Agent负责不同领域。多Agent不是越多越好通信协议设计不好系统会比单Agent还笨。我见过最典型的失败案例两个Agent用自然语言互相聊天聊着聊着就跑题了任务没完成token烧了一大堆。我的建议是多Agent之间的通信尽量结构化不要用自由文本。比如下发的任务要包含明确的目标、约束、期望产出格式返回的结果要包含结论、依据、不确定点。每个Agent对外暴露的接口就像微服务的API一样是有Schema约束的而不是你帮我看看那个东西怎么样这种模糊口头禅。另外多Agent系统必须有全局调度和仲裁机制不然两个Agent意见不一致时就会僵在那。6. 最后分享一个务实经验写了这么多最后说点个人体会。我踩过最深的坑就是把小规模Demo的成功当成了大规模系统可行的证明。Demo能跑通只说明模型在理想条件下能完成任务真实业务里充满了模糊输入、工具失败、权限不足、流程例外agent-native系统的工程重心有一半其实在兜底上而不是在让模型更聪明上。一个小技巧我觉得特别有用**在写Agent代码之前先做一次人工模拟Agent的流程演练。**你扮演模型对着工具清单一步步走一遍用户任务看看手里有没有足够的信息完成目标、卡在哪一步、需要什么额外条件。这个动作能帮你提前发现大量设计问题省下后面至少两轮返工。我自己每接一个新场景都会用这个方式过一遍比写单元测试还管用。agent-native真正考验的不是你会不会调模型而是你能不能为Agent设计出边界清晰、工具可靠、过程可查的运行环境。模型是发动机但车架、刹车、仪表盘都得你自己造。希望这篇内容能帮你少走一些弯路。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →