Heartbeat (Gateway)
Heartbeat と Cron のどちらを使うべきか? 使い分けの指針については Automation & Tasks を参照してください。Heartbeat は、モデルが あなたにスパムせずに注意が必要なことを表面化できるよう、メインセッションで定期的なエージェントターンを実行します。 Heartbeat は、メインセッションでのスケジュール済みターンであり、background task レコードは作成しません。 タスクレコードは、切り離された作業(ACP 実行、subagent、分離された cron ジョブ)用です。 トラブルシューティング: Scheduled Tasks
クイックスタート
- Heartbeat を有効のままにする(デフォルトは
30m、または Anthropic OAuth/token 認証では1h。Claude CLI の再利用を含む)か、独自の頻度を設定します。 - エージェントワークスペースに小さな
HEARTBEAT.mdチェックリストまたはtasks:ブロックを作成します(任意ですが推奨)。 - Heartbeat メッセージの送信先を決めます(デフォルトは
target: "none"です。最後の連絡先へ送るにはtarget: "last"を設定します)。 - 任意: 透明性のために heartbeat の reasoning 配信を有効にします。
- 任意: Heartbeat 実行で
HEARTBEAT.mdだけが必要な場合は、軽量な bootstrap context を使います。 - 任意: 毎回の heartbeat で会話履歴全体を送らないよう、分離セッションを有効にします。
- 任意: Heartbeat をアクティブ時間帯(ローカル時刻)に限定します。
デフォルト
- 間隔:
30m(または Anthropic OAuth/token 認証が検出された認証モードである場合は1h。Claude CLI の再利用を含む)。agents.defaults.heartbeat.everyまたはエージェントごとのagents.list[].heartbeat.everyを設定します。無効にするには0mを使います。 - プロンプト本文(
agents.defaults.heartbeat.promptで設定可能):Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK. - Heartbeat プロンプトは、ユーザーメッセージとしてそのまま送信されます。システム プロンプトには「Heartbeat」セクションが含まれ、実行は内部的にフラグ付けされます。
- アクティブ時間(
heartbeat.activeHours)は、設定されたタイムゾーンでチェックされます。 ウィンドウ外では、Heartbeat はウィンドウ内の次のティックまでスキップされます。
heartbeat プロンプトの目的
デフォルトプロンプトは意図的に広めに作られています:- バックグラウンドタスク: 「未処理タスクを考慮する」は、エージェントに フォローアップ(受信箱、カレンダー、リマインダー、キュー済み作業)を見直し、緊急なものを表面化するよう促します。
- 人間へのチェックイン: 「日中は時々 human を軽くチェックする」は、 時折の軽い「何か必要ですか?」メッセージを促しますが、 設定されたローカルタイムゾーンを使うことで夜間のスパムは避けます(/concepts/timezone を参照)。
agents.defaults.heartbeat.prompt(または
agents.list[].heartbeat.prompt)をカスタム本文(そのまま送信されます)に設定してください。
応答契約
- 注意が必要なことが何もなければ、
HEARTBEAT_OKで返信します。 - Heartbeat 実行中、OpenClaw は、返信の先頭または末尾に
HEARTBEAT_OKが現れた場合、それを ack として扱います。残りの内容が ≤ackMaxChars(デフォルト: 300)であれば、そのトークンは取り除かれ、返信は 破棄されます。 HEARTBEAT_OKが返信の途中に現れた場合は、特別扱いされません。- アラートの場合は、
HEARTBEAT_OKを含めないでください。アラート本文だけを返します。
HEARTBEAT_OK は除去され、
ログに記録されます。メッセージが HEARTBEAT_OK だけの場合は破棄されます。
設定
スコープと優先順位
agents.defaults.heartbeatはグローバルな heartbeat 動作を設定します。agents.list[].heartbeatはその上にマージされます。いずれかのエージェントにheartbeatブロックがある場合、そのエージェントだけ が heartbeat を実行します。channels.defaults.heartbeatはすべてのチャネルの可視性デフォルトを設定します。channels.<channel>.heartbeatはチャネルデフォルトを上書きします。channels.<channel>.accounts.<id>.heartbeat(マルチアカウントチャネル)はチャネルごとの設定を上書きします。
エージェントごとの heartbeat
いずれかのagents.list[] エントリに heartbeat ブロックが含まれている場合、そのエージェントだけ
が heartbeat を実行します。エージェントごとのブロックは agents.defaults.heartbeat
の上にマージされます(そのため、共通デフォルトを一度設定し、エージェントごとに上書きできます)。
例: 2 つのエージェントがあり、heartbeat を実行するのは 2 つ目だけです。
アクティブ時間の例
特定のタイムゾーンの業務時間に heartbeat を制限します:24/7 セットアップ
Heartbeat を終日実行したい場合は、次のいずれかのパターンを使います:activeHours自体を省略する(時間ウィンドウ制限なし。これがデフォルト動作です)。- 1 日全体のウィンドウを設定する:
activeHours: { start: "00:00", end: "24:00" }。
start と end を同じ時刻にしないでください(たとえば 08:00 から 08:00)。
これは幅 0 のウィンドウとして扱われるため、Heartbeat は常にスキップされます。
マルチアカウントの例
Telegram のようなマルチアカウントチャネルで特定のアカウントを対象にするにはaccountId を使います:
フィールドメモ
every: heartbeat 間隔(期間文字列。デフォルト単位 = 分)。model: heartbeat 実行用の任意のモデル上書き(provider/model)。includeReasoning: 有効時、利用可能であれば別個のReasoning:メッセージも配信します(/reasoning onと同じ形式)。lightContext: true の場合、heartbeat 実行では軽量な bootstrap context を使い、ワークスペース bootstrap ファイルからHEARTBEAT.mdのみを保持します。isolatedSession: true の場合、各 heartbeat は以前の会話履歴がない新しいセッションで実行されます。cron のsessionTarget: "isolated"と同じ分離パターンを使います。heartbeat ごとのトークンコストを大幅に削減します。最大限に節約するにはlightContext: trueと組み合わせてください。配信ルーティングでは引き続きメインセッションコンテキストを使います。session: heartbeat 実行用の任意のセッションキー。main(デフォルト): エージェントのメインセッション。- 明示的なセッションキー(
openclaw sessions --jsonまたは sessions CLI からコピー)。 - セッションキー形式: Sessions と Groups を参照してください。
target:last: 最後に使われた外部チャネルへ配信します。- 明示的なチャネル: 設定済みの任意のチャネルまたはプラグイン id。例:
discord、matrix、telegram、whatsapp。 none(デフォルト): heartbeat は実行しますが、外部には配信しません。
directPolicy: 直接/DM 配信動作を制御します:allow(デフォルト): 直接/DM への heartbeat 配信を許可します。block: 直接/DM 配信を抑制します(reason=dm-blocked)。
to: 任意の受信者上書き(チャネル固有 id。たとえば WhatsApp の E.164 や Telegram の chat id)。Telegram の topic/thread では<chatId>:topic:<messageThreadId>を使います。accountId: マルチアカウントチャネル用の任意のアカウント id。target: "last"の場合、解決された最後のチャネルがアカウント対応ならそのチャネルに適用され、そうでなければ無視されます。アカウント id が解決されたチャネルの設定済みアカウントと一致しない場合、配信はスキップされます。prompt: デフォルトのプロンプト本文を上書きします(マージはされません)。ackMaxChars: 配信前にHEARTBEAT_OKの後に許可される最大文字数。suppressToolErrorWarnings: true の場合、heartbeat 実行中のツールエラー警告ペイロードを抑制します。activeHours: heartbeat 実行を時間ウィンドウに制限します。start(HH:MM、含む。1 日の開始には00:00を使用)、end(HH:MM、含まない。1 日の終わりには24:00を使用可能)、および任意のtimezoneを持つオブジェクト。- 省略または
"user":agents.defaults.userTimezoneが設定されていればそれを使い、そうでなければホストシステムのタイムゾーンにフォールバックします。 "local": 常にホストシステムのタイムゾーンを使います。- 任意の IANA 識別子(例:
America/New_York): それを直接使います。無効な場合は上記の"user"動作にフォールバックします。 - アクティブウィンドウでは
startとendは等しくしてはいけません。等しい値は幅 0 として扱われます(常にウィンドウ外)。 - アクティブウィンドウ外では、Heartbeat はウィンドウ内の次のティックまでスキップされます。
- 省略または
配信動作
- Heartbeat はデフォルトでエージェントのメインセッション(
agent:<id>:<mainKey>)で実行され、session.scope = "global"の場合はglobalになります。特定のチャネルセッション(Discord/WhatsApp など)に上書きするにはsessionを設定します。 sessionは実行コンテキストにのみ影響します。配信はtargetとtoによって制御されます。- 特定のチャネル/受信者へ配信するには、
target+toを設定します。target: "last"の場合、 配信にはそのセッションの最後の外部チャネルが使われます。 - Heartbeat 配信では、デフォルトで直接/DM の送信先が許可されます。heartbeat ターン自体は実行しつつ直接送信先への送信を抑制するには
directPolicy: "block"を設定します。 - メインキューがビジーの場合、Heartbeat はスキップされ、後で再試行されます。
targetが外部の送信先に解決されない場合でも、実行自体は行われますが、 送信メッセージは送られません。showOk、showAlerts、useIndicatorがすべて無効な場合、実行はreason=alerts-disabledとして事前にスキップされます。- アラート配信のみが無効な場合でも、OpenClaw は heartbeat を実行し、期限タスクのタイムスタンプを更新し、セッションのアイドルタイムスタンプを復元し、外向きのアラートペイロードを抑制できます。
- Heartbeat 専用の返信はセッションを生かし続けません。最後の
updatedAtは復元されるため、アイドル期限切れは通常どおり動作します。 - 切り離された background tasks は、メインセッションがすばやく何かに気づくべきときにシステムイベントをエンキューし、heartbeat を起こすことができます。その wake によって heartbeat 実行が background task になることはありません。
可視性の制御
デフォルトでは、HEARTBEAT_OK の確認応答は抑制され、アラート内容のみが
配信されます。これをチャネルごとまたはアカウントごとに調整できます:
各フラグの意味
showOk: モデルが OK のみの返信を返した場合にHEARTBEAT_OKの確認応答を送信します。showAlerts: モデルが非 OK の返信を返した場合にアラート内容を送信します。useIndicator: UI のステータス表示向けにインジケーターイベントを発行します。
チャネルごととアカウントごとの例
よくあるパターン
| Goal | Config |
|---|---|
| デフォルト動作(OK は無音、アラートは送信) | (設定不要) |
| 完全に無音(メッセージなし、インジケーターなし) | channels.defaults.heartbeat: { showOk: false, showAlerts: false, useIndicator: false } |
| インジケーターのみ(メッセージなし) | channels.defaults.heartbeat: { showOk: false, showAlerts: false, useIndicator: true } |
| 1 つのチャネルでのみ OK を表示 | channels.telegram.heartbeat: { showOk: true } |
HEARTBEAT.md(任意)
ワークスペースに HEARTBEAT.md ファイルが存在する場合、デフォルトプロンプトは
エージェントにそれを読むよう指示します。これは「heartbeat チェックリスト」と考えてください。小さく、安定していて、
30 分ごとに含めても安全なものです。
HEARTBEAT.md が存在しても実質的に空(空行と # Heading のような markdown
見出しだけ)の場合、OpenClaw は API 呼び出しを節約するため heartbeat 実行をスキップします。
そのスキップは reason=empty-heartbeat-file として報告されます。
ファイルがない場合でも heartbeat は実行され、モデルが何をすべきか判断します。
プロンプト肥大化を避けるため、小さく保ってください(短いチェックリストやリマインダー)。
HEARTBEAT.md の例:
tasks: ブロック
HEARTBEAT.md は、heartbeat 自体の中で間隔ベースの
チェックを行うための、小さな構造化 tasks: ブロックもサポートしています。
例:
- OpenClaw は
tasks:ブロックを解析し、各タスクをそれぞれのintervalに照らしてチェックします。 - そのティックで期限が来ているタスクだけが heartbeat プロンプトに含まれます。
- 期限が来ているタスクがなければ、無駄なモデル呼び出しを避けるため heartbeat 全体がスキップされます(
reason=no-tasks-due)。 HEARTBEAT.md内のタスク以外の内容は保持され、期限が来ているタスクリストの後に追加コンテキストとして追記されます。- タスクの最終実行タイムスタンプはセッション状態(
heartbeatTaskState)に保存されるため、通常の再起動後も間隔は維持されます。 - タスクタイムスタンプが進むのは、heartbeat 実行が通常の返信経路を完了した後だけです。
empty-heartbeat-file/no-tasks-dueによりスキップされた実行では、タスクは完了済みとして記録されません。
エージェントは HEARTBEAT.md を更新できますか?
はい。そう依頼すれば可能です。
HEARTBEAT.md はエージェントワークスペース内の通常のファイルなので、
通常のチャットで次のようにエージェントへ指示できます:
- 「毎日のカレンダーチェックを追加するよう
HEARTBEAT.mdを更新して。」 - 「より短く、受信箱のフォローアップに集中するよう
HEARTBEAT.mdを書き直して。」
HEARTBEAT.md に入れないでください。プロンプトコンテキストの一部になります。
手動 wake(オンデマンド)
次のコマンドで、システムイベントをエンキューし、即座に heartbeat をトリガーできます:heartbeat が設定されている場合、手動 wake はそれら
各エージェントの heartbeat を即座に実行します。
次のスケジュールティックまで待つには --mode next-heartbeat を使います。
reasoning 配信(任意)
デフォルトでは、Heartbeat は最終的な「answer」ペイロードのみを配信します。 透明性がほしい場合は、次を有効にします:agents.defaults.heartbeat.includeReasoning: true
Reasoning: の付いた別個のメッセージも配信します(/reasoning on と同じ形式)。これは、エージェントが複数のセッション/codex を管理していて、なぜ
通知する判断をしたのかを見たい場合に便利ですが、望まないほど多くの内部詳細を漏らす可能性もあります。グループチャットでは無効のままにしておくことを推奨します。
コスト意識
Heartbeat は完全なエージェントターンを実行します。間隔を短くするとトークン消費が増えます。コストを減らすには:isolatedSession: trueを使って会話履歴全体を送らないようにする(1 実行あたり約 100K トークンから約 2-5K へ削減)。lightContext: trueを使って bootstrap ファイルをHEARTBEAT.mdだけに制限する。- より安価な
modelを設定する(例:ollama/llama3.2:1b)。 HEARTBEAT.mdを小さく保つ。- 内部状態更新だけが必要なら
target: "none"を使う。
関連
- Automation & Tasks — すべての自動化メカニズムの概要
- Background Tasks — 切り離された作業がどのように追跡されるか
- Timezone — タイムゾーンが heartbeat スケジューリングに与える影響
- Troubleshooting — 自動化の問題をデバッグする方法