为什么大家都在劝退 Agent 开发?因为多数场景根本轮不到它出场
最近掘金上一篇《为什么不推荐走 Agent 开发》引发了不小的讨论。作为一个在过去一年里给业务系统接过三轮 Agent 能力、又亲手拆掉两轮的开发者,我想认真聊聊:劝退的声音到底在劝退什么,以及 Agent 真正的适用边界在哪里。
一、先说结论:Agent 不是架构升级,是一种昂贵的兜底
很多团队的思路是这样的:业务逻辑写不动了、规则越来越复杂了,那就"上 Agent 吧,让大模型自己决策"。听起来很美------不需要枚举所有分支,不需要维护复杂的状态机,一句 prompt 搞定。
但真实情况是:Agent 把确定性问题转换成了概率性问题,而概率性系统的工程成本,大部分团队根本没有预算。
一个传统工作流,跑一万次的结果是确定的,bug 可以复现、可以修。而一个 Agent 工作流,跑一万次可能有三百次走进你从未预料到的分支。你面对的不是 bug,是分布------你修的不是代码,是概率。
二、Agent 系统的三大真实痛点
痛点 1:评估比实现难十倍
写一个能跑的 Agent demo,一个周末就够。但你要回答"它到底行不行"时,问题来了:
- 传统函数:单测覆盖率 90%,你就能睡好觉
- Agent 系统:同样的输入都可能产生不同路径,你怎么写断言?
实际项目中我们的做法是搭建一套基于"结果评分 + 路径审计"的评估流水线,这也是为什么我说评估基础设施先于 Agent 逻辑:
python
# agent_eval.py - 简化版 Agent 评估流水线
import json
from dataclasses import dataclass
@dataclass
class EvalCase:
query: str
expected_tools: list # 期望调用的工具序列
expected_keywords: list # 最终输出必须包含的关键信息
max_steps: int = 5 # 步数上限,防止"绕远路"
def score_trace(trace: dict, case: EvalCase) -> dict:
"""对一次 Agent 执行轨迹打分,而不是只看最终答案"""
scores = {"correctness": 0, "efficiency": 0, "safety": 100}
# 1. 结果正确性:关键信息是否覆盖
answer = trace["final_answer"]
hit = sum(1 for kw in case.expected_keywords if kw in answer)
scores["correctness"] = hit / max(len(case.expected_keywords), 1)
# 2. 效率:步数越接近最优路径分越高
actual_steps = len(trace["steps"])
scores["efficiency"] = max(0, 1 - actual_steps / (case.max_steps * 2))
# 3. 安全性:是否调用了白名单外的工具、是否发生死循环
used = [s["tool"] for s in trace["steps"] if s.get("tool")]
if any(u not in ALLOWED_TOOLS for u in used):
scores["safety"] = 0
if len(used) != len(set(used)) and used.count("search") > 3:
scores["safety"] -= 40 # 同一工具反复调用,疑似死循环
return scores
# 批量回归:每次改 prompt 或换模型,全量跑一遍
# 某次我们只是给 system prompt 加了一句话,效率分从 0.82 掉到 0.41
# ------ 没有评估流水线,这种退化你根本发现不了
这个例子想说明的是:Agent 的"改一行 prompt 引发全面退化"是常态而非例外。没有评估体系,你等于在盲飞。
痛点 2:成本和延迟是工作流的几倍到几十倍
一个规则的表单校验逻辑,耗时 1ms,成本为零。换成 Agent 来做,一次 LLM 调用 800ms,涉及工具调用时可能要 3-5 轮循环,token 费用是调用量 × 平均轮数的乘积。
我们在一个客服工单场景实测:Agent 方案的 P95 延迟 4.2 秒,月度 token 成本约为规则引擎方案的 47 倍,而最终解决率只从 71% 提升到 78%。这 7 个百分点值不值 47 倍成本,是产品决策,不是技术决策------但很多团队把它当成了"技术先进性"问题。
痛点 3:失败模式的不可枚举性
传统系统的失败是显式的:抛异常、返回错误码。Agent 的失败是隐式的:
- 一本正经地胡说:工具参数编造一个不存在的 ID,工具返回空结果,它接着往下编
- 无限循环:search → 结果不满意 → 再 search → 循环到 token 上限
- 目标漂移:让它查订单,它查着查着开始给用户写退款邮件
所以生产级 Agent 必须有"笼子",下面是我们踩坑后沉淀的最小安全结构:
typescript
// agent-guard.ts - 生产级 Agent 循环的最小安全结构
interface StepBudget {
maxSteps: number; // 硬性步数上限
maxSameToolCalls: number; // 同一工具最大连续调用次数
tokenBudget: number; // token 预算
}
async function runAgent(goal: string, budget: StepBudget) {
const counts: Record<string, number> = {};
let tokensUsed = 0;
for (let step = 0; step < budget.maxSteps; step++) {
const action = await llm.decide(goal, history, TOOL_SCHEMA);
tokensUsed += action.tokens;
// 护栏 1:token 预算熔断
if (tokensUsed > budget.tokenBudget) {
return fallback(action.partialResult); // 降级返回部分结果
}
// 护栏 2:防死循环 ------ 同一工具连续调用超限
counts[action.tool] = (counts[action.tool] ?? 0) + 1;
if (counts[action.tool] > budget.maxSameToolCalls) {
return escalateToHuman(goal, history); // 升级人工,而不是硬编
}
// 护栏 3:关键操作白名单 + 参数校验,拒绝"编造的 ID"
if (DESTRUCTIVE_TOOLS.has(action.tool)) {
const ok = await validateParams(action.params);
if (!ok) { history.push(reject(action)); continue; }
}
const result = await execute(action);
history.push(result);
}
return fallback("max_steps_reached");
}
没有这三层护栏的 Agent,我不建议任何团队上生产。demo 和生产之间隔着的不是功能,是护栏。
三、那到底什么时候该用 Agent?
我的判断标准就一条:任务的路径无法预先枚举,且单次失败的代价可承受。
适合 Agent 的场景:
- 开放式的研究/检索类任务(查资料写报告,错了能看出来)
- 探索性调试(路径真的不可预知)
- 人的时间远比 token 贵的高价值低频任务
不适合的场景:
- 支付、库存、权限等强一致性操作(该用状态机就用状态机)
- 高 QPS 的在线核心链路(延迟和成本都扛不住)
- 输出必须 100% 符合格式规范的场景(用结构化生成,别让模型"决定")
一个务实的架构是混合模式:90% 的确定性路径走工作流,只有兜不住的长尾请求才升级给 Agent 处理,Agent 的结果再回流到评估流水线里沉淀成新规则。这样 Agent 是你的"疑难杂症科",而不是"全科门诊"。
四、总结
劝退 Agent 开发的声音,本质上是在劝退"把 Agent 当银弹"的思路。Agent 是一种用成本和不确定性换灵活性的工具,它的引入应该由评估数据驱动,而不是由技术热情驱动。
给三个可执行的建议:
- 先建评估,再写 Agent------没有评分流水线就没有回归能力
- 给循环上护栏------步数预算、死循环检测、危险操作白名单,一个都不能少
- 默认走工作流,Agent 只做长尾兜底------把它当疑难杂症科,不当全科门诊
Agent 工程化还处在早期,工具链一年后一定会比今天成熟得多。但无论工具怎么进化,"确定性优先、概率性兜底"这条架构直觉,大概率不会变。