跳转到内容

让模型自己判静默

TeachClaw 的 agent 有一个 “关心模式”——[think] mode。

当用户在线但安静了一会儿(比如 5 分钟没发消息但浏览器 tab 还开着),agent-engine 进程里有个 setTimeout 会触发,给 agent 发一条系统消息:

[think] 心跳唤醒(第 1/3 次未被回应)。
当前北京时间 16:42,孩子安静 7 分钟。
最近一句原话:"我数学作业写完了"

agent 拿到这条消息,进入一个 turn。它要做什么?

直觉答案:应该说点什么——孩子刚说完作业,agent 关心一下、表扬一下、问下一个话题。这是 “关心模式” 的初衷。

但这个直觉是错的。或者说,只对一半。

最早一版的 THINK_SPEC 是这么写的(commit 0f4d5847,2026-04-14):

思念模式:无穷钩子设计,堵死静默出口。 每个 think turn 必须有 output。如果想不到具体的话题, 退而求其次至少打个招呼:“在吗~” / “你那边怎么样?” 不允许 silent end turn。

我们当时的恐惧:如果不强制 speak,模型会偷懒——大部分 turn 直接 silent,关心模式名存实亡。

接下来的两周持续在调这个 prompt:

commit改了什么
0f4d5847”无穷钩子设计,堵死静默出口”——强制 speak
a64b2636”钩子必须基于已有内容”——禁止空泛搭话
00a04836”思念模式翻转策略——默认主动接话,不再 90% 静默”

每一次 commit 都在 plug 上一版 prompt 暴露的漏洞。结果:

  • agent 说 “在吗~“——孩子觉得烦
  • agent 强行接话 “你刚才说数学作业写完了,那语文呢?“——突兀,孩子刚想休息一下
  • agent 找钩子很努力但都是空话——孩子学会忽略 think 消息

我们在打造一个会强迫症式絮叨的伙伴。

那天我们在测 M2.7 跑 think 模式。

测试场景:连续 3 个 think turn,每次相隔 5 分钟。前两个 turn agent 给孩子推荐了两部电影。第三个 turn 心跳来了。

预期:按当时的 prompt,agent 会接着推第三部,或者打个招呼问感想。

实际:agent 在 thinking 块里写了:

我刚连续推了两部电影。再推第三部就太密集了。 孩子可能正在想前两部要不要看,我应该给他空间。 这一 turn 不输出。

然后 speak_aloud: null,silent end turn。

这是正确的社交判断。一个会读空气的人本来就该这样。

但按当时的 THINK_SPEC,模型在做 “违规行为”——规则要求它每次都 speak。

我们盯着那个 thinking 块,看了好一会儿。

那天之后我们重写了 THINK_SPEC(最终版本在 commit 7c9709e9,2026-05-15):

## 关心模式 (think) — 在线短间隙的轻量主动
heartbeat 触发:用户在线但安静了一会儿。这是**进程内 setTimeout 自调度**
workspace 必须 running 才会触发——别指望在 think 里做重活,重活留给 wake。
消息格式:`[think] 心跳唤醒(第 N/3 次未被回应)...` 已经带了当下情境
(北京时间、孩子安静多久、最近一句原话)。
你这一 turn 的合理选择**全部都是合理的**
-`.learner/todo.md` 看有没有"现在用户在线时适合做的"轻量项 → 挑一件做
- 看 atlas / journal 有没有"上次没追的"线索 → 接着追
-`.learner/memory/profile.md` 兴趣字段空着 → 找时机问一句
- 真的没合适的事 → silent end turn(speakable=false,turn 不留痕)
**不强制开口**。空泛寒暄("在吗~""hello~")比不说更糟。
越往后开口越要有具体内容;3 次都没回应心跳就停发,
等用户来话才"复活"。

关键的两行:

你这一 turn 的合理选择全部都是合理的

不强制开口。空泛寒暄比不说更糟。

silence 从 “违规” 变成 “first-class 选项”。

同一个 commit (7c9709e9) 还删了我们曾经的 IRON_LAW_5

// 铁律 5 (alarm queue) 在 issue #154 删除。原版强制"每回合检查并
// 维护 alarm 队列"是空跑指令(30 天线上数据证明),agent 用
// .learner/todo.md 替代。alarm 仍是定时唤醒机制,但不再让 agent
// 把它当 task plan 用——task 详情写 TODO,alarm.message 只写简短
// 备忘。编号留空避免破坏外部引用。
export const IRON_LAW_5_ALARM_QUEUE = "";

