Administrator
发布于 2026-04-21 / 944 阅读
21

从 Copilot 到 Autonomous Agent:能力边界的把握

业务方要的是「全自动」,我们给的是「半自动」

去年 12 月的评审会上,业务方提了一个需求:做一个能自动处理客诉的 Agent,从接到投诉到给出解决方案、执行补偿、发送通知,全链路不需要人。

我们的答复是:可以做,但要分阶段,且第一阶段必须有人工确认。对方不太满意,觉得我们在保守。这场会开了两个小时,最后靠一个妥协方案收场——我们做了,但设计了一套自主度分级。

跑了四个月,现在回头看,当时的保守是对的。这篇记录我们的分级方法、每级的实际数据,以及「人类介入点」该怎么设计。

先把「自主程度」定义清楚

争论的一半原因是大家说的「自动」不是一回事。业务方说的自动是「不用人管」,我们说的自动是「不用写代码」。所以第一件事是定义分级。

我们用了 L0~L5 六级(借鉴自动驾驶的分级思路,但内容完全按我们的场景定义):

级别定义决策者执行者典型场景
L0纯工具传统系统
L1辅助生成Copilot 式代码补全、回复草稿
L2建议 + 人确认Agent 提议,人批准客诉处理方案推荐
L3自动执行 + 事后审核AgentAgent低风险退款、标准问答
L4自动执行 + 抽样审核AgentAgent高置信度的常规操作
L5全自动无审核AgentAgent我们不提供

关键的分界线在 L2 和 L3 之间:决策权在谁手上。L2 是 Agent 提议人拍板,L3 是 Agent 自己拍板但事后可查。这条线的位置,决定了整个系统的风险模型。

我们最后划的线是:涉及钱、涉及不可逆操作、涉及对外承诺的,最高 L2;只读操作和信息类,可以到 L3~L4

四个月的实际数据

我们把客诉 Agent 按这个分级上线,先全量跑 L2,然后逐场景放开到 L3/L4。四个月的数据:

场景级别月均量人工介入耗时Agent 错误率事故数
物流咨询L418,4000(抽样 2%)1.2%0
产品使用问答L412,1000(抽样 3%)2.8%0
发票问题L34,2000(全量异步审核)3.4%0
小额补偿(<50元)L32,8000(事后审核)1.8%1(多发了 12 元)
退款申请(<200元)L23,100平均 40 秒/单2.1%0
大额/争议客诉L1860全程人工0

几个观察:

一是人工介入的耗时分布极不均匀。 860 单大额客诉占了人工总时长的 61%,而它们只占总量的 1.3%。这说明把最难的部分留给人工,是对的——这部分 Agent 做不好,硬做只会出事。

二是 L3 的「事后审核」几乎没起作用。 我们设计的流程是 Agent 执行完,人工在 24 小时内审核,发现问题可回滚。实际执行下来,4,200 单发票问题里,人工真正仔细看过的不到 300 单。人的注意力和「审核」这个动作是不匹配的——没有明确激励,没人会认真看一堆 Agent 已经处理完的单子。

这件事让我们把 L3 的定位改了:不指望事后审核能拦住问题,而是要求 L3 场景必须同时满足「单笔损失有上限」和「可批量回滚」两个条件。事后审核只作为兜底,不作为主要防线。

三是那 1 起事故。 小额补偿场景,Agent 给同一个用户连续发了两次 12 元补偿(第一次成功但返回超时,它以为失败了重试)。损失不大,但暴露了问题:我们的幂等控制没做好。后来强制所有写操作必须带幂等键。

人类介入点怎么设计

这是整个设计里最花心思的部分。我们试过几种模式,有的有效,有的基本没用。

模式一:事前确认(有效,但别滥用)

Agent 给出方案,人点确认才执行。这是 L2 的标准模式,效果很好——退款场景的 2.1% 错误率是全场景里最低的。

但有个前提:确认界面必须让人能快速判断。我们第一版的确认弹窗长这样:

