第一次把 CuberBuddy 赛博搭子的流程从头走一遍时,我先遇到的问题很具体:它太容易开口。模型回答得聪明与否,反而排在后面。
一个主动找人的助手看起来很有吸引力:它可以提醒开始、询问进度、在结束后帮忙整理。但如果每个节点都变成一条消息,所谓“主动”很快就会变成新的通知噪音。效率工具原本要帮人少分心,最后却让人花时间处理它自己。
问题发生在开始之前
我想解决的场景很小。一个人知道今天要学习、写东西或者推进项目,却总把开始往后推。Todo 要等人主动打开,番茄钟只能在开始之后计时,聊天机器人则等着被提问。真正卡住的地方,往往是“还没有开始”这一分钟。
CuberBuddy 的核心也不在计时本身。它把行动拆成几个能被记录的状态:准备、开始、暂停、结束和复盘。用户可以在微信里说一句“我先整理二十五分钟的资料”,也可以翻转实体沙漏开始。系统要做的是把模糊的愿望压缩成一个现在能做的动作,不替用户写一份漂亮的计划。
主动不等于一直出现
我给它留下三个合适的出场时机。开始前,它只需要问“现在准备做哪一步”;暂停时,它要区分卡住、被打断和主动休息;结束后,它再要求一句产出,把结果写入时间线。执行中尽量安静,除非用户明确需要帮助。
这条边界比“让 Agent 更像朋友”有用得多。人格可以慢慢调整,时机却必须先固定。如果没有状态机,模型很容易把每一次沉默都解释成需要关心,最后变成一个热情但无法关闭的提醒器。
沙漏不是装饰
实体沙漏在这里的作用也很具体:把“我现在开始”变成一个现实动作。翻转之后,设备通过 HTTP 把状态送到后端,助手再回一条短消息,确认这次专注已经开始。它不能替代对话,也不应该成为产品的炫技部分;如果没有沙漏,文字流程依然要完整可用。
技术上,状态层要保存开始、暂停、恢复和结束的时间,不能只保存一个布尔值。重复点击要有幂等键,网络重试不能制造两次开始;消息发送失败时,时间线仍应保留本地状态,下一次同步再补发。这样才能区分“用户没有开始”和“提醒没有送到”。
这几个失败分支应该在没有模型参与时就能测试。给状态机喂一组固定事件:重复开始、暂停后断网、结束后再次结束、消息发送超时。测试要看的结果是状态不乱、失败原因可读、重试不会重复计时。模型只处理自然语言,不能成为状态正确性的唯一来源。
我还给主动消息加了一个很朴素的预算:同一任务在一个时间窗口里最多出现几次,用户明确说“先别提醒”后就暂停主动消息。这个开关要放在用户能找到的地方,不要藏在一段提示词里。越是主动的系统,越需要一个确定的安静按钮。
复盘不是一篇总结
结束时我不想让系统生成一段看起来很完整的鸡汤。它只问三件事:这轮实际做了什么、卡在哪里、下一步是什么。内容短一点没有关系,只要第二天回来时能从下一步继续,而不是重新猜昨天做到了哪里。
这也提醒我,主动型工具的价值不在消息数量,而在它能否把一次行动变成可继续的记录。模型可以负责理解自然语言、整理句子和识别暂停原因;开始的决定、任务的边界和是否继续,仍然应该留给使用者。
如果以后要做长期复盘,时间线也不能只存模型生成的总结。原始事件、用户确认过的产出和模型整理的文本应该分开保存。这样用户发现总结不准确时,可以改掉一段话,却不需要改写已经发生的开始和结束时间。记录的可信度来自可追溯,而不是来自句子听起来有多顺。
现在回看这个项目,我更在意让它在最需要出现的三分钟里出现一次,然后安静下来。功能表可以慢慢补,工具如果能少说一点,反而更像一个可靠的搭子。