别再骂模型了,你的 Agent 不是不想干活,是没人叫它起床
我最近在搭一个长期跑的自治交易员,底座用的是 Hermes。
需求其实不复杂。我希望它像一个刚入职的交易员助理,每天 24 小时自己学套利、看行情、整理案例、写策略、跑模拟盘、写日记、做复盘。除非碰到开户、动钱、上实盘、放风控这种我必须拍板的事,否则别来烦我。
听上去很合理。真跑起来就出问题了。
它每轮结束都会很乖地说一句:
下一步:继续收集案例,之后搭建模拟交易环境。无需老板决策,继续工作。
然后就没有然后了。
嘴上说继续,人已经下班。
一、问题不在提示词
我一开始也以为是 prompt 写得不够狠,于是加了一堆规则:
必须持续工作
不要停下来等待
只在关键决策时请求老板
没有需要决策的事就继续推进
这些话本身没错,但解决不了问题。
因为现在大多数 Agent 产品的最小交互单位是一个 turn。它跑完这一轮、把回复吐出来,系统就认为这轮结束了,不会自动再发起下一轮。你让它"继续",它在文字里答应你,但没有外部调度器再叫它一次,下一轮就是不会发生。
很多人对 autonomous agent 的误解就在这里。你以为缺的是更强的 prompt,其实缺的是一个会按时叫醒它的 runtime。
二、别人的 Agent 凭什么能跑一整天
差别就一句话:
普通对话:用户发消息 → Agent 工作一轮 → 回复 → 停下 长期自治:调度器到点 → 新建 session → 读状态文件 → 工作一轮 → 写回状态 → 等下次调度
真正的 24 小时工作,不是让一个上下文窗口硬撑一整天,而是把长期任务切成很多个短周期:
每 30 分钟醒一次,读当前状态,挑最高优先级的任务,推进一个明确的工作单元,更新任务队列,写运行日志,然后等下一次 heartbeat。
所以长期工作真正依赖的,是 Gateway、Cron、Heartbeat 和状态文件这四样东西。
三、Hermes 里的四个部件
我最后把整套机制拆成了四层。
1. Gateway:后台闹钟
Hermes 的 cron 任务不是靠当前聊天窗口自己倒计时的。
你执行 hermes cron create ...,本质上只是把任务写进 Hermes 的任务列表。真正负责到点检查、启动任务、新建 session 的,是 Gateway。
如果你看到这样的提示:
Gateway is not running — jobs won't fire automatically. Start it with: hermes gateway install
意思就是:闹钟列表已经写好了,但没有人在后台看表。
所以第一步先把 Gateway 装起来:
hermes gateway install没有它,cron 任务能 list 出来,但不会自动跑。
2. Cron:按时唤醒 Agent
Cron 负责定义"什么时候叫醒 Agent"。这里有一个很容易踩的坑:
hermes cron create "30m" ...这一句不是"每 30 分钟运行一次",而是"30 分钟之后运行一次"。你会在列表里看到:
Schedule: once in 30m Repeat: 0/1
这就是个一次性任务。
要循环跑,正确写法是:
hermes cron create "every 30m" ...或者在聊天里:
/cron add "every 30m" "..."every 这个词是关键。
3. Heartbeat:醒来之后该干什么
Cron 只负责叫醒 Agent,醒来之后做什么不能靠它临场发挥。
我建议给每个长期任务配一个 HEARTBEAT.md,相当于交接班卡片,写清楚每次被唤醒之后必须做什么:
读取连续工作规则
读取当前状态
读取任务队列
检查是否存在阻塞
推进一个实际工作单元
更新状态文件
写运行日志
里面有一句话我特别强调:
不要只输出计划。只要没有阻塞,就必须实际推进文件、研究、代码、报告或记录中的至少一项。
这一句是用来防止 Agent 每次醒来都礼貌地说一句"下一步我会继续",然后什么都不做。
4. 状态文件:替代聊天上下文
Hermes 的 cron run 大概率是一个 fresh session,不会继承你当前聊天窗口里的上下文。
如果你在 cron prompt 里写"继续刚才的工作",它根本不知道"刚才"是什么。
所以上下文必须落到文件系统里。我一般至少会建三个:
memory/current-state.md:记录当前阶段、主任务、已完成事项memory/task-queue.md:分成 NOW、NEXT、LATER、BLOCKED、DONE 五栏memory/run-state.md:记录最近一次运行类型、完成事项、当前 focus、下一步、是否被阻塞
每次 cron 新建 session,都从这些文件里恢复上下文。
长期自治的关键就在这里:不要让聊天记录承载连续性,要让文件系统承载连续性。
四、一个通用的 Work Heartbeat 模板
写法不复杂,关键是自包含。
你是这个项目的长期工作 Agent。工作目录是 /path/to/project。 这是一次 Work Heartbeat。不要只汇报计划,必须实际推进一个工作单元,除非遇到明确阻塞。
先读取:
HEARTBEAT.md
config/continuity_policy.md
memory/current-state.md
memory/task-queue.md
memory/run-state.md
然后执行:
检查是否存在阻塞事项。
如果没有阻塞,从 memory/task-queue.md 选择最高优先级任务。
推进一个明确工作单元。
更新 memory/current-state.md、memory/task-queue.md、memory/run-state.md。
如有实质进展,在 logs/ 写一条简短运行记录。
本轮回复只需要说明:
完成了什么
更新了哪些文件
下一轮继续什么
是否需要用户决策
注意里面没有"继续刚才"这种话。它每次都靠工作目录和状态文件自己恢复。
五、建议先配三个 Cron
刚上手没必要搞得太复杂。我自己一开始就配了三个:
Work Heartbeat,every 30m,负责日常推进
Short Review,every 12h,负责短周期复盘,避免只是在堆文件
Major Review,every 48h,负责阶段性反思,更新方向和任务队列
如果你的任务只是普通资料整理,甚至可以先只开第一个。等确认它能稳定接力,再加 12 小时和 48 小时的复盘。
六、最小文件结构
任何长期任务,我建议至少保留这几个文件:
HEARTBEAT.md
config/continuity_policy.md
memory/current-state.md
memory/task-queue.md
memory/run-state.md
logs/每个文件解决的问题分别是:
HEARTBEAT.md:每次醒来做什么continuity_policy.md:长期运行规则current-state.md:当前进展task-queue.md:下一步具体做什么run-state.md:上一次运行留下的接力信息
它们其实都在解决同一件事:Agent 可以失去聊天上下文,但不能失去工作上下文。
七、Git 不要当成实时日志
机制跑起来之后,文件会频繁变化。但我不建议让 Agent 每 30 分钟就自动 commit,更不建议自动 push。
Git 是审计账本,不是运行日志。
我自己用的规则是这样:
文件写入:随时
本地 commit:一个明确工作单元结束之后
push 到远程:低频,并且确认没有敏感信息
下面这些东西,无论如何都不要提交进 Git:
API key
cookie、token
密码、私钥
个人身份材料
大体量原始数据
高频变化的数据库文件
让 Agent 自动工作,不等于让它自动把一切推到远程。
八、最后
如果你的 Agent 做完一轮就停,不用急着骂模型。先问自己四个问题:
后台 Gateway 起了没?
Cron 用的是 once 还是 every?
每次唤醒的 prompt 是不是自包含?
有没有状态文件接住上一轮的工作?
四个都对,它才有可能真的 24 小时跑下去。
否则你只是在和一个很听话、但每次说完话就下班的 Agent 聊天。
长期工作真正的秘密,不是让 Agent 一口气跑得更久,而是让它每次醒来都知道自己是谁、在哪、要接着做什么。