AI智能体与传统后端:控制流程、成本与故障模式
以退款为例,比较确定性后端与LLM智能体循环在延迟、令牌成本、上下文规模、故障模式等方面的差异,以及混合设计最适合的应用场景。
来源: AI Agents vs Traditional Backend Applications: What’s Actually Different?
后端开发长期以来一直依赖一个令人安心的特性:确定性。编写一个处理订单的接口,它在 PostgreSQL 中检查库存并通过 Stripe 对卡片扣款,每次执行时流程都完全一致。在相同的输入和数据库状态下,第42行始终会在第43行之前执行。
随后,业界开始将人工智能代理视为后端系统的下一阶段。这很容易被当作营销话术而忽视,因为这类代理看起来也像是一个能调用外部API并写入数据库的容器化服务。但实际上,控制流程已经发生了变化。在传统的后端系统中,开发人员需要提前处理好每一个步骤、分支以及边缘情况;而在代理系统中,开发人员只需设定目标并提供一组工具,由概率模型来决定执行步骤、顺序以及任务完成的时机。如果将代理仅仅视为另一种微服务,那么在延迟、可靠性、测试以及云服务费用方面都会面临严重问题。
固定流程与推理循环
标准后端系统是通过程序员硬编码的有向无环图来处理请求的:
[Request] ──> [Validate Input] ──> [Database Query] ──> [Transform Data] ──> [Response]
│
└── (Invalid) ──> [Return 400]
无论是 if/else、switch 还是 try/catch,每种分支路径都是预先确定的。代码无法自行添加你未编写的步骤。遇到意外输入时,系统会报错或采用预定义的备用处理方式。
智能体并不遵循固定的执行流程,而是运行在基于 ReAct 模式(即 Reason 加 Act 的缩写)构建的循环结构中。后端会将控制流交给大型语言模型来处理:
┌────────────────────────┐
▼ │
[Objective] ──> [LLM Evaluates State] │
│ │
Does it need more info? │
├── Yes ──> [Select Tool & Arguments]
│ │
│ [Execute Tool] ────────┘
│ (API, DB, Search)
│
└── No ──> [Return Final Answer]
一次循环迭代包含四个部分:
- 将目标、上下文以及迄今为止已采取的操作提供给模型。
- 模型会判断自己是否拥有足够的信息,或者是否需要外部工具。
- 如果需要数据,它会发出结构化的工具调用指令,例如读取文件、调用API或执行查询。
- 运行时环境会执行该工具,将原始输出放入模型的上下文窗口中,然后重新启动循环。
关键在于模型能在运行时动态选择操作步骤的顺序。
示例:为延迟发货的客户退款
假设存在一个用于为发货延迟的客户退款的内部工具。
传统方法
在Express或FastAPI服务中,你可以编写一个处理程序来查找订单、应用固定规则、办理退款并发送通知:
// Traditional Backend: Strict, deterministic logic
async function handleRefund(orderId: string, customerReason: string) {
const order = await db.orders.findById(orderId);
if (!order) {
throw new NotFoundError("Order not found");
}
// Strict business rule written by an engineer
const isEligible = order.status === "DELAYED" && order.daysDelayed > 5;
if (!isEligible) {
return { status: "rejected", reason: "Delay does not meet refund criteria." };
}
const refund = await paymentGateway.refund(order.paymentIntentId);
await db.orders.update(orderId, { status: "REFUNDED" });
await emailService.sendRefundNotice(order.customerEmail);
return { status: "success", refundId: refund.id };
}
这段代码的执行时间不到100毫秒,计算成本几乎可以忽略不计,且每次运行结果都完全一致。但它也相当脆弱。假如有客户反映包裹虽按时送达,但送货员撞坏了邮箱,处理程序会拒绝退款,因为daysDelayed的值为零,其硬编码规则中没有任何内容允许它进行更深入的分析。
智能代理方案
智能代理会根据客户的描述来决定调用哪些工具:
// Agent Loop: The model decides which tools to call
import { generateText, tool } from "ai";
import { z } from "zod";
const tools = {
fetchOrder: tool({
description: "Fetch order details and shipping history",
parameters: z.object({ orderId: z.string() }),
execute: async ({ orderId }) => db.orders.findById(orderId),
}),
issueRefund: tool({
description: "Issue a monetary refund to the customer",
parameters: z.object({
paymentIntentId: z.string(),
amount: z.number(),
reason: z.string()
}),
execute: async (args) => paymentGateway.refund(args.paymentIntentId, args.amount),
}),
escalateToHuman: tool({
description: "Escalate edge cases or physical damage to a support manager",
parameters: z.object({ ticketSummary: z.string() }),
execute: async ({ ticketSummary }) => supportDesk.createEscalation(ticketSummary),
})
};
// The execution is governed by an evaluation loop
const response = await generateText({
model: yourConfiguredLLM,
tools,
maxSteps: 5, // Prevents infinite execution loops
prompt: `Customer Issue: "The package arrived on time, but the driver ran over my mailbox. Order #1234."
Evaluate policy guidelines and take appropriate action.`,
});
在这里,模型会读取投诉内容,调出对应订单,判断问题属于财产损失而非运输物流问题,从而跳过常规的退款检查,直接调用escalateToHuman。这种灵活性是有代价的:该处理流程需要向大语言模型发起三次请求,消耗了少量令牌费用,耗时4秒,而人工处理仅需50毫秒。
两者的对比
从确定性后端系统转向智能代理系统后,几乎所有的运营假设都会发生变化。
- 控制流程:在一种情况下由代码定义处理步骤,而在另一种情况下则由大语言模型在循环中决定步骤。
- 执行路径:后端在编译时即可确定,而智能代理则在运行时才能确定。
- 延迟:后端系统的延迟约为10到200毫秒且可预测,而智能代理的延迟则为2到30秒甚至更久,且会因迭代次数不同而变化。
作为工作记忆的上下文窗口
后端将状态存储在变量、Redis键或数据库行中,而函数则仅读取其所需的字段。对于智能体而言,上下文窗口就相当于短期工作记忆。每当某个工具被调用时,其输出会被序列化为文本,通常是JSON格式,并添加到提示历史记录中。典型的执行过程如下:
- 步骤1:用户输入的提示语,约50个标记。
- 步骤2:模型发出的工具调用请求,约40个标记。
- 步骤3:工具的返回结果,大约增加500个标记。
- 步骤4:模型分析更长的提示语后再次发起调用,增加约80个标记。
- 步骤5:第二次调用的结果返回,大约增加1,200个标记。
随着每次循环的进行,提示语的长度不断增长。由于成本和延迟都会随输入规模扩大而上升,第五步的运行速度明显慢于第一步,成本也更高。
常见的开发错误是向智能体返回整个数据库行或庞大的 API 数据包。如果 searchUsers() 工具将50个完整用户资料一次性放入上下文,很快就会耗尽模型的有效推理时间。设计智能体工具时应像处理公共 API 一样:对输出内容进行筛选和净化,仅保留模型做出下一步决策所需的字段。
为何智能体更难持续运行
后端出现故障时,你会得到堆栈跟踪信息。可以在本地重新发送相同的请求数据,检查变量并修复错误。而智能体则是以概率方式出现故障的。
无限循环。假设代理调用某个API时遇到了诸如invalid_date_format这样的细微验证错误。它会使用略有不同的日期字符串重新尝试,然后再试一次。由于没有对迭代次数(maxSteps)设置上限,它可能会在与验证器的反复交互中消耗数百美元的API额度。
虚构的工具参数。模式与验证机制能为普通代码在运行时提供类型安全保障。大型语言模型有98%的时间能生成符合您模式的有效JSON,但偶尔会加入一些并不存在的参数。您所面临的情况是:
// Expected:
{ "customerId": "cust_123", "amount": 50 }
模型在高温状态下有时会输出的内容:
// What the model occasionally outputs under high temperature:
{ "user_id": "cust_123", "refund_value": "$50.00" }
如果在执行实际函数之前,运行时没有使用 Zod 或 Pydantic 等工具进行严格的模式解析,你的后端系统就会崩溃。
不可预测的路由问题。昨天只需两步就能处理的查询,今天可能因为用户表述略有不同而需要四步才能完成。这就使得响应时间的服务级别协议难以保证。
选择合适的架构
Agent 引起了太多关注,以至于开发者试图用它们来构建整个系统,但这是个代价高昂的错误。
在以下情况下请继续使用普通的后端代码:
- 业务逻辑已知且稳定,比如发票处理、身份验证、CRUD 操作以及购物车计算。
- 需要极低的延迟,比如结账流程、搜索自动补全以及实时消息传递。
- 错误可能带来合规或财务风险,比如账本管理、健康记录处理以及权限控制。
以下情况应使用智能体:
- 解决方案的路径不明确,例如寻找有3小时中转、提供素食选项且价格低于800美元的航班。
- 输入数据杂乱无结构,比如格式各异的PDF发票、自由书写的电子邮件或客户故障报告。
- 系统必须协调没有共享API的多个不同工具,例如浏览外部网站、查阅途中找到的文档或跨多个产品对问题进行分类处理。
行之有效的混合设计
在实际应用中,最可靠的设计往往并非纯粹的智能体,而是一个具有确定性的后端,在其控制的范围内嵌入智能体:
[Incoming Request] ──> [Traditional API Gateway] ──> Authentication / Rate Limiting
│
▼
[Standard Business Logic] ──> Fast DB Reads / Validation
│
▼
[Targeted Agent Boundary] ──> Handles unstructured task
│ (Restricted to 3 safe tools)
▼
[Standard Business Logic] ──> Validates agent output
│
▼
[Final Response] <─── [Structured DB Write]
将路由、授权、持久化以及关键业务验证功能放在确定性代码中实现。仅在对真正需要类人类推理和灵活工具协调的子任务时才调用智能体。
核心要点
智能体并不比传统后端更好,它只是另一种计算范式。传统后端通过遵循明确指令来保证可预测性、速度和低成本,而智能体则依靠让大语言模型在推理循环中选择执行路径来实现适应性和问题解决能力。
因此在开发下一个功能之前,不必先考虑智能体是否能够完成该任务,因为只要有足够的标记量,它很可能就能做到。应先思考自己是否已经知道解决问题所需的步骤。如果已知,就自行编写代码;将智能体留用于那些普通代码无法灵活处理的开放式问题。