Heartbeat (Gateway)

Heartbeat vs Cron? 각각을 언제 사용해야 하는지에 대한 가이드는 Cron vs Heartbeat를 참조하세요.

Heartbeat는 메인 세션에서 주기적인 에이전트 턴을 실행하여 모델이 스팸 없이 주의가 필요한 사항을 표면화할 수 있도록 합니다.

빠른 시작 (초보자용)

  1. Heartbeat를 활성화 상태로 유지합니다 (기본값은 30m, Anthropic OAuth/setup-token의 경우 1h) 또는 자신만의 주기를 설정합니다.
  2. 에이전트 워크스페이스에 작은 HEARTBEAT.md 체크리스트를 생성합니다 (선택 사항이지만 권장됨).
  3. Heartbeat 메시지가 어디로 가야 할지 결정합니다 (target: "last"가 기본값).
  4. 선택 사항: 투명성을 위해 heartbeat reasoning 전달을 활성화합니다.
  5. 선택 사항: Heartbeat를 활동 시간(현지 시간)으로 제한합니다.

예제 설정:

{
  agents: {
    defaults: {
      heartbeat: {
        every: "30m",
        target: "last",
        // activeHours: { start: "08:00", end: "24:00" },
        // includeReasoning: true, // optional: send separate `Reasoning:` message too
      }
    }
  }
}

기본값

  • 간격: 30m (Anthropic OAuth/setup-token이 감지된 인증 모드일 경우 1h). 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 프롬프트의 용도

기본 프롬프트는 의도적으로 광범위합니다:

  • 백그라운드 작업: "미해결 작업 고려"는 에이전트가 후속 조치(받은 편지함, 캘린더, 알림, 대기 중인 작업)를 검토하고 긴급한 사항을 표면화하도록 유도합니다.
  • 사람 체크인: "낮 시간 동안 가끔 사람을 체크업"은 가끔 가벼운 "필요한 것이 있나요?" 메시지를 유도하지만, 설정된 현지 시간대를 사용하여 야간 스팸을 방지합니다 (/concepts/timezone 참조).

Heartbeat가 매우 구체적인 작업(예: "Gmail PubSub 통계 확인" 또는 "gateway 상태 확인")을 수행하도록 하려면, agents.defaults.heartbeat.prompt (또는 agents.list[].heartbeat.prompt)를 사용자 정의 본문(그대로 전송됨)으로 설정합니다.

응답 규약

  • 주의가 필요한 사항이 없으면 **HEARTBEAT_OK**로 응답합니다.
  • Heartbeat 실행 중에 OpenClaw는 HEARTBEAT_OK가 응답의 시작 또는 끝에 나타날 때 확인으로 처리합니다. 토큰이 제거되고 나머지 내용이 ackMaxChars (기본값: 300)인 경우 응답이 삭제됩니다.
  • HEARTBEAT_OK가 응답의 중간에 나타나면 특별히 처리되지 않습니다.
  • 경고의 경우 HEARTBEAT_OK를 포함하지 마십시오; 경고 텍스트만 반환합니다.

Heartbeat 외부에서는 메시지의 시작/끝에 있는 불필요한 HEARTBEAT_OK가 제거되고 로깅됩니다; HEARTBEAT_OK만 있는 메시지는 삭제됩니다.

설정

