简介:主动型Agent做不好的原因,大多不在模型能力,而在行为控制架构。本文基于实战复盘,对比行为决策层的“提示词软约束与状态机闸门”、消息守门层的“大模型自判与轻量守门人”两类方案,从决策空间、稳定性、成本延迟、可运维性等维度拆解差异,并给出场景化选型建议与迁移注意事项。
先明确本文的对比对象。被动式Agent要等用户提问才干活;而主动型Agent(proactive agent,主动型智能体)则在不被提问的情况下自行寻找任务:盯日程、扫邮件、看代码库变更、收集外部反馈,在合适的时机主动开口甚至直接行动。它更“聪明”,但也更难做对。
难到什么程度?一项覆盖3660个测试实例、14个手机场景的公开评测显示,通用能力最强的模型成功率仅7.39%,专门为此微调过的开源模型也只有19.15%。很多开发者的第一反应是“换个更强的模型”,但实战复盘给出的结论恰恰相反:真正卡住项目的环节几乎都与模型能力无关,而是集中在两个工程决策层:
围绕这两层,本文对比两组共四种工程方案:
方案A:提示词软约束。 把行为规范写进系统提示词,例如“不要打扰用户,只报真正重要的事”,期望模型在每次推理时自觉遵守。这是最直觉的起步方案,改动成本几乎为零。
方案B:状态机+闸门硬控制。 把“要不要开口”从二元问题显式建模为四选一动作空间:沉默、询问、协助、执行。沉默是默认分支,其余三个动作必须通过闸门放行。闸门检查四条硬条件:状态是否真变化、证据是否充分、动作是否在白名单内、该时间点用户是否在忙。
方案C:大模型自判守门。 让负责写消息的模型自己判断这条消息该不该发。模型既当运动员又当裁判,凭借对“重要性”的语言化理解做决定。
方案D:规则+小模型守门人。 把守门逻辑从生成模型中拆出来,用轻量规则与小型模型实现,输出只有三个离散结果:现在发、进摘要、丢掉。单次判断几十毫秒,成本近零。
在谈差异之前,先看清它们共同的地方,这决定了比较的公平性:
提示词方案的决策空间是隐式的。它把“说不说”当成非此即彼的二元问题,而且由于提示词只笼统地说“少打扰”,模型实际学到的默认行为是“有变化就报”——沉默被从选项表里删掉了。这正是第一版把主动做成“勤快”的根源:日程、邮件、代码库、外部反馈全接上,触发条件写得很宽,任何一处变化都值得报一声。
状态机方案则把四个动作全部显式化,并把沉默设为默认分支:不满足闸门条件,就什么都不发生。实测结果是,推送从每天20多条降到3条以内,采纳率反而从30%多涨到70%多。这说明克制不等于少干活,而是让每一次开口更有分量。
提示词约束的本质是“每次推理时的临场劝说”。实践记录很典型:照做了3天,第4天开始失灵。原因有二:一是模型判断“重要”的标准随上下文漂移,今天觉得要紧的事明天就可以放一放;二是它根本不知道用户当时在开会还是在写代码。用提示词管打扰,相当于让写手自己批采访许可——既当执笔者又当审查者,缺少外部硬约束。
状态机是确定性代码:条件不满足就不放行,行为可复现、可审计、可回归测试。漂移问题从“概率事件”变成“不可能事件”,因为判断标准被固化在了代码里。
提示词方案中,用户当前状态(在开会、在专注写代码、在休息)只是提示词里的一段描述,模型无法可靠地将其纳入判断。状态机方案则把状态信号作为闸门的硬输入之一——“这个时间点用户是不是在忙”是四条放行条件之一,不满足直接落入沉默分支。感知能力的差别不在于“知不知道”,而在于“知道了之后有没有结构化的地方去用”。
大模型擅长把话说漂亮,不擅长算账。一条消息该不该发,等价于一次下注:赌它带来的价值能否盖过打断用户的成本。而这笔账是可以拆成可计算的量的——事情有多大、用户据此前置行动的概率多高、机会多久过期、这份价值属于用户还是属于平台。
这类结构化计算,规则和小模型比大模型更稳定:输入是明确的量纲,输出是明确的三值结论,天然适合监控、调参和版本管理。交给大模型凭语感判断,输出不稳定,也无法解释“为什么这条被拦下了”。
大模型自判意味着每个触发点都要跑一次完整推理。一天几百个触发点,token成本和延迟都撑不住,判断还随输入波动。轻量守门人单次仅30多毫秒、成本近零,才能筛得起几百个触发点。守门人必须便宜,这是它能前置部署在所有触发点上的前提——贵的东西只能放在链路末端,便宜的东西才能铺满全程。
状态机与守门人的输出是离散、可枚举的(沉默/询问/协助/执行,现在发/进摘要/丢掉),可以做单元测试、灰度发布、指标监控与版本回滚;提示词与自由生成则难以做确定性回归,每次调优措辞更像碰运气,出问题也难以定位到具体原因。对需要长期运行、持续迭代的线上系统而言,这个差异往往比单次效果更关键。
表1:行为决策层对比(提示词软约束 vs 状态机+闸门)
| 对比维度 | 提示词软约束 | 状态机+闸门 |
|---|---|---|
| 决策空间 | 隐式,倾向二元(报/不报) | 显式四选一(沉默/询问/协助/执行) |
| 默认行为 | 有变化就报 | 沉默为默认分支 |
| 行为一致性 | 随上下文漂移,约3天后失灵 | 确定性,可复现 |
| 用户状态感知 | 弱,仅作为文本描述 | 作为闸门硬条件 |
| 可测试性 | 难做确定性回归 | 条件可单测、可审计 |
| 调优方式 | 改措辞,靠运气 | 调条件,看指标 |
表2:消息守门层对比(大模型自判 vs 规则+小模型守门人)
| 对比维度 | 大模型自判 | 规则+小模型守门人 |
|---|---|---|
| 单次延迟 | 秒级 | 几十毫秒(实测30多毫秒) |
| 单次成本 | 高 | 近零 |
| 判断稳定性 | 随输入波动 | 稳定、可解释 |
| 规模适应性 | 一天几百次即吃紧 | 可覆盖数百个触发点 |
| 表达能力 | 强(可兼写消息) | 无生成能力,只判不写 |
| 适用环节 | 最终生成与高价值判断 | 前置初筛与批量过滤 |
以下伪代码展示两类方案的核心结构(通用示例,不依赖任何特定工具):
# 行为决策层:状态机 + 闸门(示意)def decide(event, user_state):# 四条硬条件,任一不满足即回到默认分支if not is_real_change(event): return "SILENT" # 状态无真变化if not evidence_sufficient(event): return "SILENT" # 证据不足if event.action not in ACTION_WHITELIST: return "SILENT" # 不在白名单if user_state.is_busy(): return "SILENT" # 用户正忙return route_to(event) # 通过闸门后分流:ASK / ASSIST / EXECUTE
# 消息守门层:轻量守门人(示意)def gate(msg, ctx):value = value_score(magnitude=how_big(msg), # 事情有多大p_act=action_probability(msg), # 用户据此前置行动的概率urgency=expiry(msg), # 机会多久过期owner=value_owner(msg), # 价值属于用户还是平台)cost = interruption_cost(ctx) # 当前状态下的打断成本if value > cost and not expired(msg): return "SEND_NOW"if value > DIGEST_THRESHOLD: return "TO_DIGEST"return "DROP"
综合来看,不建议在四类方案中做非此即彼的选择,更合理的做法是分层组合:状态机定骨架,守门人做初筛,大模型做表达。具体条件化建议如下:
从提示词软约束迁移到状态机+守门人结构时,有几件事需要提前规划:
主动型Agent的坑,几乎都不在模型能力上,而在两个决策层的控制方式上:要不要开口,应把沉默还给动作空间,用状态机和闸门替代提示词里的临场劝说;要不要发送,应把这笔“价值能否盖过打断成本”的账,从大模型的语感判断手里拿走,交给便宜、稳定、可解释的轻量守门人。提示词软约束适合原型期快速试错,状态机与守门人适合长期运行的线上系统,大模型则应被安置在它真正擅长表达与理解的位置上。选型的关键不是“哪个方案更好”,而是“哪个决策层、什么规模、多大的确定性要求”——想清楚这三问,主动型Agent才能既找得到活干,又懂得什么时候闭嘴。