본문으로 건너뛰기

© 2026 Molayo

Qiita헤드라인2026. 06. 15. 06:26

【#7】Hermes Agent 해독하기

요약

Hermes Agent의 Kanban 영속 태스크 보드 시스템을 분석합니다. 기존 delegate_task의 동기적, 휘발성, 인간 부재 문제를 해결하기 위해 SQLite 기반의 영속성과 인간 개입이 가능한 상태 머신 메커니즘을 도입했습니다.

핵심 포인트

  • SQLite를 활용한 Kanban 영속 태스크 보드로 작업의 영속성 확보
  • 상태 머신을 통해 작업의 흐름(triage, todo, running 등) 관리
  • blocked 상태를 통해 인간의 개입 및 협업 구조 설계
  • CAS(Compare-and-Swap) 방식을 사용하여 락 없이 경합 방지
  • claim TTL 및 하트비트 임계값을 통한 작업 안정성 관리

연재 「Hermes Agent 해독하기」 제7회.

지난번의 delegate_task는 강력하지만, 3가지 약점이 있다. 동기 (Synchronous) (부모가 자식을 기다림), 휘발성 (Volatility) (프로세스가 종료되면 사라짐), 인간 부재 (Human Absence) (도중에 사람에게 물어볼 수 없음). 장기에 걸쳐 인간과 에이전트가 뒤섞이며, 중단되어도 재개할 수 있는 협업——이를 위해서는 별도의 메커니즘이 필요하다. 그것이 바로 **Kanban 영속 태스크 보드 (Kanban Persistent Task Board)**다. 약 14,000행(정확히는 14,032행)에 달하는 거대한 서브시스템으로, Hermes 중에서도 독립성이 높다.

todo |
delegate_task |
Kanban | |
|---|---|---|
| 영속성 | 세션 내 | 휘발 | 영속 (SQLite) |
| ... |
todo

(todo (제5회))는 세션 내의 망각 방지용이며, delegate_task (제6회)는 동기적인 fan-out이다. Kanban은 그 둘 모두와 다르며, 중단되어도 남고, 인간도 개입할 수 있으며, 여러 워커(Worker)가 피어(Peer)로서 협업하는 보드다.

보드는 SQLite에 영속화된다. 주요 테이블은 tasks / task_links (부모-자식 의존성) / task_comments (핸드오프(Handoff) + swarm blackboard) / task_events (감사 로그(Audit Log)) / task_runs (시도 이력) / task_attachments / kanban_notify_subs (gateway 알림 구독)이다.

태스크는 상태 머신(State Machine)을 가진다. VALID_STATUSEStriage / todo / scheduled / ready / running / blocked / review / done / archived이다. dispatch되는 본류는 todo → ready → running → done이며, blocked / scheduled / review가 분기로 포함된다.

blocked가 인간 개입의 입구다. 워커가 판단할 수 없는 국면에서 kanban_block을 호출하면, 이유(reason)가 보드에 게시되고, 인간(또는 orchestrator)이 kanban_unblock할 때까지 기다린다. unblock 후 부모 의존성이 이미 완료되었다면 ready로, 아직이라면 todo로 돌아간다.

여러 워커가 동일한 보드를 건드릴 때, 동일한 태스크를 이중으로 잡는 사고를 방지해야 한다. Hermes는 락(Lock)이 아니라 **CAS (Compare-and-Swap)**로 이를 해결한다.

**WAL +**로 트랜잭션을 시작 BEGIN IMMEDIATE

  • 태스크의 현재 상태를 읽고, 기대값과 일치하는 경우에만 claim을 작성 (compare-and-swap)
  • 경합(Contention)이 발생한 쪽은 실패를 감지하여 재시도(Retry)

이를 통해 명시적인 락 없이도 '선착순' 방식의 안전한 claim이 성립한다. 타임아웃 계열의 값은 다음 3가지이다 (kanban_db.py:111,121).

claim TTL: 15분 — claim의 유효 기간
heartbeat stale 임계값: 1시간 — 하트비트(Heartbeat)가 1시간 동안 끊기면 wedged(교착/정체) 상태로 판정
crash grace: 30초 — 크래시(Crash) 감지 유예 시간

이 부분은 골자 단계에서 오류가 있었던 지점이다. 'heartbeat 1시간'은 간격이 아니라 stale 임계값——즉, '1시간 동안 하트비트가 오지 않으면 죽은 것으로 간주한다'는 임계값이지, 1시간마다 고동을 친다는 의미가 아니다. claim TTL의 15분과는 별개의 것이므로 구분하여 작성하고 있다.

큰 태스크는 3단계로 전개된다.

decompose — 보조 LLM이 태스크를 서브태스크 그래프로 분해
specify — 각 서브태스크의 사양을 구체화
swarm — 워커 군단으로 병렬 실행

swarm의 구성은 root → workers → verifier → synthesizer이다. root가 묶고, workers가 실무를 수행하며, verifier가 검증하고, synthesizer가 통합한다. 워커 간의 정보 공유에는 blackboard (공유 칠판. 코드상에서는 [swarm:blackboard]로 확인 가능) 패턴을 사용한다——각 워커가 중간 결과를 칠판에 쓰고, 다른 워커가 그것을 읽는 방식이다.

delegate_task의 "요약만 부모에게 반환하는" 폐쇄적인 fan-out과 달리, swarm은 칠판(blackboard)을 통해 워커(worker)들끼리 수평적으로 정보를 흘려보낼 수 있다. 협업의 밀도가 한 단계 더 높다.

보드에 쌓인 태스크(task)는 누가 집어서 실행할 것인가. dispatcher가 그 역할을 담당한다.

  • Gateway 내에서 정기적으로 tick (순회)하며, ready 상태인 태스크를 찾는다.
  • 태스크를 발견하면 hermes -p <profile>워커를 서브프로세스(subprocess)로 기동한다.
  • 워커에는 HERMES_KANBAN_TASK / HERMES_KANBAN_BOARD / HERMES_KANBAN_DB / HERMES_KANBAN_WORKSPACES_ROOT 등이 환경 변수(environment variable)로 주입된다.
  • 워커는 HERMES_KANBAN_TASK의 유무에 따라 Kanban 툴 세트(제5회의 9개 툴)를 활성화한다.

태스크 지정이 CLI 플래그(예: --tasks <id> 형태)로 전달되는지, 아니면 환경 변수만으로 전달되는지는 현재 보유한 코드상에서 환경 변수 경유(HERMES_KANBAN_TASK)를 확실히 확인할 수 있는 범위 내에 있다. 여기서는 환경 변수 주입(env injection)으로 기술한다.

제5회에서 "HERMES_KANBAN_TASK 설정 시에만 Kanban 툴이 활성화된다"라고 기술한 것은 이 기동 경로와 대응된다. dispatcher가 환경 변수를 주입하여 워커를 세우면(立てる) → 워커는 환경 변수를 보고 Kanban 모드로 진입하는 흐름이다.

다음 회차에서는 시선을 외부로 돌린다. 이 모든 기능을 "어떤 면에서 접할 수 있는가" —— Gateway를 중심으로 한 접속 계층(connection layer)과 인터페이스(interface) 총람.

대응 맵 장(chapter): §16 / 행 번호는 hermes update 시 어긋날 수 있음

AI 자동 생성 콘텐츠

본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0