
멀티 에이전트 협조 — 부모-자식 위임과 보드를 통한 태스크 분해의 2가지 계통【프롬프트로 읽는 AI 에이전트 #6】
요약
멀티 에이전트 협조를 위한 두 가지 설계 방식인 '부모-자식 위임'과 '보드를 통한 태스크 분해'를 비교 분석합니다. 상위 에이전트가 하위 에이전트를 툴로 호출하는 동기적 방식과 공유 보드를 통해 비동기적으로 업무를 처리하는 방식의 차이를 다룹니다.
핵심 포인트
- 부모-자식 위임: 상위 에이전트가 하위 에이전트를 툴로 호출하는 동기적·스택형 구조
- 보드 기반 분해: 공유 칸반 보드를 통해 태스크를 비동기적으로 처리하는 큐형 구조
- 에이전트 설계 핵심: 역할 분담을 통해 복잡한 태스크를 효율적으로 해결하는 방법론 제시
연재 「프롬프트로 읽는 AI 에이전트」 제6회 (제5장).
실재하는 3가지 AI 에이전트 OSS를 실제 코드와 실제 프롬프트를 원전에서 인용하며 분석하여,
최종적으로 「스스로 AI 에이전트를 만들 수 있는」 상태를 목표로 하는 연재입니다.
이 장의 전제 (제1~4장 복습)
지금까지 단일 에이전트를 구동하는 부품은 모두 갖추었습니다. 제1장에서 Reason–Act–Observe를 반복하는 루프 (run_agent)의 골격을, 제2장에서 루프 선두에 배치하는 시스템 프롬프트 (System Prompt) (인격·행동 규범)를, 제3장에서 **툴 (Tool)**의 정의와 제시 방법을, 그리고 제4장에서 **영속 메모리 (Persistent Memory)**를組み込み(구현)했습니다. 본 장의 전제는 이 4가지입니다.
제4장 말미에서 다음과 같이 예고했습니다.
단일 에이전트 다음은 군집입니다. ―― 제4장 「기억」
본 장의 테마는 **멀티 에이전트 협조 (Multi-agent Collaboration)**입니다. 한 개체로는 감당하기 어려운 일 ―― 전문 분업, 병렬 조사, 거대한 태스크의 분해 ―― 를 여러 에이전트가 나누어 맡는 설계입니다. 다만 「여러 개체를 협조시킨다」라고 한마디로 말해도, 실행형 에이전트의 세계에는 성질이 다른 2가지 계통이 있습니다. 본 장에서는 이 2가지 계통을 구분하여 원전으로 읽어봅니다.
계통 A: 부모-자식 서브 에이전트 호출 (agent-zero의 call_subordinate)
상위 에이전트가 하위 에이전트를 툴로서 호출하고, 하위의 monologue()를 동기적으로 기다려 결과를 받습니다. 스택형·재귀적 위임.
계통 B: 보드를 통한 태스크 분해 (Hermes의 kanban)
공유 SQLite의 **칸반 보드 (Kanban Board)**에 태스크를 나열하고, 각 카드를 별도의 에이전트 (profile)가 비동기적으로 가져가 처리합니다. 큐형·조정적 분업.
본 장의 목표는 독자가 이 2가지 계통을 구분하여 이해하고, 자작 에이전트에 부모-자식 호출의 최소 골격과 보드 분해의 최소 골격을 구현할 수 있게 되는 것입니다.
우선 추상화 ―― 「직접 하지 않는다」는 공통점과, 태도의 차이
두 계통의 공통점은 "한 개체가 전부 하지 않고, 역할을 나누어 전달한다"는 점입니다. 차이점은 전달 방식에 있습니다.
계통 A (부모-자식 위임)는 상위 에이전트의 실행 스택이 하위의 완료까지 기다리는 태도입니다. 부모가 call_subordinate라는 도구를 호출하면, 그 실행 과정 중에서 자식 에이전트가 제1장의 run_agent에 상당하는 루프를 통째로 돌리고, 최종 답변을 툴 결과로서 부모에게 반환합니다. 부모 입장에서 보면 「무거운 계산을 수행하는 하나의 툴을 호출한 것」과 같습니다. 동기적·스택형.
계통 B (보드 분해)는 공유 보드 (SQLite)를 매개로 태스크의 상태 (todo / ready / running / done…)를 직렬화하고, 별도의 에이전트가 가져가 처리하는 태도입니다. 태스크를 나열하는 것은 오케스트레이터 (Orchestrator) (routing에 집중)이며, 구현하는 것은 스페셜리스트 (Specialist) (profile)입니다. 양자는 동기화되지 않으며, 보드를 공유하는 것만으로 간접적으로 협조합니다. 비동기적·큐형.
Agent0 (학습형)는 본 장에서 다루지 않습니다. 본 연재가 다루는 3자 중 실행형 2개 (agent-zero / Hermes)에 관한 이야기입니다. Agent0의 세계관은 제2부 (제7장 이후)에서 다시 다룹니다.
순서대로 원전에서 확인하겠습니다.
call_subordinate로 monologue()를 재귀시키기
실물로 확인하기 ① ― agent-zero: agent-zero (agent0ai/agent-zero @ f9d8167)의 협조는, 제2장에서 본 "동작을 prompts/*.md에 외재화한다"는 사상을 계승하여, 하나의 도구로서 구현됩니다. 그 도구의 이름이 call_subordinate입니다.
.md로 LLM에게 보여주는 설명
도구로서의 위임 ―― 우선, 제3장의 방식대로 **툴 설명서 (.md)**부터 시작합니다.
### call_subordinate
delegate research or complex subtasks to a specialized agent.
args: `message`, optional `profile`, `reset`
...
―― prompts/agent.system.tool.call_sub.md @ f9d8167
인수는 3개입니다. message
(子に渡す指示=役割・ゴール・具体タスク)、profile
(子に着せる人格=後述)、reset
(新しい子を作るか、既存の子に追加メッセージを送るか)。reset: true
의 경우에만 새로운 하위 에이전트가 생성됩니다. 예시 JSON이 제2장에서 본 JSON 응답 계약 그대로라는 점에 주의하십시오. 부모가 이 JSON을 반환하면, agent-zero의 루프(제1장에서 본 monologue의 이중 while)가 tool_name == "call_subordinate"를 발견하고 하위 에이전트를 구동하게 됩니다.
마지막의 {{if agent_profiles}} ~ {{endif}}는 동적 페르소나 카탈로그입니다. {{agent_profiles}}는 실행 시 플러그인이 대체합니다.
class CallSubordinate(VariablesPlugin):
def get_variables(
self, file: str, backup_dirs: list[str] | None = None, **kwargs
...
―― prompts/agent.system.tool.call_sub.py
@ f9d8167
, L11-33
제2장의 process_includes와 같은 계통의 삽입 메커니즘(VariablesPlugin)으로, 현재 프로젝트에서 사용 가능한 페르소나(profile) 목록을 call_subordinate 설명문에 주입합니다. 부모 LLM은 이것을 읽고 "어떤 페르소나를 하위로 호출할지" 선택할 수 있습니다. 즉, 동적 라우팅입니다.
monologue()의 재귀
위임의 본체 — 상하를 잇는 두 개의 상수와 도구 구현은 단 하나의 파일에 불과합니다. 제3장에서 본 Tool 클래스를 상속받습니다.
class Delegation(Tool):
async def execute(self, message="", reset="", **kwargs):
# create subordinate agent using the data object on this agent and set superior agent to his data object
...
―― tools/call_subordinate.py
@ f9d8167
, L7-47
내용을 분석해 보겠습니다. 세 가지 핵심 사항이 있습니다.
(1) 부모와 자식의 연결은 data 딕셔너리의 두 개의 상수로 만듭니다.
Agent 클래스는 각 인스턴스가 자유롭게 사용할 수 있는 data라는 딕셔너리를 가지고 있으며, 여기에 DATA_NAME_SUPERIOR (상위) / DATA_NAME_SUBORDINATE (하위)라는 두 개의 예약 키로 상하 관계를 기록합니다( agent.py @ f9d8167, L346-347에서 상수를 정의).```
class Agent:
DATA_NAME_SUPERIOR = "_superior"
DATA_NAME_SUBORDINATE = "_subordinate"
―― `agent.py`
@ `f9d8167`
, L344-347
하위를 생성하는 코드(L23-27)는 이 두 상수를 사용하여 양방향 링크를 만듭니다 — 자식의 `data["_superior"]`에는 부모를, 부모의 `data["_subordinate"]`에는 자식을 넣습니다. 이렇게 하면 "부모가 자식에게 추가 메시지를 보내기", "자식이 부모에게 완료를 반환하기"의 왕복이 `data` 딕셔너리 하나로 성립합니다. 재 `call_subordinate` 시 `reset: false`라면 기존의 `_subordinate`를 그대로 사용하고, `true`라면 새로운 `Agent`를 만들어서 대체합니다.
**(2) 하위는 Agent.number + 1로 번호가 매겨집니다.** 생성 라인(L24)의 `Agent(self.agent.number + 1, ...)`가 그것입니다. 제1장에서 본 에이전트 본체는 `self.number`를 가지고 있으며, `agent_name = f"A{self.number}"`로 이름을 갖습니다(`agent.py` @ `f9d8167`)
, L362-363). 최상위 부모가 A0, 그 자식이 A1, 손자가 A2……와 같이 **깊이에 따라 번호가 늘어납니다**. 이는 비유가 아니라 실제 계층 구조입니다.
**(3) 위임의 핵심은 `await subordinate.monologue()` 한 줄**입니다. L34의 이 한 줄이 agent-zero 멀티 에이전트의 심장입니다.
`monologue`는 제1장에서 보았던 ReAct 루프(외부의 「메시지 루프(message loop)」 + 내부의 「Reason–Act–Observe 반복」의 이중 while)입니다. **부모는**—— 부모는 자식의 최종 답변이 돌아올 때까지
`call_subordinate`
도구(tool) 내부에서, 자식의 `monologue` 루프가 통째로 실행되는 `await`로 대기하며, 반환값 `result`를 `Response(message=result, break_loop=False)`로 **자신의 도구 결과**로서 반환합니다.
`break_loop=False`라는 지정에도 주의하십시오 (제1장에서 보았던 종료 판정 용어입니다). 자식이 완료되어도 부모의 루프는 끝나지 않으며, 도구 결과가 부모의 이력(history)에 쌓여 다음 반복으로 진행됩니다. **최종 답변을 내는 것은 부모의 `response` 도구**이며, 자식은 「무거운 계산을 수행하는 서브루틴 (subroutine)」에 불과하다는 설계가 나타나 있습니다.
###
`_process_chain`으로 재귀적으로 연결되는 상하 연쇄
부모와 자식의 왕복은 `agent.py` 내의 `_process_chain`이라는 함수를 통해 **재귀적으로 처리**됩니다.
async def _process_chain(self, agent: "Agent", msg: "UserMessage|str", user=True):
try:
msg_template = (
...
—— `agent.py` @ `f9d8167`, L283-300 (발췌)
해석하면 다음과 같습니다.
- 받은 에이전트가 `monologue()`를 돌려 최종 답변 `response`를 얻는다.
- 해당 에이전트에 `_superior` (부모)가 등록되어 있다면, 자기 자신을 재귀 호출하여 `response`를 **부모의 것**으로서 부모의 이력에 쌓고, 부모의 `call_subordinate` 도구 결과인 `monologue()`를 돌린다.
- 부모의 부모(조부)가 있다면 더욱 재귀한다.
즉, 하위 단계가 완료되면 **부모의 도구 호출 반환값으로 돌아올 뿐만 아니라, `_process_chain`의 재귀가 체인 전체를 되감으며 올라갑니다**. 깊이 N계층까지 내려간 위임이 최상위(A0)까지 돌아와서야 비로소 사용자에게 전달되는 최종 답변이 되는 구조입니다.
### 무한 위임의 제어 장치 ―― 「자신과 동일한 profile에 통째로 떠넘기지 마라」
이토록 유연하면 당연히 "**부모가 자신을 대신해 자신과 똑같은 일을 하는 자식을 만들어 통째로 떠넘기는**" 폭주가 일어날 수 있습니다. agent-zero는 이를 **프롬프트(prompt)로** 억제합니다. 제2장에서 읽었던 문제 해결 절차(`agent.system.main.solving.md`) 안에 다음과 같이 적혀 있습니다.
3 solve or delegate
tools solve subtasks
you can use subordinates for specific subtasks
...
—— `prompts/agent.system.main.solving.md` @ `f9d8167`, L14-21
`never delegate full to subordinate of same profile as you` (자신과 동일한 profile의 하위에게 통째로 위임하지 마라) / `always describe role for new subordinate` (새로운 하위에게는 반드시 역할을 설명하라) / `use prompt profiles to specialize subordinates` (profile을 사용하여 하위를 전문화하라). **코드로 계층을 제한하는 것이 아니라, 프롬프트로 판단 기준을 LLM에게 전달합니다** ―― 제2장에서 보았던 "동작은 코드가 아니라 프롬프트로 결정된다"는 원칙이 여기서도 관철되고 있습니다.
###
`fw.msg_from_subordinate.md` 하위에서 부모로의 귀환 경로 ―― 자식에서 부모로의 응답은 `call_subordinate`의 반환값과는 별개의 경로로 포맷팅된 한 줄의 템플릿에도 나타납니다.
부하 직원 {{name}}의 메시지: {{message}}
―― `prompts/fw.msg_from_subordinate.md`
@ `f9d8167`
`{{name}}`
과 `{{message}}`
라는 두 개의 변수만 사용하는 매우 소박한 템플릿으로, 부모의 문맥에 "이것은 하위 `{{name}}`으로부터의 메시지다"라고 명시하는 역할을 합니다. 소박하지만 중요하며, 부모 LLM은 이력을 통해 "사용자 입력", "자신의 발언", "도구 결과", "**하위로부터의 메시지**"를 글자 그대로 구분할 수 있게 됩니다.
정리하자면, agent-zero의 협조는 다음과 같은 구조를 가집니다.
| 요소 | 메커니즘 |
|---|---|
| 위임의 트리거 | `call_subordinate` 도구 (JSON 응답에 `tool_name: "call_subordinate"`를 작성) |
| 상하 관계 연결 | `Agent.data` 딕셔너리의 `_superior` / `_subordinate` 두 상수를 통해 양방향으로 연결 |
| 계층 표현 | `Agent.number + 1`로 깊이를 계산 (A0 → A1 → A2 …) |
| 위임의 본체 | `await subordinate.monologue()` ―― 제1장의 루프를 재귀 호출 |
| 반환 | 자식의 최종 답변이 `Response.message`로서 부모의 도구 결과가 됨 |
| 폭주 방지 | `solving.md`의 "동일 profile에 통째로 떠넘기기 금지"라는 프롬프트 지시 |
| 인격 교체 | `profile` 인자 + 동적으로 주입되는 `{{agent_profiles}}` 카탈로그 |
**agent-zero의 협조는 제1~3장의 도구들에 새로운 원리를 단 하나도 추가하지 않았다**는 점을 깨닫게 됩니다. 루프(제1장)에 새로운 도구 하나(제3장)를 끼워 넣고, 그 도구 안에서 동일한 루프를 재귀시키며, 인격을 교체하기 위해 시스템 프롬프트(제2장)의 `profile`을 교체한다 ―― 단지 그뿐입니다. 단순한 재귀적 위임이 가진 강력함은 바로 여기에 있습니다.
## 실물로 확인하기 ② ― Hermes: 칸반(kanban) 보드로 태스크를 분해하고, 별도의 에이전트가 이를 처리함
Hermes (`NousResearch/hermes-agent` @ `6928692`)의 협조 방식은 완전히 다릅니다. 부모-자식 간의 동기적 재귀가 아니라, **공유된 SQLite 칸반 보드 (kanban board)**를 매개로 한 비동기적 중재입니다. 구현의 핵심은 세 가지입니다 ―― ① 보드 (`hermes_cli/kanban_db.py`), ② 분해기 (`hermes_cli/kanban_decompose.py`), ③ 워커(worker)를 위한 행동 규범 (`agent/prompt_builder.py`의 `KANBAN_GUIDANCE`).
### 공유 보드 ―― SQLite 위에 나열된 태스크의 라이프사이클
보드는 파일 기반의 SQLite입니다.
"""SQLite 기반의 멀티 프로필, 멀티 프로젝트 협업을 위한 칸반 보드.
새로 설치하면 보드는 <root>/kanban.db에 존재하며,
<root>는 공유된 Hermes 루트 (모든 활성 ...
―― `hermes_cli/kanban_db.py` @ `6928692`, L1-9 (발췌)
`profiles intentionally collapse onto a shared board: it IS the cross-profile coordination primitive`
(profile은 의도적으로 공유 보드에 집약된다 ―― 그것이야말로 profile을 넘나드는 협조의 프리미티브(primitive)다). 본 장의 주제 그 자체입니다. 협조 수단은 "직접적인 호출"이 아니라 "**하나의 공유 보드를 보는 것**"입니다.
태스크에는 명확한 **상태(status) 어휘**가 있으며, 이것이 라이프사이클을 형성합니다.
VALID_STATUSES = {"triage", "todo", "scheduled", "ready", "running", "blocked", "review", "done", "archived"}
―― `hermes_cli/kanban_db.py`
@ `6928692`
, L99
사용자가 대략적으로 기표(起票)한 것은 `triage`로 들어가고, 분해기(후술)가 형태를 갖추면 `todo` 또는 `ready`로 이동합니다. 실행 중인 에이전트가 있으면 `running`, 인간의 판단을 기다리는 중이면 `blocked`, 완료되면 `done`이 됩니다. 제1장의 루프가 '하나의 에이전트의 내부 상태'를 다루었다면, kanban은 '**여러 에이전트가 공유하는 외부 상태**'를 DB로 유지합니다.
### 분해기 ―― 보조 LLM이 기표를 의존 그래프로 나눈다
보드에 `triage`로 들어온 기표는 그대로 두면 '막연한 요구사항' 상태로 남습니다. 이를 **병렬로 움직일 수 있는 구체적인 태스크의 집합**으로 나누는 것이 분해기(`kankan_decompose.py`)입니다. 핵심은 다음의 시스템 프롬프트입니다 (요점 인용, 행은 연속됨).
You are the Kanban decomposer for the Hermes Agent board.
A user dropped a rough idea into the Triage column. Your job is to break it
into a small graph of concrete child tasks and route each one to the best-
...
―― `hermes_cli/kanban_decompose.py`
@ `6928692`
, L52-91 (`_SYSTEM_PROMPT` 발췌)
포인트는 4가지입니다.
**(1) 출력은 정해진 형태의 JSON 태스크 그래프**. `tasks`는 부모-자식 관계가 포함된 플랫(flat)한 리스트이며, 의존 관계는 **`parents`라는 0부터 시작하는 인덱스**로 표현됩니다. "부모가 없는 태스크는 병렬 실행, 부모가 있는 태스크는 부모가 모두 `done`이 될 때까지 대기" ―― 이것만으로 병렬·직렬 의존 그래프를 작성할 수 있습니다.
**(2) 라우팅(Routing)은 profile의 description으로 결정된다**.
`Pick assignees from the roster by matching the task to the profile's DESCRIPTION (not just the name)`
(profile의 description으로 대조하여, 이름이 아니라 설명으로 나누어라). 이것이 Hermes 협조의 핵심입니다. **오케스트레이터(Orchestrator)는 개별 에이전트를 지목하여 지시하지 않고, 보드에 "이 태스크는 이런 인격에 적합하다"라는 의도를 적을 뿐**이며, 실제로 이를 가져가는 것은 description 일치 여부로 적임자라고 판정된 profile이 됩니다.
**(3) 부모 없음 = 병렬, 부모 있음 = 대기**. "**Prefer parallelism**"이라고 명시된 대로, 분해기는 우선 **병렬로 움직일 수 있는 단위**를 찾습니다. 직렬 의존은 "데이터가 정말로 부모에게 의존할 때"만 발생합니다.
**(4) 자식 태스크의 본문은 단독으로 읽을 수 있도록 작성하라**. `Each child task body is what a fresh worker will read with no other context — be specific about goal, approach, and acceptance criteria`
(자식의 본문은 문맥이 없는 워커가 읽는 것이다 ―― 목표, 접근 방식, 수락 기준(acceptance criteria)을 구체적으로 작성하라). ―― 이 점이 계통 A(부모-자식 위임)와의 큰 차이점입니다. agent-zero의 자식은 부모와 동일한 프로세스 내에서 동일한 컨텍스트를 이어받을 수 있지만, Hermes의 자식은 **별도의 프로세스·별도의 profile에서 보드의 카드 본문만을 입력**으로 받습니다. 그렇기에 본문이 곧 **계약(contract)**이 되는 것입니다.
### profile ―― 별도 에이전트의 아이덴티티 그 자체
여기서 말하는 profile은 제2장의 `SOUL.md`에서 보았던 에이전트의 **인격**을 포함하는, 더 넓은 독립적 아이덴티티입니다.
"""
Profile management for multiple isolated Hermes instances.
Each profile is a fully independent HERMES_HOME directory with its own
...
―― `hermes_cli/profiles.py`
@ `6928692`
, L1-7
`자신만의 config.yaml, .env, memory, sessions, skills, gateway, cron, logs를 갖춘 완전히 독립적인 HERMES_HOME 디렉토리`
(독립된 `HERMES_HOME` 디렉토리로, 자체적인 설정, 환경 변수, **메모리 (memory)**, 세션, 스킬, 게이트웨이, cron, 로그를 가집니다). **프로파일 (profile)은 모델이나 인격뿐만 아니라, 제4장에서 살펴본 영속 메모리 (persistent memory)도 독립적으로 가집니다.** 코딩 프로파일은 코딩 지식을, 연구 프로파일은 연구 사실을 각각의 `MEMORY.md` / `USER.md`에 저장합니다. Hermes에서 별개의 에이전트는 말 그대로 별도의 집을 가지고 있는 셈입니다.
해당 프로파일에 대한 라우팅 (routing)을 성립시키는 것이 `ProfileInfo`의 `description` 필드입니다.
@dataclass
class ProfileInfo:
"""Summary information about a profile."""
...
―― `hermes_cli/profiles.py`
@ `6928692`, L401-422 (발췌)
주석이 본 장의 주제 그 자체입니다 ―― `Surfaced to the kanban decomposer so it can route work to the right profile based on role rather than name alone`
(**역할에 기반하여 라우팅할 수 있도록** 칸반 (kanban) 분해기 (decomposer)에 노출됨).
`description`은 사용자가 직접 작성할 수도 있고, `profile_describer.py`가 자동으로 생성해 주기도 합니다. 생성 프롬프트의 한 구절이 그 철학을 아주 명확하게 설명하고 있습니다.
You are a profile-describer for the Hermes Agent kanban board.
A user runs multiple "profiles" — distinct agent identities, each with their
own skills, model, and configuration. The kanban board's orchestrator routes
...
―― `hermes_cli/profile_describer.py`
@ `6928692`, L47-52
`distinct agent identities` (별개의 에이전트 정체성). Hermes에서 별개의 에이전트는 별개의 프로파일이며, 별개의 `description`을 통해 구인 광고를 내고 있다고 읽을 수 있습니다. 오케스트레이터 (orchestrator)는 "**역할에 대한 설명만을 보고**" 누구에게 요청할지를 결정하는 것입니다.
###
`KANBAN_GUIDANCE`
워커 (worker)의 실행 프로토콜 ―― 보드에서 할당된 하위 태스크 (child task)를 맡는 워커 측의 방식은 시스템 프롬프트 (system prompt)에 주입되는 `KANBAN_GUIDANCE`에 의해 완전히 정의됩니다. 이는 제4장에서 보았던 `MEMORY_GUIDANCE`와 같은 계통의 "특정 도구를 가질 때만 포함되는 가이드라인"입니다.
Kanban task execution protocol
You have been assigned ONE task from the shared board at ~/.hermes/kanban.db. Your task id is in $HERMES_KANBAN_TASK; your workspace is $HERMES_KANBAN_WORKSPACE. The kanban_* tools in your schema are your primary coordination surface — they write directly to the shared SQLite DB and work regardless of terminal backend (local/docker/modal/ssh).
Lifecycle
...
―― `agent/prompt_builder.py`
@ `6928692`, L174-222 (`KANBAN_GUIDANCE`
의 Lifecycle 부분 발췌. 원문은 하나의 문자열 리터럴(string literal)로 연결되어 있으며, 각 항목 끝의 보충 설명(reclaim의 동작 상세, `respawn`, secrets 금지 및 review 프로토콜 등)은 생략되어 있다.)
이것만으로 워커(worker)가 취해야 할 행동의 전체 골격이 결정됩니다.
-
**Orient (방향 설정)**: 자신의 태스크를 `kanban_show()`로 읽고, **부모 태스크의 완료 요약(summary)·메타데이터(metadata)·코멘트 이력·정형화된 `worker_context`**를 흡수한다. 부모와 직접 대화하지 않더라도, 부모가 `kanban_complete`로 남긴 구조화된 인수인계 자료를 읽는 것만으로 업무에 착수할 수 있다.
-
**Work inside the workspace (자신의 작업 영역만 다루기)**: `$HERMES_KANBAN_WORKSPACE` 외부에는 손대지 않는다. 다른 워커의 작업과의 간섭을 물리적으로 방지한다.
-
**Heartbeat (생존 보고)**: 긴 작업 시에는 `kanban_heartbeat`를 정기적으로 보낸다. 보내지 않으면 디스패처(dispatcher)가 태스크를 *탈취(reclaim)*한다. **한 명의 워커가 영원히 점유하는** 사고를 명시적인 하트비트(heartbeat)로 방지한다.
-
**Block (인간의 판단 요청)**: 스스로 판단할 수 없는 경우(자격 증명(credential) 부족, UX 선택, 피어(peer)의 출력 대기 등)에는 **추측하지 말고** `kanban_block`
AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기