콘텐츠로 이동

Heartbeat로 에이전트 똑똑하게 관리하기

Heartbeat는 메인 session에서 주기적인 agent turn을 실행해서, 모델이 여러분에게 스팸을 보내지 않고도 주의가 필요한 사항을 스스로 파악해 알려줄 수 있게 해줍니다.

Heartbeat는 예약된 메인 session turn이며, background task 레코드를 생성하지는 않아요. Task 레코드는 별도의 작업(ACP 실행, subagent, 격리된 cron 작업 등)을 위한 것이거든요.

Troubleshooting: /automation/troubleshooting

  1. Heartbeat를 활성화된 상태로 두거나(기본값은 30m, Anthropic OAuth/setup-token의 경우 1h) 원하는 주기를 설정하세요.
  2. agent workspace에 HEARTBEAT.md라는 작은 체크리스트 파일을 만드세요 (선택 사항이지만 추천합니다).
  3. Heartbeat 메시지가 어디로 전달될지 결정하세요 (기본값은 target: "none"이며, 마지막 연락처로 보내려면 target: "last"로 설정합니다).
  4. 선택 사항: 투명성을 위해 Heartbeat reasoning 전달 기능을 활성화하세요.
  5. 선택 사항: Heartbeat 실행 시 HEARTBEAT.md만 필요한 경우 가벼운 bootstrap context를 사용하세요.
  6. 선택 사항: 매번 전체 대화 내역을 보내지 않도록 isolated session을 활성화하세요.
  7. 선택 사항: Heartbeat를 특정 활동 시간(현지 시간)으로 제한하세요.

설정 예시:

