Skill: mayf3/cron-helper-mayf3 (version 1.0.0)

--- name: cron-helper description: "Configure, diagnose, and fix OpenClaw cron jobs. Activate when user mentions: cron, scheduled tasks, periodic jobs, timing issues, heartbeat vs cron, or any time-based automation." --- # Cron Helper OpenClaw cron 定时任务配置、诊断和修复。 ## When to Use - User says "配置cron", "定时任务", "周期性任务", "每天X点" - Cron jobs not firing or not sending messages - Discussing heartbeat vs cron - Debugging scheduled task failures --- ## ⚠️ CRITICAL: Cron Is Stateless — Design for Persistence **Every cron job fires in a brand-new isolated session with ZERO memory of previous runs.** The agent has no conversation history, no memory of what it did last time, and CANNOT ask the user questions. This means: ### ❌ Broken Cron Pattern (无状态 = 无用功) ``` Prompt: "检查邮件，看看有没有重要的" → Agent checks email, finds nothing, outputs "没有新邮件" → Nothing saved. No state recorded. → Next run: same check, same "没有新邮件", forever identical → If something WAS important last run, nobody knows now ``` ### ✅ Correct Cron Pattern (落盘 = 有状态 = 跨次累积) ``` Prompt: "检查未读邮件。将新邮件摘要追加到 workspace/memory/email-log.md。 如果发现标记为紧急的邮件，立即发送通知到飞书群。 上次检查过的邮件ID记录在 workspace/memory/email-cursor.json。" → Agent reads cursor to know where it left off → Agent checks NEW emails since cursor → Agent writes updated cursor → Agent appends summary to log → Next run: picks up from cursor, never re-processes ``` ### Statefulness Design Rules Every cron prompt MUST follow at least one of these patterns: | Pattern | How | Example | |---------|-----|---------| | **Cursor/Checkpoint** | Read/write a pointer file tracking progress | `memory/cursor.json` with `lastCheckTime` or `lastId` | | **Append Log** | Append results to a growing log file | `memory/email-log.md`, `memory/daily-reports/2026-05-16.md` | | **Idempotent Check** | Compare current state vs saved baseline, only act on delta | Read `memory/last-status.json`, compare, update if changed | | **Time-windowed** | Use current time to query only new data | `date -v-1H` to check last hour, write results to file | | **Counter/Tracker** | Maintain a counter or running tally | `memory/consecutive-failures.txt` to trigger escalation | ### Mandatory State Checklist (写在 prompt 里) Before writing ANY cron prompt, ensure it answers: - [ ] **Where does this run save its results?** (file path) - [ ] **How does the next run know what the previous run did?** (cursor/log/state file) - [ ] **What happens if the agent can't decide something?** (must have a default action, CANNOT ask user) - [ ] **Is the output actionable even without human follow-up?** (if not, the prompt is incomplete) ### ⚠️ Critical: Timeout Must Be ≥ 300s **CLI 默认 timeout=30s，这对任何 real task 都太短了。每次创建 cron job 时必须显式设置 timeout。** | 任务类型 | 推荐 timeout | |---------|-------------| | 简单报告（拉数据+输出） | 60-120s | | 中等任务（读文件+分析+写文件） | 300-600s | | 复杂任务（查多个数据源+多步分析） | 600-1200s | | 大规模任务（处理积压数据） | 1200-1800s | **必须在 payload 和 CLI 中同时指定：** ```bash # CLI 用 --timeout-seconds 参数 openclaw cron add --timeout-seconds 600 ... # payload 中也要写 "payload": { "kind": "agentTurn", "message": "...", "timeoutSeconds": 600 } ``` > **经验教训**：ceo-agent 的每日随想分析任务默认 300s，前2天跑成功了，但数据积压后持续超时4天。改为 1200s 后解决。 ### Prompt Self-Sufficiency Rules A cron prompt is a **standalone instruction to an amnesiac agent**. It must contain: 1. **Complete context** — Don't assume the agent knows anything from previous sessions 2. **Explicit file paths** — Where to read state, where to write state 3. **Decision authority** — The agent must be able to decide and act autonomously 4. **Fallback behavior** — What to do when things go wrong (not "ask the user") **Good prompt template:** ``` 执行 [任务描述]。 - 读取上次状态：[文件路径] - 执行检查/操作：[具体步骤] - 保存本次状态：[文件路径] - 如果发现 [异常情况]，[自动处理方式] - 将结果追加到 [日志路径] ``` **Bad prompt:** ``` 检查一下系统状态 ← 太模糊，没有落盘，没有状态 ``` --- ## Cron vs Heartbeat | | Heartbeat | Cron | |---|-----------|------| | **Location** | `workspace/HEARTBEAT.md` | `~/.openclaw/cron/jobs.json` | | **Precision** | ~30 minutes | Exact to second | | **Context** | Has conversation context | **Stateless isolated session** | | **Best for** | Bulk checks, monitoring | Precise timing, independent tasks | **Choose Cron** when: precise timing, self-contained task, no conversation context needed **Choose Heartbeat** when: bulk checks across areas, needs recent conversation context --- ## Cron Job Structure ### Required Fields ```json { "id": "daily-report-001", "agentId": "report-agent", "name": "每日报告", "enabled": true, "schedule": { "kind": "cron", "expr": "0 10 * * *", "tz": "Asia/Shanghai" }, "payload": { "kind": "agentTurn", "message": "..." }, "delivery": { "mode": "announce", "channel": "feishu", "to": "chat:oc_xxx" } } ``` Every job MUST have: `id`, `agentId`, `name`, `enabled`, `schedule`, `payload.kind="agentTurn"`, `payload.message`, `delivery.channel`, `delivery.to`. ### Cron Expression Format ``` ┌────────── minute (0-59) │ ┌────────── hour (0-23) │ │ ┌────────── day of month (1-31) │ │ │ ┌────────── month (1-12) │ │ │ │ ┌────────── day of week (0-6, Sun=0) │ │ │ │ │ * * * * * ``` Common patterns: - `0 10 * * *` — Daily at 10:00 - `*/5 * * * *` — Every 5 minutes - `0 */2 * * *` — Every 2 hours - `*/30 0-8 * * *` — Every 30min during 0:00-8:30 (night hours) - `0 9,17 * * *` — Twice daily at 9AM and 5PM --- ## Common Fatal Errors | # | Error | Fix | |---|-------|-----| | 1 | Missing `delivery.channel` + `delivery.to` | Must have BOTH: `"channel": "feishu"`, `"to": "chat:oc_xxx"` | | 2 | `delivery.channel = "last"` | "last" is NOT valid. Use `"feishu"` or `"discord"` | | 3 | Missing `payload.kind` | Must be `"agentTurn"` | | 4 | Using `peer` object in delivery | Use `to` string, not `peer` object | | 5 | Missing `schedule.tz` | Always set `"tz": "Asia/Shanghai"` | | 6 | jq redirect overwrite (`jq '...' file > file`) | Write to temp file first, then `mv` | | 7 | Vague prompt with no state persistence | See "Statefulness Design Rules" above | --- ## Safety: NEVER Modify Jobs Without These Steps 1. **Backup first**: `cp ~/.openclaw/cron/jobs.json ~/.openclaw/cron/jobs.json.backup-$(date +%Y%m%d-%H%M%S)` 2. **Precise matching**: Only modify EXACTLY what user asked (not all jobs) 3. **Test jq filter before applying**: Run read-only first to verify scope 4. **Write to temp file, validate, then atomic mv** (never jq redirect to same file) 5. **Validate after write**: See `scripts/validate-jobs-syntax-v2.sh` ### Precise Matching Rules | User Says | Scope | jq Pattern | |-----------|-------|------------| | "你的定时任务" | Only jobs with YOUR `agentId` | `select(.agentId == "your-agent")` | | "每日报告任务" | Jobs matching that name | `select(.name \| contains("每日报告"))` | | "所有定时任务" | ALL jobs (user said "所有") | `.jobs[]` | | Unclear | **ASK first** | — | --- ## Prompt Design Examples ### Example 1: Stateful Daily Report ```json { "payload": { "kind": "agentTurn", "message": "生成今日学习报告。1) 读取 memory/learning-queue.json 获取待研究主题队列。2) 研究队首主题，撰写笔记保存到 learning/YYYY-MM-DD.md。3) 从队列中移除已完成主题，追加新发现到队列。4) 将报告摘要发送到飞书群。如果队列为空，主动从 trending topics 中选择一个加入队列。" } } ``` ### Example 2: Idempotent Health Check ```json { "payload": { "kind": "agentTurn", "message": "检查服务健康状态。读取 memory/last-health-status.json 作为基线。对每个服务执行健康检查。如果状态与基线不同：更新基线文件，发送变更通知到飞书群。如果状态相同且全部正常：更新 last-check 时间戳，不发消息（避免噪音）。如果连续3次失败：发送告警并记录到 memory/alert-log.md。" } } ``` ### Example 3: Broken (Anti-pattern) ```json { "payload": { "kind": "agentTurn", "message": "检查系统状态" } } ``` **Why broken**: No state file, no decision authority, no persistence. Every run produces identical output. --- ## Diagnostic Workflow ```bash # 1. Check gateway status openclaw gateway status # 2. Validate jobs.json syntax cat ~/.openclaw/cron/jobs.json | jq . # 3. Run validation script ~/.openclaw/skills/cron-helper/scripts/validate-jobs-syntax-v2.sh # 4. Check gateway logs for cron errors openclaw gateway logs | grep -i cron ``` For detailed troubleshooting, see `references/troubleshooting.md`. For full syntax specification, see `references/syntax-guide.md`. For validation scripts, see `scripts/`. --- ## New Job Creation Template ```json { "id": "TODO-unique-id", "agentId": "TODO-agent-id", "name": "TODO-任务描述", "enabled": true, "schedule": { "kind": "cron", "expr": "TODO * * * *", "tz": "Asia/Shanghai" }, "sessionTarget": "isolated", "wakeMode": "now", "payload": { "kind": "agentTurn", "message": "TODO-完整自包含指令：读取[状态文件]→执行[操作]→保存[状态文件]→如果[异常]则[自动处理]", "timeoutSeconds": 300 }, "delivery": { "mode": "announce", "channel": "feishu", "to": "chat:oc_TODO" } } ``` **Before submitting**: Run `scripts/validate-jobs-syntax-v2.sh` on the new config.


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)