cron と heartbeat はどう使い分けるべきですか? 判断の目安は Cron vs Heartbeat を参照してください。cron はゲートウェイに組み込まれたスケジューラです。ジョブを永続化し、適切なタイミングでエージェントを起動し、必要に応じて出力をチャットへ返せます。 「毎朝これを実行したい」や「20 分後にエージェントを起こしたい」といった用途では、cron を使います。 トラブルシューティング: /automation/troubleshooting
要点
- cron は ゲートウェイ内 で実行されます(モデル内ではありません)。
- ジョブは
~/.openclaw/cron/以下に保存されるため、再起動してもスケジュールは失われません。 - 実行スタイルは 2 種類あります:
- Main session: システムイベントをキューに入れ、次の heartbeat で実行します。
- Isolated:
cron:<jobId>で専用のエージェントターンを実行し、delivery を適用します(既定はannounce、またはnone)。
- ウェイクアップは第一級の機能です。ジョブごとに「今すぐ起こす」か「次の heartbeat で実行する」かを選べます。
- webhook 投稿はジョブ単位で
delivery.mode = "webhook"とdelivery.to = "<url>"を使って設定します。 cron.webhookが設定されている場合は、保存済みのnotify: trueジョブ向けの従来フォールバックも残っています。これらのジョブはwebhookdelivery mode へ移行してください。- アップグレード時は、スケジューラが cron ストアに触れる前に
openclaw doctor --fixで従来形式の項目を正規化できます。
クイックスタート(そのまま試せる例)
ワンショットのリマインダーを作成し、存在を確認して、すぐに実行します。ツール呼び出しでの対応形式(ゲートウェイの cron ツール)
正規の JSON 形式と例は ツール呼び出し用 JSON schema を参照してください。cron ジョブの保存場所
cron ジョブは既定でゲートウェイホストの~/.openclaw/cron/jobs.json に永続化されます。ゲートウェイはこのファイルをメモリに読み込み、変更時に書き戻すため、手動編集が安全なのはゲートウェイ停止中だけです。変更には openclaw cron add/edit または cron tool call API を使うことを推奨します。
初心者向けの概要
cron ジョブは、いつ実行するか と 何をするか の組み合わせだと考えると分かりやすくなります。- スケジュールを選ぶ
- ワンショットのリマインダー →
schedule.kind = "at"(CLI:--at) - 定期ジョブ →
schedule.kind = "every"またはschedule.kind = "cron"
- ワンショットのリマインダー →
- ISO タイムスタンプにタイムゾーンがない場合は、UTC として扱われます。
-
どこで実行するかを選ぶ
sessionTarget: "main"→ 次の heartbeat 中に main コンテキストで実行します。sessionTarget: "isolated"→cron:<jobId>で専用のエージェントターンを実行します。
-
ペイロードを選ぶ
- Main session →
payload.kind = "systemEvent" - Isolated session →
payload.kind = "agentTurn"
- Main session →
schedule.kind = "at")は、既定で成功後に削除されます。保持したい場合は deleteAfterRun: false を設定してください(成功後は無効化されます)。
概念
ジョブ
cron ジョブは、次の情報を持つ保存済みレコードです。- schedule(いつ実行するか)
- payload(何をするか)
- オプションの delivery mode(
announce、webhook、none) - オプションの agent binding(
agentId): 特定のエージェントでジョブを実行します。指定がない、または不明な場合は、ゲートウェイが既定のエージェントにフォールバックします。
jobId で識別されます(CLI / ゲートウェイ API で使用)。
エージェントの tool call では jobId が正規で、互換性のために従来の id も受け付けます。
ワンショットジョブは既定で成功後に自動削除されます。保持したい場合は deleteAfterRun: false を設定してください。
スケジュール
cron は 3 種類のスケジュール種別をサポートします。at:schedule.atで指定するワンショットのタイムスタンプ(ISO 8601)every: 固定間隔(ms)cron: オプションの IANA タイムゾーン付き 5 フィールド cron 式(秒を含む 6 フィールドも可)
croner を使用します。タイムゾーンを省略した場合は、ゲートウェイホストのローカルタイムゾーンが使われます。
毎時ちょうどに多数のゲートウェイで負荷が集中するのを避けるため、OpenClaw は毎時開始の定期式(例: 0 * * * *、0 */2 * * *)に対して、ジョブごとに決定論的な最大 5 分の stagger window を適用します。0 7 * * * のような固定時刻の式は正確な時刻のままです。
どの cron スケジュールでも、schedule.staggerMs で明示的な stagger window を設定できます(0 なら正確な時刻を維持します)。CLI のショートカット:
--stagger 30s(1m、5mでも可)で明示的な stagger window を設定--exactでstaggerMs = 0を強制
Main 実行と isolated 実行
Main session ジョブ(system events)
Main ジョブは system event をキューに入れ、必要に応じて heartbeat runner を起こします。これらのジョブはpayload.kind = "systemEvent" を使う必要があります。
wakeMode: "now"(既定): event が即時の heartbeat 実行を引き起こします。wakeMode: "next-heartbeat": event は次回のスケジュール済み heartbeat まで待機します。
Isolated ジョブ(専用の cron セッション)
Isolated ジョブはセッションcron:<jobId> で専用のエージェントターンを実行します。
主な挙動:
- プロンプトには追跡しやすいように
[cron:<jobId> <job name>]が付きます。 - 各実行は 新しい session id で始まります(過去の会話は引き継がれません)。
- 既定の挙動:
deliveryを省略した場合、isolated ジョブは要約をannounceします(delivery.mode = "announce")。 delivery.modeで動作を選びます:announce: 対象チャンネルに要約を配信し、main session にも短い要約を投稿します。webhook: finished event に summary が含まれる場合、delivery.toへ finished event payload をPOSTします。none: 内部処理のみです(配信なし、main session 要約もなし)。
wakeModeは main session 要約の投稿タイミングを制御します:now: 即時 heartbeatnext-heartbeat: 次回のスケジュール済み heartbeat まで待機
ペイロードの形(何が実行されるか)
サポートされる payload の種類は 2 つです。systemEvent: main session 専用で、heartbeat prompt を通してルーティングされます。agentTurn: isolated session 専用で、専用のエージェントターンを実行します。
agentTurn フィールド:
message: 必須のテキストプロンプトmodel/thinking: オプションの override(後述)timeoutSeconds: オプションのタイムアウト overridelightContext: ワークスペース bootstrap file injection を必要としないジョブ向けの、オプションの軽量 bootstrap モード
delivery.mode:none|announce|webhookdelivery.channel:lastまたは特定の channeldelivery.to: channel 固有の target(announce)または webhook URL(webhookmode)delivery.bestEffort: announce delivery に失敗してもジョブを失敗扱いにしない
delivery.channel / delivery.to でチャットの宛先を指定してください。delivery.mode = "none" の場合、main session には要約は投稿されません。
Isolated ジョブで delivery を省略すると、OpenClaw は既定で announce を使います。
Announce delivery フロー
delivery.mode = "announce" の場合、cron は outbound channel adapter 経由で直接配信します。メインの agent を起動してメッセージを作成したり転送したりはしません。
挙動の詳細:
- コンテンツ: 配信には isolated run の outbound payload(テキスト / メディア)を使用し、通常の chunking と channel formatting が適用されます。
- heartbeat 専用の応答(
HEARTBEAT_OKで実質的な内容がないもの)は配信されません。 - Isolated run がすでに同じ target へ message tool で送信していた場合、重複を避けるため delivery はスキップされます。
- Delivery target が欠落している、または無効な場合、
delivery.bestEffort = trueでない限りジョブは失敗します。 delivery.mode = "announce"の場合のみ、短い要約が main session に投稿されます。- Main session 要約は
wakeModeに従います。nowは即時 heartbeat をトリガーし、next-heartbeatは次回のスケジュール済み heartbeat まで待機します。
Webhook delivery フロー
delivery.mode = "webhook" の場合、finished event に summary が含まれると、cron は finished event payload を delivery.to へ POST します。
挙動の詳細:
- エンドポイントは有効な HTTP(S) URL である必要があります。
- webhook mode では channel delivery は試行されません。
- webhook mode では main session 要約は投稿されません。
cron.webhookTokenが設定されている場合、auth header はAuthorization: Bearer <cron.webhookToken>になります。- 非推奨のフォールバック: 保存済みの従来ジョブで
notify: trueのものは、警告付きで引き続きcron.webhookへPOSTされます。delivery.mode = "webhook"へ移行してください。
モデルと thinking の override
Isolated ジョブ(agentTurn)では、model と thinking level を override できます。
model: Provider / model 文字列(例:anthropic/claude-sonnet-4-20250514)または alias(例:opus)thinking: Thinking level(off、minimal、low、medium、high、xhigh; GPT-5.2 + Codex モデルのみ)
model は main session ジョブにも設定できますが、共有されている main session model が切り替わります。予期しないコンテキストの変化を避けるため、model override は isolated ジョブでのみ使うことを推奨します。
解決優先順位:
- ジョブ payload の override(最優先)
- Hook 固有の既定値(例:
hooks.gmail.model) - Agent 設定の既定値
軽量 bootstrap context
Isolated ジョブ(agentTurn)では、lightContext: true を設定して軽量な bootstrap context で実行できます。
- ワークスペース bootstrap file injection を必要としない定期処理に使ってください。
- 実際には、組み込みランタイムが
bootstrapContextMode: "lightweight"で実行されるため、cron の bootstrap context は意図的に空のままになります。 - CLI の対応:
openclaw cron add --light-context ...とopenclaw cron edit --light-context
Delivery(channel + target)
Isolated ジョブは、トップレベルのdelivery 設定を使って出力を channel へ配信できます。
delivery.mode:announce(channel delivery)、webhook(HTTP POST)、またはnonedelivery.channel:whatsapp/telegram/discord/slack/mattermost(plugin)/signal/imessage/lastdelivery.to: channel 固有の recipient target
announce delivery は isolated ジョブ(sessionTarget: "isolated")でのみ有効です。webhook delivery は main ジョブと isolated ジョブの両方で有効です。
delivery.channel または delivery.to を省略した場合、cron は main session の「last route」(エージェントが最後に返信した宛先)にフォールバックできます。
宛先形式の補足:
- Slack / Discord / Mattermost(plugin)の target は、曖昧さを避けるために
channel:<id>やuser:<id>のような明示的な prefix を使ってください。 - Telegram の topic は
:topic:形式を使ってください(詳細は後述)。
Telegram の delivery 宛先(topics / forum threads)
Telegram はmessage_thread_id によるフォーラムトピックをサポートしています。cron delivery では、to フィールドに topic / thread をエンコードできます。
-1001234567890(chat id のみ)-1001234567890:topic:123(推奨: topic marker を明示)-1001234567890:123(短縮形: 数値 suffix)
telegram:... / telegram:group:... のような prefix 付き target も受け付けます。
telegram:group:-1001234567890:topic:123
ツール呼び出し用 JSON schema
ゲートウェイのcron.* ツールを直接呼び出すとき(agent tool calls または RPC)は、次の形式を使用してください。CLI フラグは 20m のような人間向け duration を受け付けますが、tool calls では schedule.at に ISO 8601 文字列を、schedule.everyMs にはミリ秒を使ってください。
cron.add params
ワンショットの main session ジョブ(system event):schedule.kind:at(at)、every(everyMs)、またはcron(expr、オプションでtz)schedule.atは ISO 8601 を受け付けます(タイムゾーンは省略可。省略時は UTC として扱われます)。everyMsはミリ秒です。sessionTargetは"main"または"isolated"である必要があり、payload.kindと一致していなければなりません。- オプション項目:
agentId、description、enabled、deleteAfterRun(atでは既定で true)、delivery wakeModeは省略時に"now"が既定になります。
cron.update params
jobIdが正規で、互換性のためにidも受け付けます。- Agent binding を解除するには、patch で
agentId: nullを使用します。
cron.runとcron.remove params
保存場所と履歴
- ジョブストア:
~/.openclaw/cron/jobs.json(ゲートウェイ管理の JSON) - 実行履歴:
~/.openclaw/cron/runs/<jobId>.jsonl(JSONL。サイズと行数に基づいて自動で prune されます) sessions.json内の isolated cron run session はcron.sessionRetentionで prune されます(既定は24h。無効にするにはfalseを設定します)。- ストアパスの上書き: 設定の
cron.store
リトライポリシー
ジョブが失敗すると、OpenClaw はエラーを transient(リトライ可能)と permanent(即時に無効化)に分類します。Transient error(リトライあり)
- レート制限(429、too many requests、resource exhausted)
- プロバイダー過負荷(例: Anthropic の
529 overloaded_error、overload fallback summaries) - ネットワークエラー(timeout、ECONNRESET、fetch failed、socket)
- サーバーエラー(5xx)
- Cloudflare 関連のエラー
Permanent error(リトライなし)
- 認証失敗(無効な API key、unauthorized)
- 設定または validation エラー
- その他の non-transient error
既定の挙動(設定なし)
ワンショットジョブ (schedule.kind: "at"):
- Transient error 時: 指数バックオフ(30s → 1m → 5m)で最大 3 回までリトライします。
- Permanent error 時: 直ちに無効化します。
- 成功または skip 時: 無効化します(
deleteAfterRun: trueなら削除)。
cron / every):
- どのエラーでも: 次のスケジュール実行前に指数バックオフ(30s → 1m → 5m → 15m → 60m)を適用します。
- ジョブは有効のままで、次に成功するとバックオフはリセットされます。
cron.retry を設定してください(Configuration を参照)。
Configuration
cron.runLog.maxBytes: prune 前に許容される run-log ファイルの最大サイズcron.runLog.keepLines: prune 時に保持する最新 N 行- どちらも
cron/runs/<jobId>.jsonlファイルに適用されます。
- 推奨: ジョブごとに
delivery.mode: "webhook"とdelivery.to: "https://..."を設定します。 - webhook URL は有効な
http://またはhttps://URL である必要があります。 POST時の payload は cron finished event の JSON です。cron.webhookTokenが設定されている場合、auth header はAuthorization: Bearer <cron.webhookToken>になります。cron.webhookTokenが設定されていない場合、Authorizationheader は送信されません。- 非推奨のフォールバック: 保存済みの従来ジョブで
notify: trueのものは、cron.webhookがある場合に引き続きそれを使用します。
cron.enabled: false(config)OPENCLAW_SKIP_CRON=1(env)
メンテナンス
cron には、isolated run session retention と run-log pruning という 2 つの組み込みメンテナンス経路があります。既定値
cron.sessionRetention:24h(run-session pruning を無効にするにはfalseを設定)cron.runLog.maxBytes:2_000_000bytescron.runLog.keepLines:2000
仕組み
- Isolated run は session entry(
...:cron:<jobId>:run:<uuid>)と transcript file を作成します。 - reaper は
cron.sessionRetentionより古い期限切れの run-session entry を削除します。 - session store から参照されなくなった削除済み run session については、OpenClaw が transcript file をアーカイブし、同じ retention window に基づいて古い削除済みアーカイブを purge します。
- 各実行の追記後、
cron/runs/<jobId>.jsonlはサイズチェックされます:- ファイルサイズが
runLog.maxBytesを超えた場合、最新のrunLog.keepLines行だけを残すように trim されます。
- ファイルサイズが
高負荷なスケジューラでのパフォーマンス上の注意
高頻度の cron 構成では、run-session と run-log が大きく膨らむことがあります。メンテナンス機能は組み込まれていますが、制限を緩くしすぎると不要な I/O やクリーンアップ作業が増える可能性があります。 確認すべき点:- isolated run が多い環境で
cron.sessionRetentionを長く設定している cron.runLog.keepLinesが大きく、かつrunLog.maxBytesも大きい- 同じ
cron/runs/<jobId>.jsonlへ大量に書き込む、騒がしい定期ジョブが多い
cron.sessionRetentionは、デバッグや監査に必要な範囲でできるだけ短く保つrunLog.maxBytesとrunLog.keepLinesは適度な値にして、run log のサイズを制限する- 不要なチャット送信を避ける delivery rule と組み合わせて、騒がしいバックグラウンドジョブは isolated mode へ移す
openclaw cron runsで定期的に増加状況を確認し、ログが大きくなる前に retention を調整する
カスタマイズ例
run session を 1 週間保持し、より大きい run log を許可する例:CLI クイックスタート
ワンショットのリマインダー(UTC の ISO、成功後に自動削除):force が既定。期限が来ているときだけ実行するには --due を使用):
cron.run は現在、ジョブ完了後ではなく、手動実行がキューに入った時点で確認応答を返します。キュー投入成功時の応答は { ok: true, enqueued: true, runId } のようになります。ジョブがすでに実行中の場合や、--due で期限到来ジョブがなかった場合の応答は、引き続き { ok: true, ran: false, reason } です。最終的な完了エントリは openclaw cron runs --id <jobId> または cron.runs gateway method で確認してください。
既存ジョブを編集する(項目を patch):
ゲートウェイ API
cron.list,cron.status,cron.add,cron.update,cron.removecron.run(force または due),cron.runsジョブを作らずに即時 system event を送るにはopenclaw system eventを使ってください。
トラブルシューティング
「何も実行されない」
- cron が有効か確認してください:
cron.enabledとOPENCLAW_SKIP_CRON - ゲートウェイが継続的に実行されているか確認してください(cron はゲートウェイ process 内で動作します)。
cronスケジュールでは、タイムゾーン(--tz)とホストのタイムゾーンが合っているか確認してください。
定期ジョブが失敗後ずっと遅延し続ける
- OpenClaw は定期ジョブで連続エラーが起きると、指数リトライバックオフを適用します: 30s、1m、5m、15m、その後は60m間隔でリトライします。
- 次に成功するとバックオフは自動的にリセットされます。
- ワンショット(
at)ジョブは、transient error(rate limit、overloaded、network、server_error)をバックオフ付きで最大 3 回までリトライします。permanent error は即座に無効化されます。詳しくは Retry policy を参照してください。
Telegramが違う場所に配信される
- フォーラムトピックでは、明示的で曖昧さのない
-100…:topic:<id>を使ってください。 - ログや保存済みの「last route」target に
telegram:...prefix が見えても正常です。cron delivery はこれらを受け付け、topic ID も正しく解析します。
Subagent の announce delivery がリトライされる
- subagent run が完了すると、ゲートウェイは結果を requester session へ announce します。
- announce フローが
falseを返した場合(例: requester session が busy)、ゲートウェイはannounceRetryCountで追跡しつつ最大 3 回までリトライします。 endedAtから 5 分を過ぎた announce は、古い entry が無限ループしないよう強制的に期限切れ扱いになります。- ログで announce delivery の繰り返しが見える場合は、subagent registry 内で
announceRetryCountが大きい entry を確認してください。