搞懂 Claude Code 的定时调度(Cron):Agent 从被动到主动的关键设计
如果你也想弄懂 Claude Code 这类 Coding Agent 到底是怎么工作的,这个仓库也许能帮你少走一些弯路。目前我的 github 的项目(OpenAI SDK 版),我学习的课程为 learn-claude-code 的 v2 版本课程(感谢原作者),大家一起学习,共同进步。如果对你有帮助,请为我点一个 Star。
项目地址:GitHub - peijiping/learn-claude-code-langchain: Openai、langchain版的learn-claude-code教程 · GitHub
一、为什么调度对 Agent 如此重要
调度的重要性不在"定时"这个动作本身,而在它带来的三个转变:
1. 从反应式到主动式:触发源变了
没有调度,Agent 是一台自动售货机——你投币(prompt),它出货(回答)。调度的本质是把输入从"人"换成了"时间"。闹钟不需要你盯着它才会响。这是"工具"和"员工"的分界线:员工会自己到点干活,售货机不会。
2. 从单线程到事件驱动:架构上的解耦
调度迫使你拆出四层:独立调度线程、触发队列、队列处理器、消费者。触发不能阻塞 agent_loop(它正忙着回答你),交付又要尊重"Agent 空闲"这个状态。这套"生产 → 排队 → 空闲交付"的结构,是所有事件驱动能力的通用骨架——后台任务完成、新消息进来、CI 挂了要提醒,全都是它。学会 cron,就等于学会事件驱动 Agent 的 hello world。
3. 从即时一次性到跨时间自治
有了调度,Agent 第一次拥有了"长期行为":定期巡检、自愈、数据同步。没有它,Agent 只能活在用户的每一条指令里,永远没有自己的时间线。
二、调度课在课程中的定位:能力层,不是地基
调度课程的代码会被后面的"综合课"继承复用,但它不是后面"团队线"课程(团队 → 协议 → 自治 → 隔离)的概念地基——那条链的地基是团队通信。调度更像中途加入的一件装备:后面会用到,但不是支撑整体结构的梁。
三、"调度会被阻塞吗?"——教学版与真实 CC 的机制
很多人会问:调度任务触发时如果我正在用 Agent,会被阻塞吗?
教学版:用一个全局互斥锁。用户交互时锁被占用,触发任务在队列里排队,Agent 空闲才交付。锁粒度较粗——覆盖一整轮多轮工具调用,排队时间可能较长。
真实 CC:把触发的工作以 priority: 'later' 入队命令队列,由队列处理器在"无 query、无阻塞 UI、队列非空"时自动交付。核心语义一致:cron 不打断用户交互,排队等空闲,只是实现粒度更细。
四、内置 Cron 与 Scheduled Tasks:别混为一谈
这是最容易混淆的一对概念:
- 内置 Cron(CronCreate 工具):把 prompt 注入当前会话的 transcript,在当前会话上下文里执行。用户正忙时排队,不另开会话。它和用户会话强绑定、共享上下文。
- Scheduled Tasks(定时任务):每次触发启动一个独立的会话,有自己的 transcript,与你的交互会话解耦。
"调度在后台启动一个会话实例"——描述的是 Scheduled Tasks,不是内置 Cron。
五、多会话下,durable 任务会"漂"
教学版是单会话模型,不存在"另一个会话"的概念。真实 CC 里,durable 任务写在项目级文件,由"谁持有锁谁触发"——所以它可能被打开同一项目的另一个会话触发(落在非创建会话上),触发后仍走"目标会话空闲才执行"。如果目标会话根本没打开,任务就攒着,等你下次启动会话时补触发。
六、Cowork 工程师的设计智慧
我曾在 Cowork 的调度对话里问过它:为什么每次调度运行都是一个新的对话?它的回答体现了设计取舍:
- 任务存成自包含的说明:定时任务保存为一份自包含提示文件(写清目标、步骤、工具、输出格式)。每次到点,拿这份文件启动一次全新的会话,不携带创建时的对话上下文。
- 可重复、可移植:任务可能在几天后、不同的机器上跑。依赖某次对话的记忆会过时、膨胀、丢失。从同一份干净说明出发,结果才可控。
- 隔离与轻量:只加载任务说明,不加载整套历史对话,更快更省资源,也不会把一次运行产生的无关内容污染到下次。
代价是"不记得上次跑过什么",换来"随时随地都能稳定重跑"。 需要任务之间记住状态时,做法是状态外置:写进进度文件,每次运行先读它。
一句话总结它的哲学:执行单元无状态化 + 状态外置文件。
七、高频与低频:一个务实的取舍
当任务频率很高(比如每 10 分钟一次),问题就来了:每次都新开会话,会话文件会不会爆炸?
答案:CC 和 Cowork 都没有做高频定时。内置 Cron 走的是低频注入,Scheduled Tasks 是人工设置的低频形态。高频独立会话调度,在产品层面本来就没有人做——不经济,也没有人真正需要。
所以务实的取舍是:只做低频定时。实现很清爽,三件套就够:
- 任务定义文件(自包含 prompt)
- 每次到点启动一个新会话,从任务文件出发干净重跑
- 需要跨次记忆就读写状态文件,不依赖会话上下文
结语
调度对 Agent 的核心价值不是"会定时",而是让 Agent 拥有自己的时间线——从被动响应走向主动工作。而做调度系统时记住一句话:状态进文件,执行无状态,会话只负责干活。
更多推荐




所有评论(0)