很多人第一次看到Codex里的Scheduled Tasks,会把它理解成:
定时运行一个Prompt。
比如每天检查一次项目、定时整理Commit、自动扫描测试失败。
但真正把Scheduled Tasks放进代码项目以后,最容易踩坑的其实不是"几点运行",而是:
任务到底在哪里运行?
现在针对Git项目,Codex的Scheduled Task可以直接在本地项目目录中执行,也可以使用独立Worktree隔离执行。官方也明确建议:如果自动任务可能产生代码修改,Worktree能够避免Scheduled Task与开发者正在进行的本地工作互相冲突。
所以真正需要理解的是:
Scheduled Task
↓
Execution Environment
↓
Local Project / Worktree
↓
Tools
↓
Changes
↓
Verification
Scheduled Tasks不是普通提醒,而是一种自动执行工作流。
一、先理解Scheduled Task到底在自动什么
普通Codex任务通常是:
打开项目
↓
输入任务
↓
Codex执行
↓
查看结果
Scheduled Task则把第一步变成自动触发:
Schedule
↓
Prompt
↓
Codex启动
↓
读取项目
↓
执行任务
↓
生成结果
比如:
每天上午检查CI失败;
每晚扫描TODO;
每周整理Release Notes;
定期检查依赖变化;
每天汇总最近Commit。
官方目前允许创建Scheduled Task时指定项目、Prompt、运行频率以及执行环境。
问题也正是在这里出现:
如果这个任务会修改代码,
它应该直接修改你现在正在工作的目录吗?
这就是Local和Worktree的核心区别。
二、Local Project是什么?
Local最容易理解。
假设你的项目目录是:
/my-project
你平时就在这里:
写代码
修改文件
运行测试
Git commit
Scheduled Task选择Local以后,它运行时使用的也是这个项目环境。
可以理解成:
Developer
↓
/my-project
↑
Scheduled Task
双方操作的是同一个工作目录。
它的最大优势就是:
环境最直接。
Agent可以看到你当前目录里的真实状态。
包括:
已经安装好的依赖;
本地配置;
当前文件;
甚至还没有提交的修改。
对于一些只读任务,这非常方便。
例如:
分析最近Commit
检查测试结果
生成项目摘要
扫描TODO
因为任务只是读取项目,并不会大量修改代码。
这种情况下Local通常足够。
三、Local真正危险的是"共享状态"
问题出现在Scheduled Task开始写文件以后。
假设你上午正在修改:
src/auth.ts
此时一个定时任务自动启动:
每天10:00
↓
检查认证模块
↓
自动修复问题
Agent也修改:
src/auth.ts
现在就出现了:
Human Change
+
Agent Change
↓
Same Workspace
可能产生:
覆盖;
冲突;
Diff混乱;
测试状态变化;
Agent基于半完成代码继续执行。
最麻烦的一种情况是:
开发者当前修改还没有Commit。
Agent看到的是:
Repository
+
Uncommitted Changes
它甚至可能把你的临时修改理解成:
项目原本状态。
于是任务输入实际上已经发生变化。
这就是共享Workspace最典型的问题:
Shared Mutable State。
四、Worktree解决的就是这个问题
Git Worktree可以让同一个Repository同时拥有多个独立Working Tree。
概念上可以理解成:
Repository
├── Main Workspace
│ └── Developer
│
└── Worktree
└── Codex
开发者继续修改自己的目录。
Codex在另一份独立Working Tree执行。
官方目前也把Worktree作为Codex并行任务和Scheduled Tasks的重要隔离机制:对于Git Repository,Scheduled Tasks可以运行在专门的后台Worktree中,从而避免自动任务干扰当前正在进行的本地修改。
这里最关键的不是:
多复制了一份代码。
真正重要的是:
Execution Isolation。
五、什么时候优先选Local?
并不是Scheduled Task全部都应该使用Worktree。
Local有非常明确的适用场景。
1. 任务主要是读取
例如:
总结昨日Commit
检查项目TODO
生成代码质量报告
这种任务几乎不会修改代码。
使用Local简单直接。
2. 必须依赖当前本地状态
有些任务就是需要读取:
当前未提交修改
比如:
每天下班前总结我今天修改了什么。
这时候如果使用独立Worktree,
Agent看到的反而可能不是你当前真实工作状态。
Local更加合理。
3. 本地环境非常复杂
例如项目依赖:
本地数据库;
特殊环境变量;
本地Service;
复杂开发工具链。
如果新的Worktree需要大量初始化成本,
Local有时候会更省事。
所以可以简单记成:
Read Current State
↓
Local
六、什么时候应该优先选Worktree?
一旦任务会:
修改代码,
Worktree的价值就明显提高。
例如:
自动修复Lint
自动补测试
处理简单Bug
更新依赖
定期重构某类代码
这类任务如果直接运行Local,相当于:
后台Agent会自动进入你正在工作的目录写代码。
风险明显更高。
使用Worktree以后:
Main Workspace
↓
Developer继续工作
同时:
Background Worktree
↓
Scheduled Task执行
两边可以相互隔离。
因此一个很实用的判断方式是:
只读任务
→ Local
写代码任务
→ 优先Worktree
当然不是绝对规则,但作为默认策略非常实用。
七、Worktree也不是完全"零成本"
Worktree虽然解决隔离问题,但也带来新的工程成本。
其中最明显的是:
Environment Setup。
创建一个新的Worktree以后,它拥有代码文件。
但不一定自动拥有完整运行环境。
例如:
node_modules
可能不存在。
Python虚拟环境可能需要重新配置。
某些:
.env
文件可能没有进入Git。
还有:
本地数据库;
缓存;
生成文件;
私有证书。
也可能不存在。
所以:
Git Worktree
≠
完整可执行环境
这也是为什么Codex的本地环境支持配置Setup Script,用来准备Worktree所需要的环境。
例如逻辑可能是:
Create Worktree
↓
Install Dependencies
↓
Load Environment
↓
Run Task
如果没有这一层,常见结果就是:
Local里运行正常,Worktree里全部报错。
八、Scheduled Task最容易出现的错误:Prompt写得太宽
比如创建一个任务:
每天检查项目并优化代码。
看起来很合理。
实际上非常危险。
因为"优化代码"没有边界。
Agent可能今天改:
auth
明天改:
database
后天又去:
refactor utils
于是Scheduled Task从:
Automation
慢慢变成:
Unbounded Agent。
自动任务尤其需要明确:
Scope
比如改成:
每天检查src/api目录中的ESLint错误,仅修复能够通过现有测试验证的问题,不修改公共接口。
现在边界就清楚很多。
九、一个好的Scheduled Task至少要有5个部分
我建议自动任务不要只写一句Prompt。
最好至少定义:
Goal
Scope
Action
Verification
Stop Condition
例如:
Goal
检查新增代码中的Lint问题。
Scope
只允许修改:
src/
Action
修复明确且低风险的Lint错误。
Verification
运行:
npm run lint
npm test
Stop Condition
如果测试失败或者需要修改公共API:
停止并报告。
于是完整逻辑变成:
Find
↓
Analyze
↓
Modify
↓
Verify
↓
Stop / Report
而不是:
Find
↓
随便改
这才是真正适合自动执行的任务。
十、Scheduled Task一定要考虑Verification
人工启动Codex时,我们会自然查看结果。
但Scheduled Task最大的不同是:
执行发生时,人可能根本不在电脑前。
所以Verification必须提前写进任务。
例如自动补测试:
不要只写:
给没有测试的代码补测试。
应该变成:
发现缺失测试
↓
创建测试
↓
运行相关测试
↓
确认通过
↓
报告修改文件
如果测试失败:
不要继续扩大修改范围
↓
保留Evidence
↓
报告失败
所以Scheduled Task真正重要的不是:
自动运行。
而是:
自动运行 + 自动验证。
十一、自动任务不能把"Done"定义得太简单
Agent执行结束并不等于任务完成。
例如:
文件修改成功
不代表:
功能正确
所以可以把自动任务的完成条件分成三层。
Execution Done
代码修改完成。
Verification Done
测试通过。
Acceptance Done
结果符合任务目标。
完整状态应该是:
Execute
↓
Test
↓
Validate
↓
Done
如果没有Verification,
Scheduled Task只是:
Scheduled Modification。
而不是:
Scheduled Engineering Workflow。
十二、频繁Scheduled Task还要注意Worktree数量
Worktree还有一个很实际的问题。
如果任务频率很高:
每小时运行一次
并且每次都创建独立Worktree,
时间长了可能累积很多工作树和任务记录。
OpenAI官方文档也专门提醒:频繁运行的Scheduled Tasks如果使用Worktree,可能随着时间产生较多Worktree,需要定期管理和归档已经不需要的运行。
所以不是:
Worktree越多越安全
而应该根据任务生命周期设计。
例如:
每天一次:
通常问题不大。
每小时一次:
就应该考虑:
是否真的需要Worktree?
是不是只读任务?
运行结果是否需要长期保存?
否则自动化系统自身就会产生新的维护成本。
十三、Scheduled Tasks更适合哪些任务?
一个任务越符合下面几个条件,就越适合自动化。
重复
每天或者每周都做。
边界明确
输入范围和修改范围清晰。
验证明确
可以用测试或者规则判断成功。
风险较低
失败不会产生严重后果。
例如:
Lint检查
测试扫描
Commit摘要
Release Notes
依赖变化分析
都比较适合。
反过来:
重新设计认证架构
大规模重构核心模块
修改生产数据库
就不应该因为"Scheduled Tasks可以运行"而直接自动化。
十四、Skills和Scheduled Tasks放在一起会更有价值
如果一个任务经常重复,真正成熟的做法不是:
每一个Scheduled Task里面写几十行Prompt。
而是把稳定流程抽成:
Skill。
例如创建:
ci-failure-review
Skill里面定义:
读取CI
↓
分类错误
↓
定位代码
↓
运行相关测试
↓
输出报告
Scheduled Task只需要负责:
什么时候运行
+
调用哪个Workflow
于是系统变成:
Schedule
↓
Skill
↓
Execution
↓
Verification
官方当前Scheduled Tasks也支持配合Skills使用。
这时候:
Scheduled Task解决When。
Skill解决How。
两个概念就彻底分开了。
十五、Local、Worktree到底怎么选?
可以直接使用下面这套判断。
任务是否需要修改代码?
如果:
否
优先考虑:
Local
继续判断:
是否必须读取当前未提交修改?
如果是:
Local更加合适。
如果:
是
继续问:
开发者是否可能同时修改这个项目?
如果:
是
优先:
Worktree
然后检查:
依赖
环境变量
Setup Script
测试环境
能否在Worktree里正常工作。
最终可以抽象成:
Read Current State
→ Local
Modify Shared Repo
→ Worktree
Need Current Uncommitted State
→ Local
Background Code Changes
→ Worktree
十六、一套可以直接使用的Scheduled Task检查表
创建任务前先检查:
① Goal
这个任务到底要完成什么?
② Scope
允许读取和修改哪些目录?
③ Environment
Local还是Worktree?
④ Dependencies
新Worktree能否正常运行项目?
⑤ Permission
任务需要哪些文件、Shell和网络权限?
⑥ Verification
修改以后运行什么测试?
⑦ Stop Condition
什么情况下必须停止?
⑧ Evidence
运行结束以后留下什么结果?
真正可靠的Scheduled Task应该形成:
Schedule
↓
Environment
↓
Execute
↓
Verify
↓
Evidence
最后
Scheduled Tasks真正有价值的地方,并不是:
Codex终于可以定时运行Prompt了。
而是:
一些边界清楚、可以验证的软件工程任务,开始能够从人工触发变成后台持续执行。
但自动执行同时意味着:
Agent可能在你没有看着的时候:
读取项目;
执行命令;
修改文件;
运行测试。
因此:
Execution Environment就变得非常重要。
Local的优势是:
简单;
直接;
能够看到当前真实状态。
Worktree的优势是:
隔离;
并行;
不会轻易污染开发者正在进行的工作。
所以不要简单理解成:
Local = 初级
Worktree = 高级
真正应该根据任务状态判断:
当前状态是否需要共享?
↓
修改是否需要隔离?
↓
环境能否独立运行?
↓
结果能否自动验证?
当Scheduled Task真正进入开发工作流以后,我们需要设计的就不只是:
什么时候运行。
而是整个:
Automation Execution Boundary。
这也是Codex从"人工调用的AI工具"走向"可以持续运行的工程执行系统"以后,一个越来越重要的能力。
持续更新Codex、大模型开发相关技术内容。
长期使用各类代码大模型,整理了稳定的AI会员订阅渠道。