{
agents: {
defaults: {
heartbeat: {
every: "30m",
target: "last", // explicit delivery to last contact (default is "none")
directPolicy: "allow", // default: allow direct/DM targets; set "block" to suppress
lightContext: true, // optional: only inject HEARTBEAT.md from bootstrap files
isolatedSession: true, // optional: fresh session each run (no conversation history)
// 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 프롬프트는 user message로 있는 그대로 전송됩니다. system prompt에는 “Heartbeat” 섹션이 포함되며, 해당 실행은 내부적으로 플래그가 지정됩니다.
  • 활동 시간(heartbeat.activeHours)은 설정된 timezone에서 확인합니다. 시간 범위 밖에서는 시간대 안으로 들어오는 다음 tick까지 Heartbeat를 건너뜁니다.

기본 프롬프트는 의도적으로 넓은 범위를 다루도록 되어 있어요.

  • Background tasks: “남은 작업 고려”라는 지침은 에이전트가 후속 작업(inbox, calendar, 미리 알림, 대기 중인 작업)을 검토하고 긴급한 사항을 알리도록 유도합니다.
  • Human check-in: “낮 시간 동안 사용자 상태 확인” 지침은 가끔 “필요한 게 있는지” 묻는 가벼운 메시지를 보내도록 유도합니다. 설정된 현지 timezone을 사용하므로 밤중에 스팸을 보낼 일은 없어요 (/concepts/timezone 참고).

Heartbeat는 완료된 background tasks에 반응할 수 있지만, Heartbeat 실행 자체가 task record를 생성하지는 않습니다.

만약 Heartbeat가 “Gmail PubSub 통계 확인”이나 “Gateway 상태 검증”처럼 아주 구체적인 작업을 수행하길 원한다면, agents.defaults.heartbeat.prompt(또는 agents.list[].heartbeat.prompt)를 원하는 내용으로 직접 설정해 보세요.

  • 특별히 주의가 필요한 사항이 없다면 **HEARTBEAT_OK**라고 응답하세요.
  • Heartbeat 실행 중에 OpenClaw는 응답의 시작 또는 끝에 HEARTBEAT_OK가 나타나면 이를 확인(ack)으로 간주합니다. 이 토큰은 제거되며, 남은 내용이 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-6",
includeReasoning: false, // default: false (deliver separate Reasoning: message when available)
lightContext: false, // default: false; true keeps only HEARTBEAT.md from workspace bootstrap files
isolatedSession: false, // default: false; true runs each heartbeat in a fresh session (no conversation history)
target: "last", // default: none | options: last | none | <channel id> (core or plugin, e.g. "bluebubbles")
to: "+15551234567", // optional channel-specific override
accountId: "ops-bot", // optional multi-account channel id
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가 그 위에 병합돼요. 만약 어떤 agent에 heartbeat 블록이 있다면, 해당 agent들만 heartbeat를 실행해요.
  • channels.defaults.heartbeat는 모든 channel의 가시성 기본값을 설정해요.
  • channels.<channel>.heartbeat는 channel 기본값을 덮어써요.
  • channels.<channel>.accounts.<id>.heartbeat (다중 계정 channel)는 계정별 설정을 덮어써요.

agents.list[] 항목에 heartbeat 블록이 포함되어 있으면, 해당 agent들만 heartbeat를 실행해요. 에이전트별 블록은 agents.defaults.heartbeat 위에 병합되므로, 공통 기본값을 한 번 설정한 뒤 agent마다 필요한 부분만 덮어쓸 수 있어요.

예시: 두 개의 agent 중 두 번째 agent만 heartbeat를 실행하는 경우예요.

{
agents: {
defaults: {
heartbeat: {
every: "30m",
target: "last", // explicit delivery to last contact (default is "none")
},
},
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.",
},
},
],
},
}

특정 타임존의 업무 시간으로 heartbeat를 제한할 수 있어요.

{
agents: {
defaults: {
heartbeat: {
every: "30m",
target: "last", // explicit delivery to last contact (default is "none")
activeHours: {
start: "09:00",
end: "22:00",
timezone: "America/New_York", // optional; uses your userTimezone if set, otherwise host tz
},
},
},
},
}

이 시간 범위 밖(동부 표준시 기준 오전 9시 이전 또는 오후 10시 이후)에는 heartbeat가 생략돼요. 범위 내에서 예약된 다음 tick은 정상적으로 실행돼요.

하루 종일 heartbeat를 실행하고 싶다면 다음 패턴 중 하나를 사용하세요.

  • activeHours를 완전히 생략하세요 (시간 제한이 없는 기본 동작이에요).
  • 전체 시간 범위를 설정하세요: activeHours: { start: "00:00", end: "24:00" }.

start와 end 시간을 동일하게 설정하지 마세요 (예: 08:00에서 08:00). 이 경우 너비가 0인 윈도우로 처리되어 heartbeat가 항상 생략돼요.

Telegram과 같은 다중 계정 channel에서 특정 계정을 타겟팅하려면 accountId를 사용하세요.

{
agents: {
list: [
{
id: "ops",
heartbeat: {
every: "1h",
target: "telegram",
to: "12345678:topic:42", // optional: route to a specific topic/thread
accountId: "ops-bot",
},
},
],
},
channels: {
telegram: {
accounts: {
"ops-bot": { botToken: "YOUR_TELEGRAM_BOT_TOKEN" },
},
},
},
}
  • every: heartbeat 간격이에요 (기간 문자열이며, 기본 단위는 분이에요).
  • model: heartbeat 실행 시 사용할 모델을 별도로 지정할 수 있어요 (provider/model).
  • includeReasoning: 활성화하면 사용 가능할 때 별도의 Reasoning: 메시지도 함께 전달해요 (/reasoning on과 동일한 형태예요).
  • lightContext: true로 설정하면 heartbeat 실행 시 가벼운 bootstrap context를 사용하며, workspace bootstrap 파일 중 HEARTBEAT.md만 유지해요.
  • isolatedSession: true로 설정하면 각 heartbeat가 이전 대화 기록이 없는 새로운 session에서 실행돼요. cron의 sessionTarget: "isolated"와 동일한 격리 패턴을 사용해요. heartbeat당 token 비용을 획기적으로 줄여주며, lightContext: true와 함께 사용하면 비용 절감 효과가 극대화돼요. 전송 라우팅은 여전히 메인 session context를 사용해요.
  • session: heartbeat 실행을 위한 선택적 session key예요.
    • main (기본값): agent의 메인 session이에요.
    • 명시적 session key: openclaw sessions --json 또는 sessions CLI에서 복사해서 사용하세요.
    • Session key 형식은 Sessions 및 Groups를 참고하세요.
  • target:
    • last: 마지막으로 사용된 외부 channel로 전달해요.
    • 명시적 channel: 설정된 channel이나 plugin id를 입력하세요 (예: discord, matrix, telegram, whatsapp).
    • none (기본값): heartbeat를 실행하지만 외부로 전송하지는 않아요.
  • directPolicy: direct/DM 전송 동작을 제어해요.
    • allow (기본값): direct/DM heartbeat 전송을 허용해요.
    • block: direct/DM 전송을 차단해요 (reason=dm-blocked).
  • to: 수신자를 별도로 지정할 때 사용해요 (channel별 id, 예: WhatsApp의 E.164 또는 Telegram chat id). Telegram topic/thread의 경우 <chatId>:topic:<messageThreadId> 형식을 사용하세요.
  • accountId: 다중 계정 channel을 위한 선택적 계정 id예요. target: "last"일 때, 해당 계정 id는 확인된 마지막 channel이 계정을 지원하는 경우에만 적용되며, 그렇지 않으면 무시돼요. 계정 id가 확인된 channel의 설정된 계정과 일치하지 않으면 전송이 생략돼요.
  • prompt: 기본 prompt 본문을 덮어써요 (병합되지 않아요).
  • ackMaxChars: 전송 전 HEARTBEAT_OK 이후에 허용되는 최대 문자 수예요.
  • suppressToolErrorWarnings: true일 때 heartbeat 실행 중 발생하는 tool error 경고 페이로드를 숨겨요.
  • activeHours: heartbeat 실행을 특정 시간대로 제한해요. start (HH:MM, 포함, 하루 시작은 00:00), end (HH:MM, 미포함, 하루 끝은 24:00), 그리고 선택 사항인 timezone 객체예요.
    • 생략하거나 "user"로 설정하면: agents.defaults.userTimezone이 설정된 경우 이를 사용하고, 그렇지 않으면 호스트 시스템 타임존을 사용해요.
    • "local": 항상 호스트 시스템 타임존을 사용해요.
    • IANA 식별자 (예: America/New_York): 직접 사용되며, 유효하지 않으면 위의 "user" 동작으로 돌아가요.
    • 활성 윈도우를 위해 start와 end는 같으면 안 돼요. 같은 값은 너비가 0인 것으로 간주되어 항상 윈도우 밖으로 처리돼요.
    • 활성 시간대 밖에서는 윈도우 내의 다음 tick까지 heartbeat가 생략돼요.
  • Heartbeat는 기본적으로 agent의 메인 session(agent:<id>:<mainKey>)에서 실행되거나, session.scope = "global"인 경우 global에서 실행돼요. 특정 channel session(Discord/WhatsApp 등)으로 덮어쓰려면 session을 설정하세요.
  • session은 실행 context에만 영향을 주며, 전송은 target과 to에 의해 제어돼요.
  • 특정 channel/수신자에게 전달하려면 target + to를 설정하세요. target: "last"를 사용하면 해당 session의 마지막 외부 channel을 통해 전송돼요.
  • Heartbeat 전송은 기본적으로 direct/DM 타겟을 허용해요. heartbeat turn은 실행하면서 direct 타겟 전송만 막으려면 directPolicy: "block"을 설정하세요.
  • 메인 큐가 바쁘면 heartbeat는 생략되고 나중에 다시 시도돼요.
  • target이 외부 목적지로 확인되지 않으면, 실행은 되지만 외부 메시지는 전송되지 않아요.
  • Heartbeat 전용 응답은 session을 유지(keep-alive)하지 않아요. 마지막 updatedAt이 복원되므로 유휴 만료(idle expiry)가 정상적으로 작동해요.
  • 분리된 background tasks는 시스템 이벤트를 큐에 넣고, 메인 session이 무언가를 빠르게 감지해야 할 때 heartbeat를 깨울 수 있어요. 이 깨움 동작이 heartbeat를 background task로 실행하게 만들지는 않아요.

개발을 하다 보면 에이전트가 조용히 일하길 바랄 때도 있고, 매 순간 상태를 보고받고 싶을 때도 있죠. OpenClaw에서는 이런 가시성을 아주 세밀하게 설정할 수 있어요.

기본적으로 알림 콘텐츠가 전달되는 동안 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 실행을 아예 건너뛰게 됩니다.

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 }
특정 채널에서만 OK 메시지 확인channels.telegram.heartbeat: { showOk: true }

