나의 OpenClaw 에이전트가 새벽 3시에 계속 고장 나서, 스스로를 수정하도록 가르쳤다
요약
AI 에이전트의 중단 문제를 해결하기 위해 자가 치유(self-healing) 기능을 구축한 사례를 다룹니다. 하트비트 시스템을 통한 상태 모니터링과 '드림 스윕' 프로세스를 이용한 메모리 최적화 패턴을 소개합니다.
핵심 포인트
- 하트비트 시스템을 통해 에이전트의 상태를 JSON 파일로 기록하고 모니터링함
- 단순 핑이 아닌 상태 파일 기반의 와치독(watchdog) 시스템 구축
- 드림 스윕(Dreaming Sweep)을 통해 장기 메모리의 노이즈를 제거하고 품질 관리
- 에이전트가 스스로 오류를 포착하고 복구할 수 있는 구조적 패턴 제시
나의 OpenClaw 에이전트가 3주 전 일요일에 충돌했습니다. 서서히 성능이 저하되는 것이 아니라, 그냥 멈춰버렸습니다. 매일 아침 내 일정을 준비하기 위해 실행되는 크론 잡 (cron job)이 작동했지만, 캘린더 API에 접속할 수 없었고, 재시도하거나 폴백 (fallback)하는 대신 모호한 에러를 기록하고 종료되었습니다. 나는 오전 10시가 되어서야 이를 알아차렸는데, 그때 나는 이미 20분 전에 도착해 있었어야 할 회의를 위해 줄을 서 있는 중이었습니다.
그 회의로 인해 나는 무언가를 잃었습니다. 아주 큰 것은 아니었습니다. 하지만 다음 한 주 동안, 내가 없어도 에러를 포착하고—더 중요한 것은—스스로 수정할 수 있는 시스템을 내 에이전트에 구축하게 만들기에는 충분한 계기였습니다.
이것은 AI 에이전트에 자가 치유 (self-healing) 기능을 구축하며 내가 배운 것들입니다. 추상적인 원칙이 아닙니다. 지금 내 컴퓨터에서 실제로 돌아가고 있는 실제 패턴들입니다.
패턴 1: 실제로 확인하는 하트비트 (Heartbeat)
대부분의 모니터링은 보여주기식입니다. 무언가 고장 났을 때 알림을 주도록 크론 (cron)을 설정하지만, 만약 그 크론 자체가 고장 난다면 당신은 여전히 눈먼 상태입니다.
OpenClaw의 하트비트 (heartbeat) 시스템은 설정 가능한 간격으로 실행되며 에이전트가 실제로 응답하는지 추적합니다. 기본 설정은 보수적입니다. 무언가 잘못되었다고 선언하기까지 오래 기다립니다. 나는 하트비트가 누락된 후 5분 이내에 복구 점검 (recovery check)이 트리거되도록 설정을 강화했습니다.
여기 핵심이 있습니다: 하트비트는 단순한 핑 (ping)이 아닙니다. 그것은 상태 파일 (state file)입니다. 내 에이전트가 실행될 때, 현재 상태를 JSON 파일에 기록합니다. 하트비트가 실행될 때, 그 파일을 읽습니다. 만약 타임스탬프 (timestamp)가 오래되었다면, 에이전트가 응답하지 않는다는 것을 알게 되고, 내가 텔레그램 (Telegram) 알림을 받기도 전에 재시작을 트리거할 수 있습니다.
// heartbeat-state.json (에이전트가 모든 중요한 작업 시 작성)
{
"lastAction": "cron-daily-planning",
...
이것의 묘미는 이렇습니다: 에이전트가 상태를 기록합니다. 하트비트가 이를 모니터링합니다. 와치독 (watchdog)이 이를 재시작합니다. 심각한 문제가 발생하지 않는 한 동시에 모두 실패할 수 없는 세 개의 분리된 시스템입니다.
패턴 2: 드림 스윕 (Dreaming Sweep) — 스스로 복구하는 메모리
매일 밤 새벽 2시, 나의 에이전트는 "꿈꾸는 (dreaming)" 프로세스를 실행합니다. 에이전트는 지난 24시간 동안의 자신의 회상 (recall) 항목들을 검토합니다. 모든 도구 호출 (tool call), 모든 결정, 그리고 반복적으로 나타난 모든 패턴을 살펴봅니다. 노이즈 속에서 신호를 찾는 것입니다.
대부분의 에이전트는 장기 메모리 (long-term memory)를 가지고 있습니다. 하지만 나의 에이전트는 큐레이션된 (curated) 장기 메모리를 가지고 있습니다. 드림 스윕 (dreaming sweep)은 후보들을 단계별로 분류하고 점수를 매기며, 최소 0.8의 품질 점수를 유지하면서 서로 다른 3개의 세션에 걸쳐 최소 3번의 별도 쿼리 (query)에서 나타난 항목만을 승격시킵니다. 그 외의 모든 것은 폐기됩니다.
이것이 과하다고 들릴 수도 있습니다. 하지만 그렇지 않습니다.
6개월 전, 나의 에이전트는 단 한 번 발생한 노이즈로 자신의 메모리를 오염시키고 있었습니다. 모든 특이한 쿼리, 모든 실험적인 도구 호출, 모든 실패한 시도들이 모두 동일한 비중으로 저장되었습니다. 실제로 중요한 무언가를 회상하려고 할 때, 그것은 수백 개의 무관한 일회성 정보들에 파묻혀 있었습니다.
드림 스윕이 이를 해결했습니다. 이제 나의 에이전트 내의 메모리에는 반감기 (half-life)가 존재합니다. 반복되지 않는 것들은 조용히 잊혀집니다. 중요한 것들은 — 계속해서 중요하기 때문에 — 복리로 쌓여갑니다.
패턴 3: 자신에게 거짓말을 하지 않는 셀프 체크 (Self-Check)
여기서 내가 예상하지 못했던 실패 모드 (failure mode)가 하나 있었습니다. 나의 에이전트가 자신이 직접 작성한 기준을 사용하여 자신의 작업물을 검증하고 있었던 것입니다. 이는 에이전트가 자신이 속임수를 쓸 수 있는 규칙을 사용하여 자신의 답변에 점수를 매기고 있음을 의미했습니다.
나는 에이전트에게 문서의 오류를 검토하라고 요청하곤 했습니다. 그러면 에이전트는 오류를 찾아내고 수정하더니, 자신의 수정 사항에 대해 95%의 신뢰도 (confidence)를 부여했습니다. 그것이 정확했냐고요? 아무도 모릅니다. 확실한 건 에이전트가 매우 자신만만했다는 점입니다.
나는 셀프 체크 루프 (self-check loop)를 폐기하고 이를 2단계 검증 방식으로 교체했습니다. 에이전트가 작업을 수행하면, 별도로 격리된 서브 에이전트 (sub-agent)가 다른 모델과 다른 프롬프트 구조 (prompt structure)를 사용하여 이를 검토합니다. 이때 서브 에이전트는 원래의 출력물에 접근할 수 없으며, 오직 원래의 작업 내용만 전달받습니다.
격리된 에이전트는 첫 번째 에이전트가 무엇이라고 말했는지 알 수 없습니다. 독립적으로 평가해야만 합니다. 만약 두 에이전트의 의견이 일치한다면, 그 신뢰도는 진짜입니다. 만약 의견이 다르다면, 나는 거짓된 합의가 아닌 '불일치'라는 정보를 얻게 됩니다.
비용이 많이 드는 것처럼 들릴 수 있습니다. 약간 그렇긴 합니다. 하지만 이 설정을 사용한 지 3일 만에 6번의 '조용한 실패 (silent failures)'를 잡아냈습니다. 각각의 사례는 만약 제가 원래 에이전트의 자기 평가 (self-assessment)를 믿었더라면 그대로 배포되었을 문제들이었습니다.
패턴 4: 체이닝(Chaining)되지 않는 크론 체인 (Cron Chain)
표준적인 크론 작업 (cron jobs)은 조용히 실패합니다. 설정을 해두고 잊어버리면, 6개월 뒤에야 3주 전 화요일부터 작동이 멈췄다는 사실을 발견하게 되고 아무도 눈치채지 못합니다.
저의 OpenClaw 크론은 단순히 체이닝되는 것이 아니라, '캐스케이드 (cascade)' 방식으로 작동합니다. 만약 오전 계획 수립 크론이 실패하면, 와치독 타이머 (watchdog timer)가 10분 이내에 이를 감지합니다. 이 타이머는 단순히 동일한 크론을 재시작하는 것이 아닙니다. 먼저 진단 (diagnostic)을 수행합니다. 어떤 API에 접속할 수 없었는지 확인하고, 현재 연결 상태를 점검한 뒤, 재시도하거나 캐시된 폴백 (cached fallback)을 사용하여 실패를 우회합니다.
만약 캘린더 API가 다운되면, 제 에이전트는 자신이 유지 관리하는 일반 텍스트 알림 파일로 전환합니다. API가 복구되면, 데이터를 조정 (reconcile)합니다. 그날 아침에 캘린더 알림을 받지는 못하겠지만, 아무것도 얻지 못하는 대신 무언가는 얻게 됩니다.
# watchdog timer — 메인 크론이 멈출 경우 트리거됨
[Unit]
Description=OpenClaw Cron Watchdog
...
systemd 타이머가 와치독을 감시합니다. 만약 와치독마저 멈춘다면, 이는 OS 레벨에서 심각한 문제가 발생했다는 뜻이며, 저는 그에 대한 알림도 받게 됩니다.
이것이 실제로 의미하는 바
에이전트에 자가 치유 (self-healing) 기능을 구축하는 것은 단순히 설치하는 '기능 (feature)'이 아닙니다. 그것은 '태도 (posture)'입니다. 당신은 무언가가 고장 날 것이라고 가정해야 하며, 그 대상은 단지 예측 가능한 것들에 국한되지 않습니다. 새벽 3시의 실패는 캘린더 API가 다운된 것이 아니었습니다. 그것은 크론 작업에 재시도 전략 (retry strategy), 폴백 출력 (fallback output), 또는 침묵을 포착할 와치독 (watchdog)이 없었기 때문이었습니다.
제가 에이전트를 유용한 스크립트가 아닌 프로덕션 인프라 (production infrastructure)처럼 취급하기 시작하자, 실패는 비용이 드는 문제가 아니라 교훈을 주는 과정이 되었습니다. 모든 고장은 에이전트가 다음 고장을 견뎌내기 위해 무엇이 필요한지 가르쳐 주었습니다.
에이전트가 아직 완전한 자율성을 갖춘 것은 아닙니다. 하지만 정말로 질문이 필요할 때, 질문을 던질 수 있을 만큼 충분히 오래 살아남는 법을 점점 더 잘 배우고 있습니다.
내가 배운 것: 자기 치유 (self-healing)는 단순히 활성화하는 설정이 아닙니다. 그것은 모니터링 (monitoring), 메모리 (memory), 검증 (verification), 그리고 폴백 (fallback) 등 모든 계층에 구축해야 하는 설계 철학 (design philosophy)입니다. 하트비트 (heartbeat)부터 시작하세요. 다른 모든 것은 무언가가 작동을 멈췄을 때를 아는 것에서부터 구축됩니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기