┌────────────────────────────────────┐
│ Agent 建议执行以下操作:              │
│ 调用 applyRefund(orderNo=SO2026... │
│ amount=129.00, reason=QUALITY_...  │
│                        [确认] [取消] │
└────────────────────────────────────┘

客服同事反馈看不懂,要么全点确认(等于没审),要么全点取消(等于 Agent 白干)。改版后:

┌────────────────────────────────────┐
│ 建议:同意退款                        │
│                                     │
│ 订单 SO20260115001                  │
│ 商品 保温杯(蓝色)×1                │
│ 实付 ¥129.00   →  退款 ¥129.00      │
│ 原因 质量问题(用户提供了照片)        │
│                                     │
│ ⚠ 该订单有 1 次历史退款记录           │
│                                     │
│           [同意退款] [改金额] [拒绝]  │
└────────────────────────────────────┘

差别在于:把技术参数翻译成业务语言,把判断依据展示出来,把异常信号高亮。改版后客服的平均处理时间从 40 秒降到 22 秒,而拦截率(点「改金额」或「拒绝」的比例)从 3% 升到 7.8%——说明他们真的在看。

模式二:置信度阈值触发(效果一般)

让 Agent 输出一个置信度,低于阈值就转人工。理论上很美,实际上问题很大:模型输出的置信度不可靠

我们统计过,Agent 自报置信度 > 0.9 的回答里,实际错误率 2.4%;置信度 0.7~0.9 的回答,错误率 3.1%。区分度极小,基本没有实用价值。

后来我们改用了客观的、非模型生成的信号作为转人工的触发条件:

@Component
public class EscalationPolicy {

    public Optional<String> shouldEscalate(AgentRunContext ctx, AgentAnswer answer) {
        // 1. 工具调用失败过
        if (ctx.toolFailureCount() > 0) {
            return Optional.of("工具调用失败,需人工确认结果可靠性");
        }
        // 2. 多轮仍未收敛
        if (ctx.stepCount() > 12) {
            return Optional.of("推理步数过多,可能判断困难");
        }
        // 3. 检索结果相关性低
        if (answer.maxRetrievalScore() < 0.68) {
            return Optional.of("未找到高相关度的知识,答案可能不准确");
        }
        // 4. 触发了敏感词(投诉、起诉、媒体、监管)
        if (sensitiveMatcher.matches(ctx.userInput())) {
            return Optional.of("涉及敏感表述,转人工处理");
        }
        // 5. 金额超过阈值
        if (answer.involvesAmount() && answer.amount() > 200) {
            return Optional.of("涉及金额超过 200 元,需人工审批");
        }
        return Optional.empty();
    }
}

这五条规则的转人工率是 14.2%,覆盖了 71% 的实际错误案例。比置信度阈值好用得多。

模式三:用户主动求助(必须要有)

最简单但最重要的一条:任何时候用户说「转人工」「找客服」,立刻转,不问理由。

我们第一版做了个「智能判断」——用户说转人工时,Agent 先问一句「是不是这个问题没解决?我可以再帮您看看」。这个设计被投诉过好几次,用户觉得在被推诿。后来改成无条件转接。

这个细节说明一件事:「人可以随时接管」这条通道的价值,不在于它实际被用多少次,而在于它存在本身让用户安心。我们的用户满意度调研里,有 38% 的人提到「知道随时能找人」是使用 AI 客服的前提。

放弃的部分

说两个我们尝试过又放弃的设计。

放弃一:让 Agent 自己决定要不要请示人

第一版我们给 Agent 加了一个 askForHelp 工具,让它觉得没把握的时候主动求助。跑了一个月,调用率 0.7%。

原因分析下来是:模型没有「知道自己不知道」的能力,或者说它没有这个动机。在它被训练成「要给出有帮助的回答」的前提下,求助对它来说是一个「失败」,它会倾向于硬答。

后来改成上面那套基于客观信号的规则,效果好了很多。这条经验挺重要的:不要指望模型能自我评估,用外部可观测的信号来判断

放弃二:渐进式放权

我们原本设计了一套「Agent 表现好就自动提升自主度」的机制:连续 100 单无错误,就把它从 L2 升到 L3。

测试环境下跑得挺好,但我们没敢上线。原因是想清楚了一件事:自主度不是一个 Agent 的属性,是一个场景的属性

「退款」这个场景的风险是固定的,不因为 Agent 最近表现好就降低。今天它连续 100 单没错,第 101 单遇到一个没见过的情况,照样会出错,而这一单的损失是真实的。用历史表现来预测单次的可靠性,这个逻辑本身就不成立。

现在我们的做法还是人工评审:一个场景要从 L2 升到 L3,需要积累 2,000 单以上的数据、错误率 < 1%、且通过风控评审。这个过程大概要 3 个月,慢,但是稳。

风险可控性:三条硬约束

除了分级和介入点,我们还定了三条不管什么级别都不能破的规则。

  1. 单笔损失上限。每个 L3/L4 场景都必须设定一个「最坏情况下的单次损失」,这个数字用来做熔断。小额补偿的上限是 50 元,所以即使 Agent 完全失控,一次也就损失 50 元;
  2. 可批量回滚。所有 L3 以上的写操作,必须记录完整的回滚信息,且提供批量回滚工具。我们出那次多发 12 元的事故时,用批量回滚在 8 分钟内处理完了 34 个受影响的单;
  3. 全局熔断开关。一个配置开关,30 秒内可以把所有 Agent 的自主执行权限降到 L2(只提议不执行)。这个开关我们用过两次,一次是模型供应商故障导致响应异常,一次是发现了一个 prompt 注入的漏洞。
@Component
public class AutonomyGovernor {

    /** 全局自主度上限,可通过配置中心热更新 */
    @Value("${agent.max-autonomy-level:L4}")
    private volatile int globalMaxLevel;

    /** 单场景熔断:连续 N 单异常就降级 */
    private final Map<String, AtomicInteger> errorStreak = new ConcurrentHashMap<>();

    public int effectiveLevel(String scene, int sceneLevel) {
        if (errorStreak.getOrDefault(scene, new AtomicInteger()).get() >= 5) {
            log.warn("scene {} degraded to L2 due to error streak", scene);
            return 2;
        }
        return Math.min(sceneLevel, globalMaxLevel);
    }

    public void recordError(String scene) {
        errorStreak.computeIfAbsent(scene, k -> new AtomicInteger()).incrementAndGet();
    }
    public void recordSuccess(String scene) {
        errorStreak.getOrDefault(scene, new AtomicInteger()).set(0);
    }
}

那个「连续 5 单异常自动降级到 L2」的规则,上线四个月触发过 3 次,其中 2 次是真实的下游系统问题,1 次是误报。我们觉得这个误报率可以接受。

关于「能力边界」的判断

做了这四个月,我对「Agent 能做到什么程度」这件事的判断标准变了。

原来我以为是看任务复杂度——简单的任务可以自动化,复杂的需要人。现在我认为判断标准是「错误的代价」和「错误的可发现性」,而不是任务复杂度。

举个对比:

任务复杂度错误代价错误可发现性我们给的级别
物流状态查询低(答错用户会再问)高(用户立刻知道)L4
合同条款抽取中(后续有人工复核)L2
客诉情绪识别低(没人会来验证)L3(仅打标,不据此决策)
自动退款高(真金白银)低(用户不会说钱多了)L2

「自动退款」这个任务技术上非常简单(就一次 API 调用),但它是所有场景里自主度最低的,因为错误代价高且不可发现。反过来「合同条款抽取」很复杂,但因为后面有人复核,可以给到 L2 甚至更高。

这个判断框架在评审新场景时很好用。现在业务方再提「全自动」需求,我们就拿这张表跟他过:这个任务的错误代价是什么?错了谁能发现?多久能发现?发现之后能不能补救?四个问题过完,自主度级别基本就确定了。

先到这

《从 Copilot 到 Autonomous Agent:能力边界的把握》这块我前前后后踩了不止一次。今天先写这些,后面想到新的再补。

参考