워크스페이스에 HEARTBEAT.md 파일이 있다면, 기본 프롬프트가 에이전트에게 이 파일을 읽으라고 지시해요. 이 파일은 30분마다 포함해도 부담 없는 작고 안정적인 “heartbeat 체크리스트”라고 생각하면 좋습니다.

만약 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.md를 더 짧게 다시 써줘.”

만약 에이전트가 알아서 수정하길 원한다면, heartbeat 프롬프트에 “체크리스트가 오래되었다면 더 나은 내용으로 HEARTBEAT.md를 업데이트해”라는 문구를 명시적으로 포함할 수도 있어요.

보안 주의사항: HEARTBEAT.md는 프롬프트 컨텍스트의 일부가 되므로 API key, 전화번호, 프라이빗 토큰 같은 민감한 정보는 절대 넣지 마세요.

AI Setup Assistant

시스템 이벤트를 큐에 추가하고 즉시 heartbeat를 트리거하고 싶다면 다음 명령어를 사용하면 돼요.

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

여러 agent에 heartbeat가 설정되어 있는 경우, 수동 깨우기를 실행하면 각 agent의 heartbeat가 즉시 실행됩니다.

다음으로 예정된 tick까지 기다리려면 --mode next-heartbeat를 사용하세요.

기본적으로 heartbeat는 최종 “답변” 페이로드만 전달해요.

