AI Agent 就是后端微服务
riotamago
AI Agent 就是后端微服务
我最近工作上的一些感悟, ai agent 的本质越发趋近于成熟的软件工程。它不是一个全新的,玄学的东西,而是可以放回到已经熟悉的软件工程框架里理解:每一个部件,几乎都能找到传统后端系统里的对照。只不过代码驱动的业务逻辑转而部分变成了 LLM 驱动,取代了 if else branch,AI 可以自己选择路要怎么走。这么做的优点,是 LLM 本身的 inference 能力能够接受和产出更灵活多变的 input 和 output。而缺点则是速度太慢和输出的稳定性不佳。
所以,从这个角度看,AI Agent 的本质就是一种后端微服务的变体,适用于特定的业务场景。
如果你需要做一个稳定、高并发、低延迟、强一致性的支付接口,那毫无疑问应该继续走传统后端微服务。因为这里需要的是确定性、性能、幂等,而不是让 LLM “理解一下用户想不想付款”。
但如果业务是一些更开放、更模糊、更依赖自然语言输入的场景,比如客服、研究助手、内部知识库问答、代码辅助等以自然语言作为输入的方式,那么 LLM 的 inference 能力就非常有价值。它可以让服务从“只能处理预定义参数”变成“可以理解用户意图并动态组织执行路径”。
既然二者本质上都可以被看成服务,那么它们当然也可以混用。
一个传统微服务可以作为 MCP 工具暴露给 AI Agent,让 Agent 在需要的时候调用它,从而得到某些稳定、可验证的结果。比如创建 ticket、查 databricks 数据等。反过来,一个 AI Agent 也可以被包装成传统后端服务,对外暴露 HTTP API、gRPC API 或消息队列接口。其他系统并不需要知道它内部是用 LLM 推理、规则引擎,还是普通代码实现的。
说回 Agent 开发。公司主要用的是 Google 推出的 ADK 框架,我也研究得比较多。一个很有意思的视角是:可以把 ADK 里的各种概念和传统后端开发做一个系统性的对照。
A2A = 服务发现
ADK 里的 A2A(Agent-to-Agent)本质上就是服务发现。
在传统微服务里,一个服务需要知道另一个服务的地址、能力、接口和调用方式。A2A 解决的是同样的问题:一个 Agent 如何发现另一个 Agent,并把任务交给它。比如一个 Planner Agent 可以把“查数据”交给 Data Agent,把“生成报告”交给 Writer Agent,把“执行操作”交给 Ops Agent。这和微服务里的 service orchestration 没什么区别。区别只是传统服务之间传的是结构化 RPC,而 Agent 之间传的是自然语言任务和上下文。
Multi-Agent = 微服务拆分
这是通用概念,我认为 Multi-Agent 很像微服务拆分。一个大 Agent 往往会变得越来越难维护。它的 prompt 会越来越巨大,tool 会越来越多,上下文会越来越混乱,行为也会越来越不稳定。这个问题和传统单体服务非常像:一开始所有逻辑都放在一个服务里很方便,但随着业务复杂度上升,边界会变得模糊,修改风险会变大,系统也会越来越难测试。
所以更合理的方式是拆分。Planner Agent 负责规划,Research Agent 负责检索,Coding Agent 负责写代码,Reviewer Agent 负责检查,Executor Agent 负责执行。每个 Agent 只负责单一职责,只暴露有限能力,只维护自己的上下文和工具集合。
这和微服务里的 bounded context 几乎一样。拆分 Agent 的目的不是为了显得架构复杂,而是为了降低单个 Agent 的认知负担,让职责边界更清晰,让系统更可测试、更可观测、更容易演进。
Tool/ function call = SDK
这是个通用概念,一个 Tool 可以是本地函数、HTTP API、数据库查询、MCP Server,甚至另一个 Agent。但对 LLM 来说,它们都只是被包装到本地的 “可调用能力”。
传统后端里,我们会设计 API schema;Agent 里则是 tool schema。一个好的 Tool 定义,不只是参数列表,而是完整的接口契约,比如什么时候该调用,参数含义是什么,返回值代表什么。所以 Tool Engineering 其实就是 API Engineering。
MCP = Rest API/gRPC
MCP 也是个通用概念,之前已经说过 tool,但 tool 的局限是可能你为 Agent A 写的 tool,因为格式不兼容等原因,不能很轻易地给 Agent B 用。 MCP (model context protocol) 如字面意义,就是一种模型上下文协议,试图统一大模型和外部工具之间的通信规则。当然实际对话中,很多人口中的 MCP 也指实施了 MCP 的,能被 agent 调用的 server。MCP 能让不同 Agent 可以用一致的方式访问数据库,文件系统,业务 API。就如同传统后端里 REST API 规定了固定的字段和调用约定,大家照着接就行。
写到这里其实我们发现,让 AI agent 获得额外的能力有非常多方式,你可以再搞一个新的 agent,用 A2A 作为接口,做一套 multi-agent 系统。你可以维持单一 Agent,通过连接用了 MCP 的外部服务从而实现额外功能。你也可以把外部服务包装成 Tool 让 Agent 直接调用,类似把依赖包用 SDK 的形式写进自己的代码里。很多人觉得目前这部分很混乱,可我觉得哪怕在传统后端的世界里,这些不同的方案也都是可行的,所以最终需要一些架构上的设计,决定每一个情况用什么解决方案最合理。
目前关于 AI Agent 领域可能缺乏一些公认的架构设计理论,告诉你什么时候适合用 tool,什么时候用 mcp 或者 sub agent,也有声音说 mcp 会被包装成 tool 的 cli 取代等等,最终会演化到什么程度我也不好说,可能有些方式确实会消亡,也可能共存。
聊完宏观的,再说说单一 agent 之内的一些概念。
Prompt = 业务逻辑 ?
大家应该都明白 prompt 是什么。传统后端里,业务规则写在代码里:什么条件触发什么动作,按什么顺序执行,全都由开发者用确定的语法固定下来。而对于 AI Agent 来说,相当一部分这种逻辑从代码挪进了基于自然语言的 prompt,直接告诉 LLM 要做什么。
再次强调,相比于传统代码确定性的语义,Prompt 同一个意图,换一种说法、调一下语序、加一个例子,模型的行为可能就不一样了。且代码做不了任何带有一点不确定的东西,比如让它写篇文章,而 LLM 的 inference 能力配上 合适的提示词几乎能写任何文章,所以可能还是有些本质的不同...
Context = 工作内存
Context 本质上就是 Agent 的工作内存。
传统程序运行时会有内存,保存当前函数调用栈、局部变量、中间状态和依赖对象。Agent 也一样,只不过它的内存是被放进模型上下文窗口里的 token。System prompt、用户输入、历史对话、工具描述、检索结果、中间推理摘要、tool response,都会共同组成当前这次模型调用的 context。
所以 context window 可以类比成一种非常昂贵、非常有限、而且生命周期很短的工作内存。
Skill = 可复用的函数
Skill 本质上是可复用的能力模块,类似传统软件里的函数、类库或业务组件。
一个 Skill 可以封装一套特定任务的执行方式。比如 “分析 SQL 查询性能” 可以是一个 Skill,“生成周报”可以是一个 Skill,它可能包含 prompt、工具、示例、约束、输出格式,甚至一个小型 workflow。但从工程角度看,它就是把一段可复用能力抽象出来,避免每次都从零开始让模型理解任务。
这和写代码时遇到重复或者近似逻辑时写成带些参数的函数的意图是一样的。
RAG = 数据库
RAG (Retrieval-Augmented Generation) 会让 AI 先检索外部数据库,根据从数据库里得到的额外知识做出更好的回答,尤其用于文档多到不可能放在上下文窗口里的情况。
传统的数据库基本要靠 SQL 等 query language 才能查询,由于 AI Agent 的输入多为自然语言,也需要能用自然语言直接查询的方式,最常用的做法,也是很多人说起 RAG 默认会使用的流程,是把知识转成向量,再放入向量数据库里,同时把用户或者 AI 生成的自然语言提问也转成向量,进行向量和向量之间的比对,最终实现基于自然语言的搜索。
这中间会有大量的工程实践,比如向量数据库里的数据怎么加索引,文字变成的向量会转成多少维度,如果文字量太大如何切成小块逐一存储等等,再后来又延伸出不只依赖 vector search,而是把多种检索方式按权重混合的 hybrid search 等更复杂的做法。
Structured Output = Schema / Protobuf
Structured Output 本质上就是 Schema,或者说更像 Agent 世界里的 protobuf。
一旦 Agent 要进入生产系统,它就不能只输出一段自然语言。自然语言适合给人看,但不适合作为下游系统的输入。下游系统需要的是稳定结构,比如 JSON、SQL、workflow plan、action list、classification result 或某种业务 schema。
传统后端里,服务之间通信需要 protobuf、JSON schema、Avro 或数据库 schema。它们的作用是定义字段、类型、嵌套结构和兼容性。Agent 系统也一样。如果 Agent 输出不稳定,下游系统就无法可靠解析。
Session = Request Context
ADK 里的 Session 保存的是当前交互中的上下文、用户输入、中间结果、工具调用历史,以及可能包含 trace、logs 相关的执行信息。ADK 实现的方式也很简单,就是存在内存里只服务于当前 request 的 key value pair。
传统 HTTP request 通常几百毫秒就结束了,但 Agent Session 可能持续几分钟甚至几十分钟。用户可能连续追问,Agent 可能多次调用工具,可能产生中间结果,也可能在多个步骤之间保持上下文。虽然生命周期更长,但本质上它仍然是一次请求上下文。
Memory = 服务于特定目的的缓存和数据库
算是一个比较新的概念,人们总有 “AI 会成长”,“越用越聪明”的想象,而做法大体就是 Agent 会从像人一样在不断的交互中“记住”很多东西,从而表现得越来越好。
但从目前的工程实现来看,Memory 本质上只是缓存、数据库、profile store、vector DB 或 knowledge base。它解决的不是魔法问题,而是数据存储和检索问题。
用户偏好、历史任务、长期上下文、业务知识,这些东西本来就在传统系统里存在。比如推荐系统会保存用户偏好,CRM 会保存客户历史,搜索系统会维护索引,知识库会保存组织文档。Agent Memory 只是让 LLM 可以在合适的时候通过 semantic retrieval 使用这些信息。
所以 Memory Service 更像“带 embedding 的数据库”。真正难的不是把信息存进去,而是决定什么信息值得存,什么时候应该检索,检索出来是否相关,过期信息如何处理,错误记忆如何修改,用户如何删除,以及多个记忆冲突时应该相信谁。
Workflow = 状态机 / 业务逻辑
在 ADK 里写一个 AI Agent,本质就是画一幅流程图 (workflow),并定义好每个 Node 具体做什么,这里每一个 node 就好比传统代码里的一个 class 或者 function,而业务逻辑把这些 class/function 串联到一起。比如订单系统会经历创建订单、锁库存、发起支付、确认支付、创建履约单、通知用户等步骤。每一步都有状态转移、失败处理和补偿逻辑。
Agent 系统也一样。比如一个 Research Agent,可能需要先理解问题,再搜索资料,然后总结结果,之后自我检查,最后输出答案。一个 Data Agent 可能需要先理解用户问题,再找到相关表,生成 SQL,执行查询,检查结果,最后解释结论。这些流程本质上都是 workflow orchestration。
ADK 支持的如 Sequential Agent、Loop Agent、Parallel Agent (注:这里的 agent 算是 ADK 内部术语,更类似 node 的意思,不是指独立的 AI Agent),可以提供多种连接方式,把这些 node 拼接成一个完整的 workflow。
区别只是传统 workflow 的节点通常是 deterministic code,而 Agent workflow 的某些节点变成了 LLM inference。所以 Agent Workflow 的重点不是“让模型自由发挥”,而是清楚地区分哪些步骤允许推理,哪些步骤必须校验,哪些步骤必须人工确认,哪些步骤必须由确定性代码执行。
Eval = 测试系统和 profiling
Eval 本质上是 Agent 世界里的(性能)测试系统。
传统后端有 unit test、integration test、regression test,用来保证代码修改不会破坏已有行为。Agent 也需要类似体系。只不过 Agent 的测试更复杂,因为它的输出不总是完全 deterministic。同一个问题,在不同模型版本、不同上下文、不同温度设置下,可能会产生不同结果。
所以 Agent Eval 更像测试系统和质量评估系统的结合。它不只是看程序有没有 exception,而是要判断 Agent 的行为质量。比如工具调用是否正确,输出是否符合 schema,是否出现 hallucination,是否完成用户任务,是否遵守安全边界,是否在关键步骤请求人工确认。
Eval 也有非常多技术细节,比如传统软件开发里的测试往往是发版前就测好,在 agent 里对应叫 offline eval,除此之外还有上线后持续跑的 online eval。做 eval 之前如何收集数据,标注正确的答案,构建回归集,设计具体 eval 的 grader 里具体的 metrics 和 scoring,如何对比不同版本,甚至不同模块的 regression。由于 LLM 生成自然语言的天性,难免要进行自然语言的对比。比如面对用户问题真实客服的回答 v.s. agent 的回答,可能具体文字截然不同但都把问题解决了,所以可能会引入另一个 LLM as a judge 来判断 agent 的回答是否有效。而 LLM as a judge 本身的正确程度就值得单独再搞一个 eval...
结语
写到这里,以及基于我个人工作的经验感受,我觉得让 AI Agent 真正变得可靠的,不总是更强的模型或更巧妙的 prompt,而是那些我们在传统软件工程里早已熟悉的东西——服务拆分、接口设计、状态管理、可观测性、测试与校验。LLM 带来的只是把其中若干个"确定性节点"换成了"推理节点",整个系统的骨架并没有变。
所以与其把 AI Agent 当成一个截然不同的新东西,不如把它看成后端工程的一次输入和输出层面的升级。它让系统能够消费模糊的自然语言、动态组织执行路径,但代价是牺牲了确定性、速度和稳定性。AI Agent 的架构设计本质就是划清边界,哪些步骤交给推理,哪些步骤必须由确定性代码守住,哪些步骤需要人来拍板。
这个领域今天看起来概念繁多、方案混乱,但这种混乱本身并不新鲜。微服务当年也是这么走过来的。我认为最终的结局,其一, AI Agent 没能推翻软件工程,它只是在传统的软件工程里加了点新东西。其二可能是以后基座模型的能力变得夸张般强大,以至于不再需要很多工程化的方案和限制,也能实现确定性和稳定性(我短暂尝试了 fable5,我觉得它还做不到)。模型还会继续迭代升级,最终会走向哪条路我不好说,只能说如今要最高效的利用 LLM / AI Agent,还是可以以软件工程的思维继续驾驭。
我最近工作上的一些感悟, ai agent 的本质越发趋近于成熟的软件工程。它不是一个全新的,玄学的东西,而是可以放回到已经熟悉的软件工程框架里理解:每一个部件,几乎都能找到传统后端系统里的对照。只不过代码驱动的业务逻辑转而部分变成了 LLM 驱动,取代了 if else branch,AI 可以自己选择路要怎么走。这么做的优点,是 LLM 本身的 inference 能力能够接受和产出更灵活多变的 input 和 output。而缺点则是速度太慢和输出的稳定性不佳。
所以,从这个角度看,AI Agent 的本质就是一种后端微服务的变体,适用于特定的业务场景。
如果你需要做一个稳定、高并发、低延迟、强一致性的支付接口,那毫无疑问应该继续走传统后端微服务。因为这里需要的是确定性、性能、幂等,而不是让 LLM “理解一下用户想不想付款”。
但如果业务是一些更开放、更模糊、更依赖自然语言输入的场景,比如客服、研究助手、内部知识库问答、代码辅助等以自然语言作为输入的方式,那么 LLM 的 inference 能力就非常有价值。它可以让服务从“只能处理预定义参数”变成“可以理解用户意图并动态组织执行路径”。
既然二者本质上都可以被看成服务,那么它们当然也可以混用。
一个传统微服务可以作为 MCP 工具暴露给 AI Agent,让 Agent 在需要的时候调用它,从而得到某些稳定、可验证的结果。比如创建 ticket、查 databricks 数据等。反过来,一个 AI Agent 也可以被包装成传统后端服务,对外暴露 HTTP API、gRPC API 或消息队列接口。其他系统并不需要知道它内部是用 LLM 推理、规则引擎,还是普通代码实现的。
说回 Agent 开发。公司主要用的是 Google 推出的 ADK 框架,我也研究得比较多。一个很有意思的视角是:可以把 ADK 里的各种概念和传统后端开发做一个系统性的对照。
A2A = 服务发现
ADK 里的 A2A(Agent-to-Agent)本质上就是服务发现。
在传统微服务里,一个服务需要知道另一个服务的地址、能力、接口和调用方式。A2A 解决的是同样的问题:一个 Agent 如何发现另一个 Agent,并把任务交给它。比如一个 Planner Agent 可以把“查数据”交给 Data Agent,把“生成报告”交给 Writer Agent,把“执行操作”交给 Ops Agent。这和微服务里的 service orchestration 没什么区别。区别只是传统服务之间传的是结构化 RPC,而 Agent 之间传的是自然语言任务和上下文。
Multi-Agent = 微服务拆分
这是通用概念,我认为 Multi-Agent 很像微服务拆分。一个大 Agent 往往会变得越来越难维护。它的 prompt 会越来越巨大,tool 会越来越多,上下文会越来越混乱,行为也会越来越不稳定。这个问题和传统单体服务非常像:一开始所有逻辑都放在一个服务里很方便,但随着业务复杂度上升,边界会变得模糊,修改风险会变大,系统也会越来越难测试。
所以更合理的方式是拆分。Planner Agent 负责规划,Research Agent 负责检索,Coding Agent 负责写代码,Reviewer Agent 负责检查,Executor Agent 负责执行。每个 Agent 只负责单一职责,只暴露有限能力,只维护自己的上下文和工具集合。
这和微服务里的 bounded context 几乎一样。拆分 Agent 的目的不是为了显得架构复杂,而是为了降低单个 Agent 的认知负担,让职责边界更清晰,让系统更可测试、更可观测、更容易演进。
Tool/ function call = SDK
这是个通用概念,一个 Tool 可以是本地函数、HTTP API、数据库查询、MCP Server,甚至另一个 Agent。但对 LLM 来说,它们都只是被包装到本地的 “可调用能力”。
传统后端里,我们会设计 API schema;Agent 里则是 tool schema。一个好的 Tool 定义,不只是参数列表,而是完整的接口契约,比如什么时候该调用,参数含义是什么,返回值代表什么。所以 Tool Engineering 其实就是 API Engineering。
MCP = Rest API/gRPC
MCP 也是个通用概念,之前已经说过 tool,但 tool 的局限是可能你为 Agent A 写的 tool,因为格式不兼容等原因,不能很轻易地给 Agent B 用。 MCP (model context protocol) 如字面意义,就是一种模型上下文协议,试图统一大模型和外部工具之间的通信规则。当然实际对话中,很多人口中的 MCP 也指实施了 MCP 的,能被 agent 调用的 server。MCP 能让不同 Agent 可以用一致的方式访问数据库,文件系统,业务 API。就如同传统后端里 REST API 规定了固定的字段和调用约定,大家照着接就行。
写到这里其实我们发现,让 AI agent 获得额外的能力有非常多方式,你可以再搞一个新的 agent,用 A2A 作为接口,做一套 multi-agent 系统。你可以维持单一 Agent,通过连接用了 MCP 的外部服务从而实现额外功能。你也可以把外部服务包装成 Tool 让 Agent 直接调用,类似把依赖包用 SDK 的形式写进自己的代码里。很多人觉得目前这部分很混乱,可我觉得哪怕在传统后端的世界里,这些不同的方案也都是可行的,所以最终需要一些架构上的设计,决定每一个情况用什么解决方案最合理。
目前关于 AI Agent 领域可能缺乏一些公认的架构设计理论,告诉你什么时候适合用 tool,什么时候用 mcp 或者 sub agent,也有声音说 mcp 会被包装成 tool 的 cli 取代等等,最终会演化到什么程度我也不好说,可能有些方式确实会消亡,也可能共存。
聊完宏观的,再说说单一 agent 之内的一些概念。
Prompt = 业务逻辑 ?
大家应该都明白 prompt 是什么。传统后端里,业务规则写在代码里:什么条件触发什么动作,按什么顺序执行,全都由开发者用确定的语法固定下来。而对于 AI Agent 来说,相当一部分这种逻辑从代码挪进了基于自然语言的 prompt,直接告诉 LLM 要做什么。
再次强调,相比于传统代码确定性的语义,Prompt 同一个意图,换一种说法、调一下语序、加一个例子,模型的行为可能就不一样了。且代码做不了任何带有一点不确定的东西,比如让它写篇文章,而 LLM 的 inference 能力配上 合适的提示词几乎能写任何文章,所以可能还是有些本质的不同...
Context = 工作内存
Context 本质上就是 Agent 的工作内存。
传统程序运行时会有内存,保存当前函数调用栈、局部变量、中间状态和依赖对象。Agent 也一样,只不过它的内存是被放进模型上下文窗口里的 token。System prompt、用户输入、历史对话、工具描述、检索结果、中间推理摘要、tool response,都会共同组成当前这次模型调用的 context。
所以 context window 可以类比成一种非常昂贵、非常有限、而且生命周期很短的工作内存。
Skill = 可复用的函数
Skill 本质上是可复用的能力模块,类似传统软件里的函数、类库或业务组件。
一个 Skill 可以封装一套特定任务的执行方式。比如 “分析 SQL 查询性能” 可以是一个 Skill,“生成周报”可以是一个 Skill,它可能包含 prompt、工具、示例、约束、输出格式,甚至一个小型 workflow。但从工程角度看,它就是把一段可复用能力抽象出来,避免每次都从零开始让模型理解任务。
这和写代码时遇到重复或者近似逻辑时写成带些参数的函数的意图是一样的。
RAG = 数据库
RAG (Retrieval-Augmented Generation) 会让 AI 先检索外部数据库,根据从数据库里得到的额外知识做出更好的回答,尤其用于文档多到不可能放在上下文窗口里的情况。
传统的数据库基本要靠 SQL 等 query language 才能查询,由于 AI Agent 的输入多为自然语言,也需要能用自然语言直接查询的方式,最常用的做法,也是很多人说起 RAG 默认会使用的流程,是把知识转成向量,再放入向量数据库里,同时把用户或者 AI 生成的自然语言提问也转成向量,进行向量和向量之间的比对,最终实现基于自然语言的搜索。
这中间会有大量的工程实践,比如向量数据库里的数据怎么加索引,文字变成的向量会转成多少维度,如果文字量太大如何切成小块逐一存储等等,再后来又延伸出不只依赖 vector search,而是把多种检索方式按权重混合的 hybrid search 等更复杂的做法。
Structured Output = Schema / Protobuf
Structured Output 本质上就是 Schema,或者说更像 Agent 世界里的 protobuf。
一旦 Agent 要进入生产系统,它就不能只输出一段自然语言。自然语言适合给人看,但不适合作为下游系统的输入。下游系统需要的是稳定结构,比如 JSON、SQL、workflow plan、action list、classification result 或某种业务 schema。
传统后端里,服务之间通信需要 protobuf、JSON schema、Avro 或数据库 schema。它们的作用是定义字段、类型、嵌套结构和兼容性。Agent 系统也一样。如果 Agent 输出不稳定,下游系统就无法可靠解析。
Session = Request Context
ADK 里的 Session 保存的是当前交互中的上下文、用户输入、中间结果、工具调用历史,以及可能包含 trace、logs 相关的执行信息。ADK 实现的方式也很简单,就是存在内存里只服务于当前 request 的 key value pair。
传统 HTTP request 通常几百毫秒就结束了,但 Agent Session 可能持续几分钟甚至几十分钟。用户可能连续追问,Agent 可能多次调用工具,可能产生中间结果,也可能在多个步骤之间保持上下文。虽然生命周期更长,但本质上它仍然是一次请求上下文。
Memory = 服务于特定目的的缓存和数据库
算是一个比较新的概念,人们总有 “AI 会成长”,“越用越聪明”的想象,而做法大体就是 Agent 会从像人一样在不断的交互中“记住”很多东西,从而表现得越来越好。
但从目前的工程实现来看,Memory 本质上只是缓存、数据库、profile store、vector DB 或 knowledge base。它解决的不是魔法问题,而是数据存储和检索问题。
用户偏好、历史任务、长期上下文、业务知识,这些东西本来就在传统系统里存在。比如推荐系统会保存用户偏好,CRM 会保存客户历史,搜索系统会维护索引,知识库会保存组织文档。Agent Memory 只是让 LLM 可以在合适的时候通过 semantic retrieval 使用这些信息。
所以 Memory Service 更像“带 embedding 的数据库”。真正难的不是把信息存进去,而是决定什么信息值得存,什么时候应该检索,检索出来是否相关,过期信息如何处理,错误记忆如何修改,用户如何删除,以及多个记忆冲突时应该相信谁。
Workflow = 状态机 / 业务逻辑
在 ADK 里写一个 AI Agent,本质就是画一幅流程图 (workflow),并定义好每个 Node 具体做什么,这里每一个 node 就好比传统代码里的一个 class 或者 function,而业务逻辑把这些 class/function 串联到一起。比如订单系统会经历创建订单、锁库存、发起支付、确认支付、创建履约单、通知用户等步骤。每一步都有状态转移、失败处理和补偿逻辑。
Agent 系统也一样。比如一个 Research Agent,可能需要先理解问题,再搜索资料,然后总结结果,之后自我检查,最后输出答案。一个 Data Agent 可能需要先理解用户问题,再找到相关表,生成 SQL,执行查询,检查结果,最后解释结论。这些流程本质上都是 workflow orchestration。
ADK 支持的如 Sequential Agent、Loop Agent、Parallel Agent (注:这里的 agent 算是 ADK 内部术语,更类似 node 的意思,不是指独立的 AI Agent),可以提供多种连接方式,把这些 node 拼接成一个完整的 workflow。
区别只是传统 workflow 的节点通常是 deterministic code,而 Agent workflow 的某些节点变成了 LLM inference。所以 Agent Workflow 的重点不是“让模型自由发挥”,而是清楚地区分哪些步骤允许推理,哪些步骤必须校验,哪些步骤必须人工确认,哪些步骤必须由确定性代码执行。
Eval = 测试系统和 profiling
Eval 本质上是 Agent 世界里的(性能)测试系统。
传统后端有 unit test、integration test、regression test,用来保证代码修改不会破坏已有行为。Agent 也需要类似体系。只不过 Agent 的测试更复杂,因为它的输出不总是完全 deterministic。同一个问题,在不同模型版本、不同上下文、不同温度设置下,可能会产生不同结果。
所以 Agent Eval 更像测试系统和质量评估系统的结合。它不只是看程序有没有 exception,而是要判断 Agent 的行为质量。比如工具调用是否正确,输出是否符合 schema,是否出现 hallucination,是否完成用户任务,是否遵守安全边界,是否在关键步骤请求人工确认。
Eval 也有非常多技术细节,比如传统软件开发里的测试往往是发版前就测好,在 agent 里对应叫 offline eval,除此之外还有上线后持续跑的 online eval。做 eval 之前如何收集数据,标注正确的答案,构建回归集,设计具体 eval 的 grader 里具体的 metrics 和 scoring,如何对比不同版本,甚至不同模块的 regression。由于 LLM 生成自然语言的天性,难免要进行自然语言的对比。比如面对用户问题真实客服的回答 v.s. agent 的回答,可能具体文字截然不同但都把问题解决了,所以可能会引入另一个 LLM as a judge 来判断 agent 的回答是否有效。而 LLM as a judge 本身的正确程度就值得单独再搞一个 eval...
结语
写到这里,以及基于我个人工作的经验感受,我觉得让 AI Agent 真正变得可靠的,不总是更强的模型或更巧妙的 prompt,而是那些我们在传统软件工程里早已熟悉的东西——服务拆分、接口设计、状态管理、可观测性、测试与校验。LLM 带来的只是把其中若干个"确定性节点"换成了"推理节点",整个系统的骨架并没有变。
所以与其把 AI Agent 当成一个截然不同的新东西,不如把它看成后端工程的一次输入和输出层面的升级。它让系统能够消费模糊的自然语言、动态组织执行路径,但代价是牺牲了确定性、速度和稳定性。AI Agent 的架构设计本质就是划清边界,哪些步骤交给推理,哪些步骤必须由确定性代码守住,哪些步骤需要人来拍板。
这个领域今天看起来概念繁多、方案混乱,但这种混乱本身并不新鲜。微服务当年也是这么走过来的。我认为最终的结局,其一, AI Agent 没能推翻软件工程,它只是在传统的软件工程里加了点新东西。其二可能是以后基座模型的能力变得夸张般强大,以至于不再需要很多工程化的方案和限制,也能实现确定性和稳定性(我短暂尝试了 fable5,我觉得它还做不到)。模型还会继续迭代升级,最终会走向哪条路我不好说,只能说如今要最高效的利用 LLM / AI Agent,还是可以以软件工程的思维继续驾驭。
已获得 91 大米


+2
共30条回复
✨ 您正在体验新版论坛UI


