
1. 我为什么认为 agent-native 是一次架构级别的转身1.1 大多数AI应用其实只是调了个大模型接口过去一年里我看过不少号称AI 驱动的产品扒开外壳之后发现套路都差不多传统后端不动前端插一个聊天框大模型被封装成一个 REST 接口业务逻辑该怎么写还是怎么写。你问它帮我查一下上周的订单它确实能聊但真正去翻数据库、改数据、触发流程的还是你手写的那堆老代码。LLM 在这里只是一个人肉翻译器把自然语言翻译成固定的几个入口参数。这种做法的好处是稳妥坏处是天花板很低。任何一个稍微复杂一点的任务比如把这三个客户的账单合并起来去掉重复项再生成一封沟通邮件翻译器模式就会撞墙——如果后端没有一个现成的合并账单并发电邮接口你就要为每一个新需求写一个新的接口。你越做越像在给大模型打工而不是在利用大模型。agent-native 的思路完全是另一个方向。它默认一件事系统里真正的执行者是一个或一群AI Agent而不是传统代码里的 controller 和 service。人的角色从逐步操作软件变成表达意图、给出边界、验收结果。这不是把 LLM 塞进现有系统的缝里而是让 Agent 成为软件的主体传统模块全部退化成它手里的工具。1.2 两者最本质的区别在数据和控制流的方向传统架构的控制流是用户 → 界面 → 业务逻辑 → 数据每一步都是确定性的开发者能预判所有路径。agent-native 的控制流变成了用户 → Agent →规划→调用工具→观察结果→再规划→ 数据中间那一段是模型生成的、动态的、无法穷举的。这意味着你不能再靠把所有分支都写出来来保证系统正确你得靠约束、护栏、评测和观测来兜底。我第一次做这种转身时最直观的感受是数据库表设计变了。以前订单表只需要存业务字段现在要给 Agent 预留意图记录中间结果任务状态这些原来根本不会出现在业务表里的东西。API 设计也变了以前接口给人看要友好、简洁、有分页现在接口给 Agent 看要语义明确、参数自解释、错误信息可理解。连日志系统都变了人看的日志按请求打就行Agent 的日志得按轨迹打一条任务可能横跨十几个工具调用。所以我把 agent-native 定义成一种完整的架构身份从底层的存储结构、中间层的接口设计到上层的交互逻辑全都围绕自主 Agent 如何更好地理解、决策、行动来重建。你不可能只在提示词层面玩出 agent-native它不是咒语是工程体系。2. agent-native 架构的四个设计支点2.1 工具不是接口是一等公民在传统架构里一个 API 的价值取决于它的性能、稳定性和文档。在 agent-native 架构里工具tool/function是 Agent 感知世界和改变世界的唯二通道它的价值取决于Agent 能不能在上下文中正确理解它并在合适的时机调用它。这意味着两件传统后端开发几乎不会做的事第一你要为每个工具写一段给机器看的自然语言描述这段描述的质量直接影响模型的选型准确率第二你要让工具具备自我描述能力——Agent 在运行中可能需要发现新工具而不是靠开发者在提示词里把全部工具列表硬编码进去。工具注册表tool registry在 agent-native 系统中的地位相当于传统系统里的 API 网关。我在实际操作里会为每个工具维护三份东西JSON Schema 定义参数结构、给模型看的工具描述两句话讲清楚干什么、什么时候用、给人类看的文档方便排查。Schema 错了模型会幻觉参数描述模糊了模型会在多个相似工具之间随机跳。这三样都做到位工具层才算合格。2.2 记忆与状态从无状态接口到有状态主体传统的 REST 接口默认无状态每个请求自带完整上下文用户身份靠 token 识别。但 Agent 天然有状态——它要记住用户刚才说过什么、自己已经做了哪几步、哪份文档已经读过了。如果你把状态全扔给模型上下文很快就会撞上 context window 的上限如果不做状态管理Agent 多轮任务会反复犯同样的错。我建议把 Agent 的状态分成三层来设计。短期记忆放当前任务的过程数据比如已执行的工具调用序列、中间决策理由这部分住在上下文窗口里工作记忆放跨步骤的业务数据比如正在处理的订单列表、已经合并的账单 ID这部分要落到 Redis 或专门的 state store 里长期记忆放用户偏好、历史结论、可复用的经验这部分落到向量库或结构化存储里。三层之间要有明确的读写接口而不是让 Agent 自己拿上下文塞。踩过一个很典型的坑一开始图省事让 Agent 把全部中间结果都存在上下文里结果任务一长模型开始把旧数据当新数据用甚至把两个订单的信息混在一起。后来改成关键业务数据必须落库上下文里只保留引用 ID准确率立刻上去一截。2.3 从请求-响应到持续运行的事件循环传统 Web 应用是短连接思维一个请求进来一个响应出去完事。Agent 系统是长任务思维一个目标进来Agent 要规划、调用工具、等待反馈、失败重试、可能要征求用户意见整个过程可能是几十秒也可能是几小时。这就要求你的运行时runtime具备事件循环能力。我常用的是一个非常朴素的状态机待处理pending→ 规划中planning→ 工具调用中tool_use→ 等待反馈waiting_input→ 完成done→ 失败failed任何一种中间状态都可以被打断、恢复、超时处理。数据库里有一条任务表字段包括目标、状态、已用预算、agent 上下文句柄、下一步 pending 的动作。为什么强调这一点因为生产环境里 Agent 一定会遇到调用第三方接口 30 秒没返回用户临时打断要求换个方案模型服务限流这类情况。如果你的运行时假设 Agent 是一次性同步调用这些场景全都会变成线上事故。把整个运行过程改造成可恢复的事件流之后我处理这类问题的思路就从保证不出错变成了出错后能回到任意检查点继续。2.4 上下文即产品上下文工程而不是提示词工程现在圈子里还在热烈讨论提示词工程但在 agent-native 架构里我更愿意提上下文工程。因为决定一个 Agent 行为质量的不是那几句 system prompt 写得有多花哨而是它在每一步决策时手里到底握着什么信息。上下文工程的本质是信息编排。你要在正确的时刻把正确的信息放进模型视野把无关信息挡在外面。比如一个处理售后的 Agent它查用户订单时只需要该用户的近期订单摘要不需要把全量订单历史全塞给它它调用退款工具之前给它的上下文是退款政策摘要和本次订单明细而不是漫无边际的产品手册。实际操作时我会给上下文划分区域固定指令区系统人设与硬性约束、动态记忆区任务状态与中间结果、工具反馈区最近一次工具返回数据、用户输入区最新指令。每个区域有 token 预算比如固定指令区常年控制在 2k token 以内动态记忆区控制在 8k 以内超了就做摘要压缩。这样既不浪费钱又不会因为上下文过载导致模型忘事。这四类设计做完agent-native 的地基基本稳了接下来要把地基上的砖一块块砌好。3. 把 API 改造成 Agent 能看懂的东西3.1 工具定义的质量决定了 Agent 的下限接手过不少团队的 Agent 项目我发现一个共性规律凡是 Agent 表现差的项目八成问题出在工具层只有两成出在模型本身。模型再聪明如果递给它的工具是黑盒它也只能靠猜。一个合格的工具定义至少要说清四件事这个工具是干什么的、什么时候该用它、什么时候不该用、每个参数到底是什么意思。例如有一个彻底删除订单的接口如果描述只写删除订单模型很可能在用户说把不需要的订单清一下的时候直接调用它把数据抹了。你需要在描述里加上本工具会物理删除订单且不可恢复仅在产品经理明确要求清除测试数据时使用普通取消请求应调用取消订单工具。这种描述看似啰嗦但它是 Agent 不犯低级错误的关键保障。3.2 一个工具描述改写的前后对比我拿一个真实例子说明改写的效果。之前有个工具原来的描述是这样的get_orders(user_id, status, page)描述写的是获取订单列表。——就这一句。结果是 Agent 经常在查询时需要翻页却不知道传什么参数或者把用户 ID 和订单状态搞混导致返回错误数据。我改成了这样{ name: get_orders, description: 根据用户 ID 查询该用户的订单列表。当用户询问我买了什么订单到哪了时使用。返回数据按创建时间倒序排列每页默认 20 条。若要获取下一页请使用返回结果中的 page_token 并传入相同参数。历史订单超过 90 天的不会出现在结果中如需查询请使用 search_archived_orders 工具。, parameters: { user_id: {type: string, description: 用户唯一标识格式为 uuid来自用户会话上下文}, status: {type: string, enum: [pending, paid, shipped, completed, cancelled], description: 按订单状态筛选不传时返回全部状态}, page_token: {type: string, description: 分页游标由上一次调用的返回结果提供首次查询不传} } }改了之后效果立竿见影工具选错率降低需要人工介入纠正的对话轮次少了大约 60%。我把这归因为三个字——自解释。工具能自解释Agent 就不需要靠猜也不需要靠 system prompt 里的各种防呆咒语。3.3 工具注册、发现与冲突处理当单个 Agent 的工具数量超过 20 个之后另一个问题会浮出来模型在每一步决策时要从几十个工具里选一个选错的概率迅速上升。我见过一上来就挂 60 个工具的 Agent效果反而比只挂 8 个工具时差得多。解决思路不是减少能力而是分级暴露。我把工具按使用频率和风险等级分成三层常驻层是 Agent 一问一答必然要用的工具比如查询、算数、格式化始终在上下文中按需层是根据任务类型动态加载的领域工具比如处理退款时挂载退款相关工具特权层是高风险操作比如删除数据、发送邮件给客户、修改价格默认不暴露只有在 Agent 明确输出需要权限信号并且人工授权之后才挂载。这个方案实操下来工具选择的准确率提高很明显而且顺带解决了安全问题——高风险工具不在视野里Agent 自然不可能误调。冲突处理是另一个容易忽略的点。当两个工具功能相似时比如修改订单地址和修改订单收货人模型会随机选。我的做法是保留一个另一个要么合并参数要么在描述里写清楚此工具不处理收货人变更请调用 XX 工具。工具层史上最经典的 bug 就是这么来的——一个不存在的分支让 Agent 在循环里反复横跳后来才知道是工具描述没写清楚边界。3.4 用协议思维做工具层MCP 只是开始最近 Model Context ProtocolMCP很火很多人问我要不要上。我的看法是MCP 解决的是工具如何被标准化地暴露给 Agent的问题它把每个工具封装成标准化的 resource/tool/prompt 三种原语让 Agent 可以在运行时动态发现工具。这确实是 agent-native 架构缺的一块拼图。但协议不是银弹。MCP 标准化了传输格式没有标准化工具内部的业务语义。你依然要花力气写工具描述、做权限控制、设计错误码。我更愿意把它当作一种工程规范来用所有内部工具都走同一套 schema 标准未来接外部 Agent 生态时无缝迁移。先把内部的工具治理做好再考虑协议级别的问题顺序不要反。4. 单 Agent 打天下还是上多 Agent 协作4.1 什么时候拆分 Agent我刚入局时迷信一个超级 Agent 干所有事很快发现它撑不住。原因不是模型能力不够而是上下文管理和工具选择失去了焦点。一个 Agent 又管数据分析又管客户沟通又管退款审批它的上下文里全是互相冲突的指令工具列表长到模型开始瞎选。拆分的信号有三个任务之间的工具集几乎不重叠任务对状态的读写边界清晰不同任务需要不同的人设和回复风格。比如客服机器人就可以拆成三个客服 Agent处理咨询、售后 Agent处理退换货、质检 Agent审核高风险操作。它们各管一摊工具集互不干扰状态也有明确的领域边界。满足这三个条件时拆开一定比混着好。4.2 常见编排模式编排者-工人、流水线、混合多 Agent 协作的编排模式我在项目里用的主要有三种。编排者-工人模式orchestrator-worker主 Agent 负责拆解目标、分配子任务、汇总结果工人 Agent 只干一件事。适合任务类型多但每类任务独立的场景比如写一份市场分析报告——编排者决定去查数据、读竞品页面、生成图表、写结论分别派给不同工人。流水线模式pipeline每个 Agent 处理固定阶段的输入并输出给下一个。适合流程固化、顺序稳定的场景比如舆情预警→摘要生成→风险定级→通知值班人每个环节的 Agent 只用关心自己那一截数据。混合模式大部分任务走流水线遇到异常由编排者介入重新规划。这是生产环境中我最常用的既享受了流水线的稳定又保留了编排者的灵活性。调度参数上有一个很实际的建议给每个子任务设置独立的超时和重试次数。比如查询类工具超时 10 秒最多重试 2 次生成类任务超时 60 秒最多重试 1 次。别把重试交给 Agent 自己决定模型在失败时往往会换个说法再试一次这在某些场景等同于刷钱。4.3 多 Agent 最难的不是通信是共享状态多 Agent 系统里大家第一反应是设计 Agent 之间的消息协议。但我在实践中发现更难的是共享状态的控制。多个 Agent 并发跑都要读写同一个订单对象谁能改、谁只能读、改坏了怎么回滚这些问题不早设计好协作模式再漂亮也会崩。我的方案是引入工作台概念每个业务对象有一个 owner Agent其他 Agent 只能通过 owner 的接口间接读写。比如订单的 owner 是售后 Agent质检 Agent 想给订单加一个风险标记它不能直接改订单表只能调用售后 Agent 暴露的add_risk_flag 工具。这跟传统后端里的聚合根思想很像只不过现在执行者从代码换成了 Agent。谁拥有这个对象谁就对它的数据一致性负责这样即使 Agent 行为不可预测数据损坏的范围也被圈住了。4.4 用 Message Bus 还是用记忆共享多 Agent 通信有两种实现路线我两种都试过。一种是消息总线Message BusAgent 之间发事件比如订单状态已变更另一种是共享记忆区Agent 都可以读取一个公共的黑板在上面写过程信息。前者适合事件驱动、实时性要求高的流程后者适合有大量上下文需要分阶段积累的任务。我的建议是别二选一而是区分信息类型任务指令走消息总线语义是请你去做这件事做完回复我过程事实写共享黑板语义是这个任务的最新状态长这样。两者都在同一套事件系统上实现只是消息类型和权限不同。有一次我把两类信息混在一个 channel 里结果 Agent 把别人的中间结果当成给自己的指令执行那场面相当混乱。5. Agent 可观测性与评测比传统测试难一个量级5.1 没有轨迹追踪Agent 项目等于盲飞传统后端调一个接口链路追踪是锦上添花Agent 项目求一个链路口径混乱、调用随便失败链路追踪则是保命底线。一个 Agent 任务从用户输入到最终输出中间可能有十几轮模型推理→工具调用→结果回填任何一轮出了问题最终结果都可能是垃圾。你必须在每一轮把思考过程、工具调用参数、工具返回值、模型响应全部落日志。我在项目里直接采用 trace 机制一个任务一条 trace每个工具调用一个 span。关键字段包括本轮模型的完整输入当时的上下文快照、输出内容、工具名、工具参数、工具返回状态码、耗时。排查一次回答质量下降的问题我通常直接看轨迹而不是重新跑一遍因为 Agent 的执行是非确定性的重跑大概率复现不了原问题。5.2 评估 Agent 要拆成四个维度Agent 评测和传统功能测试有个根本差别没有固定的期望输出。同一个问题Agent 可能用完全不同的路径完成但结果都可能正确。所以不能用单元测试那套思路我拆成四个维度来做评估。任务完成率给定一组标准任务人工或用一个裁判模型判断 Agent 是否达成了目标。这个指标最直接。工具调用有效率统计所有工具调用里真正对推进任务有贡献的比例。如果 Agent 反复调同一个工具且参数一模一样说明它陷入死循环。这一维度我定了一个硬性指标连续两次相同参数的调用视为异常要触发中断。成本与延迟每一千个任务的平均 token 消耗、平均调用次数、p95 延迟。Agent 项目里模型费用不是线性的因为一次任务的调用次数不可控不设预算真的会失控。有害行为率Agent 是否触发了高风险工具、是否泄露敏感信息、是否在没有授权时执行破坏性操作。这是一个一票否决的指标只要有害行为超过阈值系统必须下线。5.3 成本治理给 Agent 装上预算表我第一次跑正式 Agent 产品时一个月成本比预期高了两倍原因后来一查就是少量任务失控单个任务调了上百次工具。治理思路不能靠模型自觉要靠运行时约束。我在运行时核心做三件事。第一步数上限单个任务最多允许 N 次工具调用超了就强制中断并要求 Agent 总结已做事项交给用户决定是否继续。第二预算上限按任务维护一个 token 计数器模型调用前检查本次预估 token 是否会超预算超了就拒绝执行下一步。第三成本熔断设置单任务成本阈值一旦超过阈值自动降级为只读模式Agent 只能查询不能写操作直到用户确认加预算。滴几个月的经验下来这套约束让账单回归理性虽然偶尔会中断一些真实需要长任务的场景但总体收益远大于损失。6. 从踩坑到落地几条操作层面的建议6.1 先在流程最稳定的环节引入 Agent讲完架构层面的东西说点落地顺序的建议。很多团队上来就想让 Agent 处理所有客户消息结果被各种 edge case 淹没。我的建议是反着来先从流程最稳定、容错最好、人类已经高度标准化了的环节开始。比如把工单自动分诊给 Agent 做而不是先把客户投诉处理交给 Agent。分诊任务结构清晰、判断边界明确、错了也不会造成大事故非常适合作为 agent-native 架构的第一个练兵场。第一个场景跑通之后你会积累一套自己的Agent 靠谱度感觉——大概能预估模型在什么条件下靠谱、什么条件下需要人兜底。带着这个感觉再逐步把更复杂的环节接进来比一上来就搞大而全稳妥得多。6.2 给 Agent 设置三类护栏Agent 的自主性是一把双刃剑。我在生产环境里固定用三类护栏兜底。操作护栏高风险工具必须人工授权授权采用一次性 token 机制用户点了允许之后这个 token 只能用一次。信息护栏设置敏感信息过滤规则Agent 的输入输出都要过一遍脱敏层身份证号、手机号这类字段在进入模型之前就打码。行为护栏定义 Agent 不能自主执行的动作清单包括承诺赔偿、修改价格、对外发布内容这些只能由人来做Agent 最多生成建议并附上草稿。6.3 我的实践经验先跑通再优化先约束再扩展最后分享一点个人体会。我在 agent-native 这条路上最大的教训是不要试图第一次就构建一个完美的自主系统。自主性的边界应该随着评测体系的完善逐步放宽。一开始把 Agent 的决策权限设得很窄跑通了评测指标稳了再一点点扩大它的自主范围。这比一开始就全放开然后被线上事故打回原形要划算得多。另一个小技巧给 Agent 系统留一个手动降级开关。遇到大规模异常时一键把系统切换回纯人工模式。这个开关我从来没真正用过但它的存在让整个团队敢放手去升级那种心理安全感在长期迭代里非常重要。agent-native 是方向但不是一蹴而就的工程用迭代的心态做每次只前进一步慢一点反而快。