작동 과정을 투명하게 확인하고 싶다면 이 설정을 활성화해 보세요.

  • agents.defaults.heartbeat.includeReasoning: true

이 옵션을 켜면 heartbeat가 Reasoning:이라는 접두사가 붙은 별도의 메시지를 함께 전달합니다 (/reasoning on과 동일한 형태예요). agent가 여러 세션이나 codex를 관리하고 있을 때, 왜 나에게 알림을 보냈는지 이유를 파악하기 좋습니다. 다만 원치 않는 내부 디테일까지 노출될 수 있으니, 그룹 채팅에서는 이 기능을 꺼두는 편이 나아요.

Heartbeat는 에이전트의 전체 턴(turn)을 실행해요. 그래서 실행 간격이 짧을수록 더 많은 토큰을 소모하게 되죠. 비용을 효율적으로 관리하려면 다음 방법들을 참고해 보세요.

  • isolatedSession: true를 사용하세요. 전체 대화 기록을 매번 보내지 않기 때문에, 실행당 토큰 소모량을 약 100K에서 2~5K 정도로 크게 줄일 수 있어요.
  • lightContext: true를 설정해서 부트스트랩 파일을 HEARTBEAT.md 하나로 제한하세요.
  • 더 저렴한 model을 설정하세요 (예: ollama/llama3.2:1b).
  • HEARTBEAT.md 파일 내용을 간결하게 유지하세요.
  • 내부 상태 업데이트만 필요한 경우에는 target: "none"을 사용하세요.
OpenClaw

OpenClaw Expert

아직 막혀 있나요?

이 문서에서 답을 못 찾았다면 OpenClaw Expert에게 바로 물어보세요.