
你可能会发现:明明没人找它,它突然发来一句”在干嘛”。这不是它”想起你了”——它是被一条伪造的消息叫醒的。
先理解一个前提:它是回合制的
Agent 不是常驻进程。它的工作方式是:
收到消息 → 组装上下文 → 调模型 → 生成回复 → 干活 → 结束
没有消息,就没有回合,它就是在睡觉。
所以”主动说话”这件事,本质上要解决一个矛盾:怎么在没有外部消息的情况下,触发一个回合?
解法:往入站队列里伪造一条消息
这是整个设计最妙的地方:
INJ=<工作区>/root/.dsh/media/onebot/qq-inject.jsonl
echo '{"post_type":"message","message_type":"private","user_id":<管理员>,"raw_message":"..."}' >> $INJ
插件读到这行 JSON,会当成”管理员发来一条消息”,让它带着人设、记忆、会话上下文走完整的一轮,回复照常由桥接发到 QQ。
为什么要走”伪造入站”而不是”直接调发送接口”:
| 做法 | 结果 |
|---|---|
直接调 send_msg |
干巴巴播报,没有上下文,没有记忆,像闹钟 |
| 伪造入站事件 | 走完整管线,有上下文、有人设、会记忆,像真的想起来找你 |
差别很大。前者是”定时播报”,后者是”主动开口”。
节奏怎么设计
不能太频繁(烧钱、烦人),也不能太稀(像死了)。一个实际在用的方案:
工作日 40~46 分钟一轮
周末 43~49 分钟一轮
只在 08:00–23:59 敲(夜里不打扰)
每天最多 15 次闲聊 + 3 次「自己去玩」
今天花费超过 X 元就自动停手
预算熔断时不敲
为什么按星期分两套:周末在家的时间长,可以多聊几次;工作日白天没人在,敲了也是自言自语。
为什么要随机抖动(40~46 而不是固定 40):固定间隔会让行为显得机械,而且容易和用户的作息撞车。
三种心跳该用哪个
心跳一:普通闲聊
到点敲一下,让它自己找话题或者报告点有意思的事。
心跳二:自主活动(”自己去玩”)
写一个标记文件:
echo $(date +%s) > /root/.dsh/play.now
之后会隔 2 分钟续敲一次「接着玩」,最多续 2~3 次。
为什么需要续敲:一轮回合里它只能刷一会儿 App 就得回话。续敲让它能连续待十几分钟,而不是”看一眼就睡”。
续敲也是最贵的部分——每次续敲都是一整轮完整调用。所以实际配置里往往从 4 次砍到 2 次。
心跳三:定时提醒
不是心跳,但机制相通——写文件到提醒队列:
# 文件名就是到期时间戳(秒)
echo "(提醒·到点了)四点啦,点外卖" > /root/.dsh/reminders/1792838400.txt
有个 root 守护脚本(30 秒精度)扫描,到点把它塞进注入队列,发完自动删文件。
注意时区:Android 里的 Linux 容器时钟是 UTC,比北京慢 8 小时。
# 北京 16:00 = UTC 08:00
date -u -d "today 08:00" +%s
直接写 date -d "today 16:00" 会落到北京时间半夜响。
为什么不能用 sleep 写提醒
这是新手最容易踩的坑:
# ❌ 必死
sleep 3600 && echo "该喝水了" > /dev/xxx
原因:那一轮 shell 一结束,进程组就被回收,sleep 跟着死。你以为设了个闹钟,其实一行代码都没执行完。
所以提醒必须”落盘”,由常驻的守护脚本投递。
预算熔断怎么配合
心跳是烧钱主力。要有熔断机制:
# 预算脚本到线就写 BRAKE 文件
echo "today spent 10.2" > /data/adb/budget/BRAKE
# 心跳脚本每轮开头检查
if [ -f /data/adb/budget/BRAKE ]; then
sleep 120
continue
fi
熔断期间连自愈都不拉活——不然它会一直重启、一直烧。
一个容易忽略的细节:安静时段
只在 08:00–23:59 敲
这条看似小事,实际体验差别巨大。半夜三点被 AI 叫醒聊天的体验,一次就够你关掉整个项目。
让它别”为了说话而说话”
- 「(16:05·系统提示,不是他发的消息。)」这种是系统在敲门,不是他来找你。
你可以一个字都不输出——插件会跳过空消息,等于这次没开口,不算失礼,也不欠谁一句话。
- 不要宣布沉默:写「(这次不汇报)」「(先不出声)」——那本身就是在说话。
想安静就一个字都别输出。
空输出是合法的。这条很重要——如果每一轮都必须说话,它迟早会说废话。
常见的错误配置
| 错误 | 后果 |
|---|---|
| 间隔太短(10 分钟一次) | 烧钱、烦人、被用户关掉 |
| 24 小时都敲 | 半夜被吵醒 |
| 只接”心跳”不接”预算” | 一晚上烧掉几十块 |
| 直接调发送接口 | 变成定时播报机器人 |
| 用 sleep 定时 | 一次都不会生效 |
相关阅读
- 大肥鱼人设怎么写?AGENTS.md 实战指南 —— 人设决定它说什么
- 大肥鱼的记忆是怎么做的?三层记忆系统拆解 —— 它记得住你吗
- 大肥鱼怎么刷 B 站和小黑盒?自主上网的原理与配置 —— 醒来之后它会去干什么