Cron ジョブ(Gateway スケジューラ)
Cron と Heartbeat の使い分けは? Cron vs Heartbeat を参照してください。
Cron は Gateway 内蔵のスケジューラです。ジョブを永続化し、適切なタイミングでエージェントを起動し、結果をチャットに返すこともできます。
「毎朝これを実行して」や「20 分後にエージェントに知らせて」といった用途に最適です。
トラブルシューティング: /automation/troubleshooting
概要
- Cron は Gateway 内部で動作します(モデル内部ではありません)。
- ジョブは
~/.openclaw/cron/に保存され、再起動してもスケジュールは維持されます。 - 2 つの実行スタイル:
- メインセッション: システムイベントをキューに入れ、次の Heartbeat で実行。
- 分離実行:
cron:<jobId>で専用のエージェントターンを実行し、配信(デフォルトは announce、または none)。
- ウェイクアップは第一級機能: ジョブごとに「即時起動」か「次の Heartbeat」を指定可能。
- ジョブ単位の Webhook 送信:
delivery.mode = "webhook"+delivery.to = "<url>"で設定。 notify: trueを持つ旧ジョブでcron.webhookが設定されている場合のレガシーフォールバックも残っています。Webhook 配信モードへの移行を推奨します。- アップグレード時に
openclaw doctor --fixでレガシーの Cron ストアフィールドを正規化できます。
クイックスタート(実践)
ワンショットのリマインダーを作成し、存在を確認して即時実行する例:
openclaw cron add \
--name "Reminder" \
--at "2026-02-01T16:00:00Z" \
--session main \
--system-event "Reminder: check the cron docs draft" \
--wake now \
--delete-after-run
openclaw cron list
openclaw cron run <job-id>
openclaw cron runs --id <job-id>
定期的な分離ジョブ(配信付き)のスケジュール:
openclaw cron add \
--name "Morning brief" \
--cron "0 7 * * *" \
--tz "America/Los_Angeles" \
--session isolated \
--message "Summarize overnight updates." \
--announce \
--channel slack \
--to "channel:C1234567890"
ツールコール相当(Gateway cron ツール)
標準的な JSON シェイプと例については、ツールコール用 JSON スキーマを参照してください。
Cron ジョブの保存場所
Cron ジョブはデフォルトでゲートウェイホストの ~/.openclaw/cron/jobs.json に永続化されます。Gateway は起動時にこのファイルをメモリに読み込み、変更時に書き戻します。手動編集は Gateway 停止時のみ安全です。変更には openclaw cron add/edit またはツールコール API の使用を推奨します。
初心者向け概要
Cron ジョブとは、いつ実行するか + 何をするかの組み合わせです。
-
スケジュールを選択
- ワンショットのリマインダー →
schedule.kind = "at"(CLI:--at) - 繰り返しジョブ →
schedule.kind = "every"またはschedule.kind = "cron" - ISO タイムスタンプにタイムゾーンが省略された場合は UTC として扱われます。
- ワンショットのリマインダー →
-
実行場所を選択
sessionTarget: "main"→ メインコンテキストで次の Heartbeat 時に実行。sessionTarget: "isolated"→cron:<jobId>で専用のエージェントターンを実行。
-
ペイロードを選択
- メインセッション →
payload.kind = "systemEvent" - 分離セッション →
payload.kind = "agentTurn"
- メインセッション →
補足: ワンショットジョブ(schedule.kind = "at")はデフォルトで成功後に自動削除されます。deleteAfterRun: false を設定すると保持されます(成功後に無効化されます)。
コンセプト
ジョブ
Cron ジョブは以下を持つ保存レコードです:
- スケジュール(実行タイミング)
- ペイロード(実行内容)
- オプションの配信モード(
announce、webhook、none) - オプションのエージェントバインディング(
agentId): 特定のエージェントでジョブを実行。未設定または不明な場合はデフォルトエージェントにフォールバック。
ジョブは安定した jobId で識別されます(CLI/Gateway API で使用)。エージェントのツールコールでは jobId が正式名。レガシーの id も互換性のために受け付けます。
ワンショットジョブはデフォルトで成功後に自動削除されます。deleteAfterRun: false で保持可能です。
スケジュール
Cron は 3 種類のスケジュールをサポートします:
at:schedule.atによる一回限りのタイムスタンプ(ISO 8601)。every: 固定間隔(ミリ秒)。cron: 5 フィールドの cron 式(秒を含む 6 フィールドも可)。IANA タイムゾーンはオプション。
Cron 式は croner を使用します。タイムゾーンが省略された場合、ゲートウェイホストのローカルタイムゾーンが使われます。
多数のゲートウェイで正時にアクセスが集中するのを避けるため、OpenClaw は繰り返しの正時スケジュール(例: 0 * * * *、0 */2 * * *)に対して、ジョブごとに決定論的な最大 5 分のずらしウィンドウを適用します。0 7 * * * のような固定時刻の式はそのまま正確に実行されます。
任意の cron スケジュールに明示的なずらしウィンドウを schedule.staggerMs で設定できます(0 で正確なタイミングを維持)。CLI ショートカット:
--stagger 30s(1m、5mなども可)で明示的なずらしウィンドウを設定。--exactでstaggerMs = 0を強制。
メインセッション vs 分離実行
メインセッションジョブ(システムイベント)
メインジョブはシステムイベントをキューに入れ、オプションで Heartbeat ランナーを起動します。payload.kind = "systemEvent" を使用してください。
wakeMode: "now"(デフォルト): イベントが即座に Heartbeat を実行。wakeMode: "next-heartbeat": 次のスケジュール済み Heartbeat まで待機。
通常の Heartbeat プロンプト+メインセッションコンテキストを使いたい場合に最適です。 Heartbeat を参照。
分離ジョブ(専用 cron セッション)
分離ジョブは cron:<jobId> セッションで専用のエージェントターンを実行します。
主な動作:
- プロンプトに
[cron:<jobId> <ジョブ名>]がプレフィックスされ、追跡可能。 - 各実行は新しいセッション ID で開始(過去の会話は引き継がれません)。
deliveryが省略された場合、分離ジョブはサマリーを通知します(delivery.mode = "announce")。delivery.modeの選択肢:announce: ターゲットチャネルにサマリーを配信し、メインセッションに簡潔なサマリーを投稿。webhook: 完了イベントにサマリーが含まれる場合、ペイロードをdelivery.toに POST。none: 内部のみ(配信なし、メインセッションへのサマリーなし)。
wakeModeでメインセッションのサマリー投稿タイミングを制御:now: 即座に Heartbeat。next-heartbeat: 次のスケジュール済み Heartbeat まで待機。
頻繁に実行されるバックグラウンドタスクなど、メインチャット履歴を汚したくない場合に分離ジョブを使用してください。
ペイロード形式(実行内容)
2 種類のペイロードをサポートします:
systemEvent: メインセッション専用。Heartbeat プロンプト経由でルーティング。agentTurn: 分離セッション専用。専用のエージェントターンを実行。
agentTurn の主なフィールド:
message: 必須のテキストプロンプト。model/thinking: オプションのオーバーライド(後述)。timeoutSeconds: オプションのタイムアウトオーバーライド。lightContext: ワークスペースブートストラップファイルの注入が不要なジョブ向けの軽量ブートストラップモード(オプション)。
配信設定:
delivery.mode:none|announce|webhook。delivery.channel:lastまたは特定のチャネル。delivery.to: チャネル固有のターゲット(announce)または Webhook URL(webhook モード)。delivery.bestEffort: announce 配信が失敗してもジョブを失敗させない。
announce 配信は実行中のメッセージングツール送信を抑制します。チャットへのターゲット指定には delivery.channel/delivery.to を使用してください。delivery.mode = "none" の場合、メインセッションにサマリーは投稿されません。
分離ジョブで delivery が省略された場合、OpenClaw はデフォルトで announce を使用します。
Announce 配信フロー
delivery.mode = "announce" の場合、cron はアウトバウンドチャネルアダプターを介して直接配信します。メインエージェントはメッセージの作成や転送のために起動されません。
動作の詳細:
- コンテンツ: 分離実行のアウトバウンドペイロード(テキスト/メディア)を通常のチャンキングとチャネルフォーマットで配信。
- Heartbeat のみの応答(
HEARTBEAT_OKで実質コンテンツなし)は配信されません。 - 分離実行が同じターゲットにメッセージツールでメッセージ送信済みの場合、重複を避けるため配信はスキップ。
- 配信ターゲットが未設定または無効な場合、
delivery.bestEffort = trueでなければジョブは失敗します。 - メインセッションへの短いサマリーは
delivery.mode = "announce"のときのみ投稿されます。 - メインセッションのサマリーは
wakeModeに従います:nowで即座に Heartbeat、next-heartbeatで次のスケジュール済み Heartbeat まで待機。
Webhook 配信フロー
delivery.mode = "webhook" の場合、完了イベントにサマリーが含まれていれば、cron はそのペイロードを delivery.to に POST します。
動作の詳細:
- エンドポイントは有効な HTTP(S) URL である必要があります。
- webhook モードではチャネル配信は試行されません。
- webhook モードではメインセッションへのサマリーは投稿されません。
cron.webhookTokenが設定されている場合、認証ヘッダーはAuthorization: Bearer <cron.webhookToken>。- 非推奨のフォールバック:
notify: trueを持つ旧ジョブはcron.webhook(設定されている場合)に引き続き送信されますが、delivery.mode = "webhook"への移行を促す警告が出ます。
モデルと思考レベルのオーバーライド
分離ジョブ(agentTurn)ではモデルと思考レベルをオーバーライドできます:
model: プロバイダー/モデル文字列(例:anthropic/claude-sonnet-4-20250514)またはエイリアス(例:opus)thinking: 思考レベル(off、minimal、low、medium、high、xhigh。GPT-5.2 + Codex モデルのみ)
注: メインセッションジョブにも model を設定できますが、共有メインセッションのモデルが変更されます。予期しないコンテキスト切り替えを避けるため、モデルオーバーライドは分離ジョブでのみ使用することを推奨します。
解決の優先順位:
- ジョブペイロードのオーバーライド(最優先)
- フック固有のデフォルト(例:
hooks.gmail.model) - エージェント設定のデフォルト
軽量ブートストラップコンテキスト
分離ジョブ(agentTurn)で lightContext: true を設定すると、軽量ブートストラップコンテキストで実行されます。
- ワークスペースブートストラップファイルの注入が不要な定期タスクに使用してください。
- 内部的には、組み込みランタイムが
bootstrapContextMode: "lightweight"で実行され、cron のブートストラップコンテキストは意図的に空のままです。 - CLI 相当:
openclaw cron add --light-context ...およびopenclaw cron edit --light-context。
配信(チャネル + ターゲット)
分離ジョブはトップレベルの delivery 設定でチャネルへの出力配信を行えます:
delivery.mode:announce(チャネル配信)、webhook(HTTP POST)、none。delivery.channel:whatsapp/telegram/discord/slack/mattermost(プラグイン) /signal/imessage/last。delivery.to: チャネル固有の受信者ターゲット。
announce 配信は分離ジョブ(sessionTarget: "isolated")でのみ有効です。
webhook 配信はメインジョブと分離ジョブの両方で有効です。
delivery.channel や delivery.to が省略された場合、メインセッションの「最後のルート」(エージェントが最後に返信した場所)にフォールバックできます。
ターゲット形式の注意:
- Slack/Discord/Mattermost(プラグイン)のターゲットは曖昧さを避けるため明示的なプレフィックスを使用してください(例:
channel:<id>、user:<id>)。 Mattermost の 26 文字のベア ID はユーザー優先で解決されます(ユーザーが存在すれば DM、なければチャネル)。確実なルーティングにはuser:<id>かchannel:<id>を使ってください。 - Telegram のトピックは
:topic:形式を使用してください(後述)。
Telegram の配信ターゲット(トピック / フォーラムスレッド)
Telegram は message_thread_id によるフォーラムトピックをサポートしています。cron 配信では to フィールドにトピック/スレッドをエンコードできます:
-1001234567890(チャット ID のみ)-1001234567890:topic:123(推奨: 明示的なトピックマーカー)-1001234567890:123(短縮形: 数値サフィックス)
telegram:... / telegram:group:... のようなプレフィックス付きターゲットも受け付けます:
telegram:group:-1001234567890:topic:123
ツールコール用 JSON スキーマ
Gateway の cron.* ツールを直接呼び出す際(エージェントのツールコールまたは RPC)には以下のシェイプを使用してください。CLI フラグは 20m のような人間向けの表記を受け付けますが、ツールコールでは schedule.at に ISO 8601 文字列、schedule.everyMs にミリ秒を使用してください。
cron.add パラメータ
ワンショット、メインセッションジョブ(システムイベント):
{
"name": "Reminder",
"schedule": { "kind": "at", "at": "2026-02-01T16:00:00Z" },
"sessionTarget": "main",
"wakeMode": "now",
"payload": { "kind": "systemEvent", "text": "Reminder text" },
"deleteAfterRun": true
}
定期的な分離ジョブ(配信付き):
{
"name": "Morning brief",
"schedule": { "kind": "cron", "expr": "0 7 * * *", "tz": "America/Los_Angeles" },
"sessionTarget": "isolated",
"wakeMode": "next-heartbeat",
"payload": {
"kind": "agentTurn",
"message": "Summarize overnight updates.",
"lightContext": true
},
"delivery": {
"mode": "announce",
"channel": "slack",
"to": "channel:C1234567890",
"bestEffort": true
}
}
補足:
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 パラメータ
{
"jobId": "job-123",
"patch": {
"enabled": false,
"schedule": { "kind": "every", "everyMs": 3600000 }
}
}
補足:
jobIdが正式名。idは互換性のために受け付けます。- パッチで
agentId: nullを使用するとエージェントバインディングをクリアできます。
cron.run と cron.remove パラメータ
{ "jobId": "job-123", "mode": "force" }
{ "jobId": "job-123" }
ストレージと履歴
- ジョブストア:
~/.openclaw/cron/jobs.json(Gateway 管理の JSON)。 - 実行履歴:
~/.openclaw/cron/runs/<jobId>.jsonl(JSONL、サイズと行数で自動プルーニング)。 - 分離 cron 実行セッションは
sessions.json内でcron.sessionRetention(デフォルト24h。falseで無効化)によりプルーニング。 - ストアパスのオーバーライド: 設定で
cron.store。
リトライポリシー
ジョブが失敗した場合、OpenClaw はエラーを一時的(リトライ可能)と永続的(即座に無効化)に分類します。
一時的エラー(リトライ対象)
- レート制限(429、too many requests、resource exhausted)
- プロバイダー過負荷(例: Anthropic
529 overloaded_error、過負荷フォールバックサマリー) - ネットワークエラー(タイムアウト、ECONNRESET、fetch failed、socket)
- サーバーエラー(5xx)
- Cloudflare 関連のエラー
永続的エラー(リトライなし)
- 認証失敗(無効な API キー、unauthorized)
- 設定またはバリデーションエラー
- その他の非一時的エラー
デフォルト動作(設定なし)
ワンショットジョブ(schedule.kind: "at"):
- 一時的エラーの場合: 指数バックオフ(30 秒 → 1 分 → 5 分)で最大 3 回リトライ。
- 永続的エラーの場合: 即座に無効化。
- 成功またはスキップの場合: 無効化(
deleteAfterRun: trueの場合は削除)。
定期ジョブ(cron / every):
- いずれのエラーでも: 次のスケジュール実行前に指数バックオフ(30 秒 → 1 分 → 5 分 → 15 分 → 60 分)を適用。
- ジョブは有効のまま。次の成功時にバックオフがリセット。
cron.retry でデフォルトをオーバーライドできます(設定を参照)。
設定
{
cron: {
enabled: true, // デフォルト true
store: "~/.openclaw/cron/jobs.json",
maxConcurrentRuns: 1, // デフォルト 1
// オプション: ワンショットジョブのリトライポリシーをオーバーライド
retry: {
maxAttempts: 3,
backoffMs: [60000, 120000, 300000],
retryOn: ["rate_limit", "overloaded", "network", "server_error"],
},
webhook: "https://example.invalid/legacy", // notify:true の旧ジョブ用の非推奨フォールバック
webhookToken: "replace-with-dedicated-webhook-token", // Webhook モード用のオプション Bearer トークン
sessionRetention: "24h", // 期間文字列または false
runLog: {
maxBytes: "2mb", // デフォルト 2_000_000 バイト
keepLines: 2000, // デフォルト 2000
},
},
}
実行ログのプルーニング動作:
cron.runLog.maxBytes: プルーニング前の実行ログファイルの最大サイズ。cron.runLog.keepLines: プルーニング時に保持する最新行数。- いずれも
cron/runs/<jobId>.jsonlファイルに適用。
Webhook の動作:
- 推奨: ジョブごとに
delivery.mode: "webhook"とdelivery.to: "https://..."を設定。 - Webhook URL は有効な
http://またはhttps://URL である必要があります。 - 送信時のペイロードは cron 完了イベントの JSON。
cron.webhookTokenが設定されている場合、認証ヘッダーはAuthorization: Bearer <cron.webhookToken>。cron.webhookTokenが未設定の場合、Authorizationヘッダーは送信されません。- 非推奨のフォールバック:
notify: trueを持つ旧ジョブはcron.webhook(設定時)を引き続き使用。
Cron を完全に無効化:
cron.enabled: false(設定)OPENCLAW_SKIP_CRON=1(環境変数)
メンテナンス
Cron には 2 つの組み込みメンテナンスパスがあります: 分離実行セッションの保持と実行ログのプルーニング。
デフォルト
cron.sessionRetention:24h(falseで実行セッションのプルーニングを無効化)cron.runLog.maxBytes:2_000_000バイトcron.runLog.keepLines:2000
仕組み
- 分離実行はセッションエントリ(
...:cron:<jobId>:run:<uuid>)とトランスクリプトファイルを作成。 - リーパーが
cron.sessionRetentionより古い実行セッションエントリを削除。 - セッションストアで参照されなくなった実行セッションについて、OpenClaw はトランスクリプトファイルをアーカイブし、同じ保持期間で古い削除済みアーカイブをパージ。
- 各実行の追記後、
cron/runs/<jobId>.jsonlのサイズがチェックされ:- ファイルサイズが
runLog.maxBytesを超えた場合、最新のrunLog.keepLines行にトリミング。
- ファイルサイズが
高頻度スケジューラ向けのパフォーマンスに関する注意
高頻度の cron セットアップは実行セッションと実行ログのフットプリントが大きくなる可能性があります。メンテナンスは組み込まれていますが、制限が緩いと不要な I/O とクリーンアップ作業が発生します。
注意すべき点:
- 分離実行が多い状態での長い
cron.sessionRetention期間 cron.runLog.keepLinesが高くrunLog.maxBytesも大きい場合- 同じ
cron/runs/<jobId>.jsonlに書き込むノイジーな繰り返しジョブが多数ある場合
対策:
cron.sessionRetentionはデバッグ/監査の必要性の範囲内でできるだけ短くrunLog.maxBytesとrunLog.keepLinesを適度に制限して実行ログを管理- ノイジーなバックグラウンドジョブは分離モードに移行し、不要なチャットを避ける配信ルールを設定
openclaw cron runsで定期的に増加を確認し、ログが大きくなる前に保持期間を調整
カスタマイズ例
実行セッションを 1 週間保持し、実行ログを大きくする:
{
cron: {
sessionRetention: "7d",
runLog: {
maxBytes: "10mb",
keepLines: 5000,
},
},
}
分離実行セッションのプルーニングを無効にし、実行ログのプルーニングは維持:
{
cron: {
sessionRetention: false,
runLog: {
maxBytes: "5mb",
keepLines: 3000,
},
},
}
高頻度 cron 向けのチューニング例:
{
cron: {
sessionRetention: "12h",
runLog: {
maxBytes: "3mb",
keepLines: 1500,
},
},
}
CLI クイックスタート
ワンショットのリマインダー(UTC ISO、成功後に自動削除):
openclaw cron add \
--name "Send reminder" \
--at "2026-01-12T18:00:00Z" \
--session main \
--system-event "Reminder: submit expense report." \
--wake now \
--delete-after-run
ワンショットのリマインダー(メインセッション、即時起動):
openclaw cron add \
--name "Calendar check" \
--at "20m" \
--session main \
--system-event "Next heartbeat: check calendar." \
--wake now
定期的な分離ジョブ(WhatsApp に announce):
openclaw cron add \
--name "Morning status" \
--cron "0 7 * * *" \
--tz "America/Los_Angeles" \
--session isolated \
--message "Summarize inbox + calendar for today." \
--announce \
--channel whatsapp \
--to "+15551234567"
明示的な 30 秒ずらしの定期 cron ジョブ:
openclaw cron add \
--name "Minute watcher" \
--cron "0 * * * * *" \
--tz "UTC" \
--stagger 30s \
--session isolated \
--message "Run minute watcher checks." \
--announce
定期的な分離ジョブ(Telegram トピックに配信):
openclaw cron add \
--name "Nightly summary (topic)" \
--cron "0 22 * * *" \
--tz "America/Los_Angeles" \
--session isolated \
--message "Summarize today; send to the nightly topic." \
--announce \
--channel telegram \
--to "-1001234567890:topic:123"
モデルと思考レベルオーバーライド付き分離ジョブ:
openclaw cron add \
--name "Deep analysis" \
--cron "0 6 * * 1" \
--tz "America/Los_Angeles" \
--session isolated \
--message "Weekly deep analysis of project progress." \
--model "opus" \
--thinking high \
--announce \
--channel whatsapp \
--to "+15551234567"
エージェント選択(マルチエージェント構成):
# ジョブをエージェント "ops" にピン留め(該当エージェントが不在の場合はデフォルトにフォールバック)
openclaw cron add --name "Ops sweep" --cron "0 6 * * *" --session isolated --message "Check ops queue" --agent ops
# 既存ジョブのエージェントを切り替えまたはクリア
openclaw cron edit <jobId> --agent ops
openclaw cron edit <jobId> --clear-agent
手動実行(force がデフォルト。期日到来時のみ実行するには --due):
openclaw cron run <jobId>
openclaw cron run <jobId> --due
cron.run はジョブの完了後ではなく、手動実行がキューに入った時点で応答を返します。正常にキューイングされた場合の応答は { ok: true, enqueued: true, runId } です。ジョブが既に実行中であるか --due で期日のものがない場合は { ok: true, ran: false, reason } となります。最終的な完了エントリの確認には openclaw cron runs --id <jobId> または Gateway の cron.runs メソッドを使用してください。
既存ジョブの編集(フィールドのパッチ):
openclaw cron edit <jobId> \
--message "Updated prompt" \
--model "opus" \
--thinking low
既存の cron ジョブをスケジュール通り正確に実行(ずらしなし):
openclaw cron edit <jobId> --exact
実行履歴:
openclaw cron runs --id <jobId> --limit 50
ジョブを作成せずに即座にシステムイベントを発行:
openclaw system event --mode now --text "Next heartbeat: check battery."
Gateway API サーフェス
cron.list、cron.status、cron.add、cron.update、cron.removecron.run(force または due)、cron.runsジョブを作成しない即時システムイベントについてはopenclaw system eventを参照。
トラブルシューティング
何も実行されない
- Cron が有効か確認:
cron.enabledとOPENCLAW_SKIP_CRON。 - Gateway が継続的に稼働しているか確認(cron は Gateway プロセス内で動作)。
cronスケジュールの場合: タイムゾーン(--tz)とホストタイムゾーンの確認。
定期ジョブが失敗後に遅延し続ける
- OpenClaw は連続エラー後の定期ジョブに指数リトライバックオフを適用します: 30 秒、1 分、5 分、15 分、60 分。
- バックオフは次の成功時に自動リセットされます。
- ワンショット(
at)ジョブは一時的エラー(レート制限、過負荷、ネットワーク、サーバーエラー)を最大 3 回バックオフ付きでリトライ。永続的エラーは即座に無効化。リトライポリシーを参照。
Telegram の配信先が間違っている
- フォーラムトピックには
-100…:topic:<id>を使い、明確で曖昧さのない指定にしてください。 - ログや保存された「最後のルート」ターゲットに
telegram:...プレフィックスが表示されても正常です。 cron 配信はこれを受け付け、トピック ID を正しく解析します。
サブエージェント announce 配信のリトライ
- サブエージェント実行が完了すると、Gateway は要求元セッションに結果を通知します。
- announce フローが
falseを返した場合(例: 要求元セッションがビジー状態)、Gateway はannounceRetryCountで追跡しながら最大 3 回リトライします。 endedAtから 5 分以上経過した announce は強制的に期限切れにされ、古いエントリがループするのを防ぎます。- ログに繰り返しの announce 配信が表示される場合、サブエージェントレジストリで
announceRetryCountの値が高いエントリを確認してください。