{
  agents: {
    defaults: {
      heartbeat: {
        every: "30m",           // default: 30m (0m disables)
        model: "anthropic/claude-opus-4-5",
        includeReasoning: false, // default: false (deliver separate Reasoning: message when available)
        target: "last",         // last | none | <channel id> (core or plugin, e.g. "bluebubbles")
        to: "+15551234567",     // optional channel-specific override
        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.",
        ackMaxChars: 300         // max chars allowed after 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 상위에 병합됩니다 (따라서 공유 기본값을 한 번 설정하고 에이전트별로 재정의할 수 있습니다).

예제: 두 개의 에이전트, 두 번째 에이전트만 heartbeat를 실행합니다.

{
  agents: {
    defaults: {
      heartbeat: {
        every: "30m",
        target: "last"
      }
    },
    list: [
      { id: "main", default: true },
      {
        id: "ops",
        heartbeat: {
          every: "1h",
          target: "whatsapp",
          to: "+15551234567",
          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."
        }
      }
    ]
  }
}

필드 노트

  • every: heartbeat 간격 (지속 시간 문자열; 기본 단위 = 분).
  • model: heartbeat 실행을 위한 선택적 모델 재정의 (provider/model).
  • includeReasoning: 활성화되면 사용 가능한 경우 별도의 Reasoning: 메시지도 전달합니다 (/reasoning on과 동일한 형태).
  • session: heartbeat 실행을 위한 선택적 세션 키.
    • main (기본값): 에이전트 메인 세션.
    • 명시적 세션 키 (openclaw sessions --json 또는 sessions CLI에서 복사).
    • 세션 키 형식: SessionsGroups 참조.
  • target:
    • last (기본값): 마지막으로 사용된 외부 채널로 전달합니다.
    • 명시적 채널: whatsapp / telegram / discord / googlechat / slack / msteams / signal / imessage.
    • none: heartbeat를 실행하지만 외부로 전달하지 않습니다.
  • to: 선택적 수신자 재정의 (채널별 id, 예: WhatsApp의 경우 E.164 또는 Telegram 채팅 id).
  • prompt: 기본 프롬프트 본문을 재정의합니다 (병합되지 않음).
  • ackMaxChars: 전달 전 HEARTBEAT_OK 이후 허용되는 최대 문자 수.

전달 동작

  • Heartbeat는 기본적으로 에이전트의 메인 세션(agent:<id>:<mainKey>)에서 실행되거나, session.scope = "global"일 때 global에서 실행됩니다. 특정 채널 세션(Discord/WhatsApp 등)으로 재정의하려면 session을 설정합니다.
  • session은 실행 컨텍스트에만 영향을 줍니다; 전달은 targetto에 의해 제어됩니다.
  • 특정 채널/수신자에게 전달하려면 target + to를 설정합니다. target: "last"를 사용하면 전달은 해당 세션의 마지막 외부 채널을 사용합니다.
  • 메인 큐가 바쁘면 heartbeat가 건너뛰어지고 나중에 재시도됩니다.
  • target이 외부 목적지로 해결되지 않으면 실행은 여전히 발생하지만 아웃바운드 메시지는 전송되지 않습니다.
  • Heartbeat 전용 응답은 세션을 활성 상태로 유지하지 않습니다; 마지막 updatedAt이 복원되어 유휴 만료가 정상적으로 작동합니다.

가시성 제어

기본적으로 HEARTBEAT_OK 확인은 억제되고 경고 내용은 전달됩니다. 채널별 또는 계정별로 이를 조정할 수 있습니다:

channels:
  defaults:
    heartbeat:
      showOk: false      # Hide HEARTBEAT_OK (default)
      showAlerts: true   # Show alert messages (default)
      useIndicator: true # Emit indicator events (default)
  telegram:
    heartbeat:
      showOk: true       # Show OK acknowledgments on Telegram
  whatsapp:
    accounts:
      work:
        heartbeat:
          showAlerts: false # Suppress alert delivery for this account

우선순위: 계정별 → 채널별 → 채널 기본값 → 내장 기본값.

각 플래그의 기능

  • showOk: 모델이 OK 전용 응답을 반환할 때 HEARTBEAT_OK 확인을 전송합니다.
  • showAlerts: 모델이 OK가 아닌 응답을 반환할 때 경고 내용을 전송합니다.
  • useIndicator: UI 상태 표면을 위한 인디케이터 이벤트를 방출합니다.

세 가지 모두 false인 경우 OpenClaw는 heartbeat 실행을 완전히 건너뜁니다 (모델 호출 없음).

채널별 vs 계정별 예제

channels:
  defaults:
    heartbeat:
      showOk: false
      showAlerts: true
      useIndicator: true
  slack:
    heartbeat:
      showOk: true # all Slack accounts
    accounts:
      ops:
        heartbeat:
          showAlerts: false # suppress alerts for the ops account only
  telegram:
    heartbeat:
      showOk: true

일반적인 패턴

목표설정
기본 동작 (조용한 OK, 경고 켜짐)(설정 불필요)
완전히 조용함 (메시지 없음, 인디케이터 없음)channels.defaults.heartbeat: { showOk: false, showAlerts: false, useIndicator: false }
인디케이터만 (메시지 없음)channels.defaults.heartbeat: { showOk: false, showAlerts: false, useIndicator: true }
한 채널에서만 OKchannels.telegram.heartbeat: { showOk: true }

HEARTBEAT.md (선택 사항)

워크스페이스에 HEARTBEAT.md 파일이 존재하면 기본 프롬프트는 에이전트에게 이를 읽도록 지시합니다. 이를 "heartbeat 체크리스트"로 생각하세요: 작고, 안정적이며, 30분마다 포함하기에 안전합니다.

HEARTBEAT.md가 존재하지만 사실상 비어 있는 경우(빈 줄과 # Heading과 같은 마크다운 헤더만 있음), OpenClaw는 API 호출을 절약하기 위해 heartbeat 실행을 건너뜁니다. 파일이 없으면 heartbeat는 여전히 실행되고 모델이 무엇을 할지 결정합니다.

프롬프트 비대화를 피하기 위해 작게 유지하세요 (짧은 체크리스트 또는 알림).

예제 HEARTBEAT.md:

# Heartbeat checklist

- Quick scan: anything urgent in inboxes?
- If it's daytime, do a lightweight check-in if nothing else is pending.
- If a task is blocked, write down *what is missing* and ask Peter next time.

에이전트가 HEARTBEAT.md를 업데이트할 수 있나요?

예 — 요청하면 가능합니다.

HEARTBEAT.md는 에이전트 워크스페이스의 일반 파일일 뿐이므로 (일반 채팅에서) 에이전트에게 다음과 같이 말할 수 있습니다:

  • "매일 캘린더 확인을 추가하도록 HEARTBEAT.md를 업데이트해."
  • "HEARTBEAT.md를 더 짧고 받은 편지함 후속 조치에 집중하도록 다시 작성해."

이것이 적극적으로 발생하기를 원한다면 heartbeat 프롬프트에 다음과 같은 명시적인 줄을 포함할 수도 있습니다: "체크리스트가 오래되면 더 나은 것으로 HEARTBEAT.md를 업데이트하세요."

안전 참고사항: API 키, 전화번호, 개인 토큰과 같은 비밀을 HEARTBEAT.md에 넣지 마세요 — 프롬프트 컨텍스트의 일부가 됩니다.

수동 깨우기 (온디맨드)

시스템 이벤트를 큐에 넣고 즉시 heartbeat를 트리거할 수 있습니다:

openclaw system event --text "Check for urgent follow-ups" --mode now

여러 에이전트에 heartbeat가 설정되어 있으면 수동 깨우기는 각 에이전트 heartbeat를 즉시 실행합니다.

다음 예약된 틱을 기다리려면 --mode next-heartbeat를 사용하세요.

Reasoning 전달 (선택 사항)

기본적으로 heartbeat는 최종 "답변" 페이로드만 전달합니다.

투명성을 원하면 다음을 활성화하세요:

  • agents.defaults.heartbeat.includeReasoning: true

활성화되면 heartbeat는 Reasoning:이 접두사로 붙은 별도의 메시지도 전달합니다 (/reasoning on과 동일한 형태). 이는 에이전트가 여러 세션/코덱스를 관리하고 있고 왜 당신에게 핑을 보내기로 결정했는지 보고 싶을 때 유용할 수 있습니다 — 하지만 원하는 것보다 더 많은 내부 세부 정보를 누출할 수도 있습니다. 그룹 채팅에서는 비활성화 상태를 유지하는 것이 좋습니다.

비용 인식

Heartbeat는 전체 에이전트 턴을 실행합니다. 더 짧은 간격은 더 많은 토큰을 소모합니다. HEARTBEAT.md를 작게 유지하고 내부 상태 업데이트만 원하는 경우 더 저렴한 model 또는 target: "none"을 고려하세요.