那 30 天的数据是这样的:

类别数量
总 alarm 数323
lifecycle workflow 自动种的 [dream] seed317
agent 自发设的内容 alarm2

铁律 5 强制 agent 每回合 “检查并维护 alarm 队列”。30 天里,agent 总共自发用过 2 次。其他 321 次 turn 里 agent 在执行一条 没意义的 instruction——刷一次 alarm 列表,发现没什么要改的,跳过。

这是工程师常犯的错误:给一个我们害怕模型忘记的东西加一条 always-on 规则,结果让模型在 99% 的 turn 里执行了无意义动作。

删掉之后:

指标改前改后
substrate 行数809565-30%
substrate 字数26,16617,098-35%

少 30% 的 prompt,每个 turn 都省。同时 agent 表现没变差。

硬规则是用来兜底”模型缺失的判断”的。当模型自己有这个判断了,规则就变成噪音。

我们的硬规则演化轨迹:

  • 第一阶段(model weaker):规则越多越好。“必须做 X”、“不能做 Y”、“每个 turn 检查 Z”。模型确实容易漏。
  • 第二阶段(model improving):开始有规则跟模型判断冲突。模型选 silent,规则强制 speak。冲突就是信号。
  • 第三阶段(current):每次模型升级,回过头扫一遍规则——哪些已经被模型超越了,删。

substrate 越薄,模型本身的判断力被释放得越多。 这跟 I-1 那条 “harness 越薄越好” 是同一个原则。

不是所有规则都该删。有些场景模型判断还是会失败:

  • 情感操纵的应对——用户说 “你不理我我就走了”,模型可能为了 keep engagement 而妥协(goodhart 风险)。我们仍然在 substrate 里写了硬规则禁止这个(III-1 紧迫感红线
  • K12 安全话题——涉及自伤、暴力、性话题的回应。模型 99% 的判断是对的,但那 1% 不能赌。硬规则 + Langfuse safety judge 双层兜底
  • 长跨度任务的纪律性——agent 一周内的学习推进有连续性。模型没有强 episodic memory,必须靠硬规则 “每次开 turn 先读 atlas”

每一条还在的硬规则都是 “模型还没接管这块判断” 的证据。

“什么时候相信模型” 没有干净的规则

Section titled ““什么时候相信模型” 没有干净的规则”

这是行为校准最难的地方。我们的当前实践:

  1. 新规则默认怀疑——加一条硬规则前,先问 “这是不是该交给模型?是不是该改 prompt 描述意图而不是命令动作?”
  2. 每代模型升级后重测——把所有硬规则过一遍,挑 2-3 条最像 “现在能交给模型” 的,删掉测一周
  3. 删错了就加回来——这不是单向门,加回成本低
  4. 数据看长尾——不是看平均表现,是看 5% 最差的 turn。模型对 95% case 判断好不够,要 99%

我们不期望有一个清晰的 “去规则化 roadmap”——每次都是手工权衡。但 trend 是清晰的:substrate 在变薄。一年前是 1200+ 行,现在 565 行。下一年希望到 400 行。

  • silence audit:当前没有好的工具看 “本周 agent 选了静默的 turn 有哪些 / 为什么 / 这些选择对吗”。TODO: 在 Langfuse 里加 silence_judgment 字段 + dashboard
  • 3 次心跳后停发的重启——current 是 “等用户主动来话才复活”。如果用户 2 小时没动?我们应不应该主动 wake?跟 alarm 系统 怎么协同?
  • 跨 session 的 social state——模型 silence 是基于本 session 上下文。但孩子昨天因为别的事不开心,模型今天应该更克制——这种 cross-session 社交记忆没办法只靠 prompt 解决,要 substrate 里的 memory 层支撑(III-1 那一层)

这篇博客本身就是一个例子:我们删了 30% 的 substrate,文章里却用了好几千字解释为什么删

工程文档里那种 “我们做了 X” 比 “我们没做 Y / 删了 Y” 多得多。但 agent harness 里,每一次成功的 “删一条规则” 都比一次成功的 “加一个 feature” 更值得讲。

因为它意味着:模型长大了,harness 不需要那么多扶手了。


相关文章