DureClaw Protocol Specification v1.0

July 2, 2026 · View on GitHub

분산 AI 에이전트 팀이 사용하는 모든 통신 프로토콜의 공식 정의입니다.


계층 구조

┌─────────────────────────────────────────────────────────────┐
│  L4  Team Protocol     TeamCreate / SendMessage / TaskCreate │
├─────────────────────────────────────────────────────────────┤
│  L3  Application       Channel Events + REST API            │
├─────────────────────────────────────────────────────────────┤
│  L2  Transport         Phoenix WebSocket (5-tuple)          │
├─────────────────────────────────────────────────────────────┤
│  L1  Network           Tailscale (WireGuard) / LAN / TCP    │
└─────────────────────────────────────────────────────────────┘

L1 — 네트워크 프로토콜

Tailscale (권장)

  • WireGuard 기반 E2E 암호화 mesh VPN
  • 에이전트 연결 주소: ws://<tailscale-ip>:4000
  • 자동 NAT 통과, 포트포워딩 불필요
  • mDNS 대안: ws://oah.local:4000 (같은 LAN)

포트

포트용도
4000Phoenix HTTP + WebSocket (단일 포트)

L2 — 전송 프로토콜: Phoenix 5-tuple

WebSocket 연결 주소:

ws://<host>:4000/socket/websocket?vsn=2.0.0

메시지 형식 (JSON 배열)

[join_ref, ref, topic, event, payload]
필드타입설명
join_refstring | null채널 join 시 발급된 참조 ID
refstring | null메시지 고유 참조 ID (응답 매칭용)
topicstring채널 토픽: work:LN-YYYYMMDD-XXX
eventstring이벤트 이름
payloadobject이벤트 데이터

시스템 이벤트

이벤트방향설명
phx_joinC→S채널 입장
phx_replyS→Cjoin/push 응답
phx_leaveC→S채널 퇴장
phx_errorS→C채널 에러
phx_closeS→C채널 종료
heartbeatC→S30초 간격 ping (topic: "phoenix")

연결 순서

1. WebSocket upgrade (HTTP → WS)
2. [null, "1", "work:LN-...", "phx_join", {agent_name, role, machine, capabilities}]
3. S→C: [joinRef, "1", topic, "phx_reply", {"status":"ok", "response":{presences, work_key, project}}]
4. S→C: [null, null, topic, "agent.hello", {agent, role, machine, work_key}]  ← broadcast
5. S→C: [null, null, topic, "mailbox.message", msg]  ← 쌓인 mailbox 전달

L3 — 애플리케이션 프로토콜

3-A: 에이전트 아이덴티티

Agent Name (고유 식별자)

형식: {role}@{machine}
예시: builder@mac-mini-m4
      orchestrator@Hongui-MacBookPro
      tester@raspi-4

Work Key (작업 세션 식별자)

형식: LN-YYYYMMDD-NNN
예시: LN-20260406-001

- LN: DureClaw 고정 접두사
- YYYYMMDD: UTC 날짜
- NNN: 당일 시퀀스 (001~999, 자동 증가)

Work Key 생명주기

created → running → done
                 ↘ failed

Work Key 스코핑 시맨틱 (중요 · #18)

Work Key는 격리 경계가 아니라 그룹핑 라벨이다. 태스크가 노드에 도달하는 경로는 둘이고 스코핑이 다르다:

경로스코핑설명
WS broadcast (task.assign on work:{WK})WK 필터해당 WK 채널에 join한 에이전트만 수신
Mailbox 폴링 (GET /api/mailbox/{agent})agent 단위 (WK 무관)오프라인 대비 큐 — 에이전트가 다른 WK에 바인딩돼 있어도 자기 mailbox의 태스크는 소비

즉 presence가 WK-A에 바인딩된 에이전트도, POST /api/task가 오프라인으로 판단해 mailbox에 넣은 WK-B 태스크를 pickup할 수 있다. 격리가 필요하면 POST /api/task {"strict_work_key": true} 로 dispatch하면 mailbox 폴백을 건너뛰어 broadcast-only == WK 엄격 스코프가 된다.

태스크 상태 라이프사이클 (#19)

POST /api/task의 201은 pickup을 보장하지 않는다. GET /api/task/{id}가 상태 + 타임스탬프를 반환한다:

queued (queued_at) → running (picked_up_at) → done | failed (finished_at)

running은 에이전트의 pickup ack(첫 task.progress)로 전이된다. 계속 queued면 아직 아무도 안 잡은 것.

로컬 무인증 (#16)

서버를 OAH_TRUST_LOOPBACK=1로 기동하면 루프백(127.0.0.1/::1) 요청은 토큰 없이 REST API 사용 가능 — 같은 머신의 오케스트레이터(Claude Code)가 OAH_SECRET 없이 presence/task API를 쓸 수 있다. 원격/포워딩된 IP는 절대 신뢰하지 않는다.

Agent 역할 (role)

role설명
orchestrator팀 조율, 태스크 분배
builder코드 생성, 빌드, 파일 수정
tester테스트 실행, 검증
analyst코드 분석, 리포트
deployer배포, 서비스 관리
executor범용 실행자

Capabilities 형식

["macos", "apple-gpu", "xcode", "ram:64g", "docker"]
capability의미
macos / linux / windowsOS
apple-gpu / nvidia-gpuGPU
arm / x86_64아키텍처
ram:XgRAM 크기 (예: ram:16g)
xcode / docker설치된 도구
rpi-speakerphone / printer특수 장치

3-B: 채널 이벤트 프로토콜

phx_join payload (C→S)

{
  "agent_name": "builder@mac-mini",
  "role": "builder",
  "machine": "mac-mini-m4",
  "capabilities": ["macos", "apple-gpu"]
}

phx_join response (S→C)

{
  "presences": { "<agent_name>": { "metas": [{ ... }] } },
  "work_key": "LN-20260406-001",
  "project": { "status": "running", "goal": "..." }
}

task.assign (S→C, 브로드캐스트)

태스크 할당. 클라이언트가 to 필드로 자신에게 해당하는 것만 처리.

{
  "task_id": "build-001",
  "to": "builder@mac-mini",
  "from": "orchestrator@MacBook",
  "instructions": "[SHELL] make build",
  "work_key": "LN-20260406-001",
  "context": {},
  "depends_on": [],
  "ts": "2026-04-06T12:00:00Z"
}

task.progress (C→S, 브로드캐스트)

진행 상황 스트리밍.

{
  "task_id": "build-001",
  "from": "builder@mac-mini",
  "percent": 42,
  "message": "컴파일 중... 3/7",
  "ts": "2026-04-06T12:01:00Z"
}

task.result (C→S, 브로드캐스트)

태스크 완료.

{
  "task_id": "build-001",
  "from": "builder@mac-mini",
  "event": "task.result",
  "status": "done",
  "output": "BUILD SUCCEEDED\n...",
  "exit_code": 0,
  "ts": "2026-04-06T12:05:00Z"
}

task.blocked (C→S, 브로드캐스트)

태스크 진행 불가.

{
  "task_id": "build-001",
  "from": "builder@mac-mini",
  "event": "task.blocked",
  "reason": "missing_dependency",
  "message": "gcc를 찾을 수 없습니다",
  "ts": "2026-04-06T12:02:00Z"
}

task.approval_requested (C→S, 브로드캐스트)

Human-in-the-loop 승인 요청.

{
  "task_id": "deploy-001",
  "from": "deployer@server",
  "prompt": "프로덕션 배포를 진행할까요?",
  "options": ["yes", "no", "later"],
  "ts": "2026-04-06T12:10:00Z"
}

agent.hello (S→C, 브로드캐스트)

에이전트 입장 알림.

{
  "agent": "builder@mac-mini",
  "role": "builder",
  "machine": "mac-mini-m4",
  "work_key": "LN-20260406-001"
}

agent.bye (S→C, 브로드캐스트)

에이전트 퇴장 알림.

{
  "agent": "builder@mac-mini",
  "role": "builder",
  "work_key": "LN-20260406-001"
}

mailbox.post (C→S)

오프라인 에이전트에게 메시지 전송.

{
  "to": "tester@raspi",
  "from": "orchestrator@MacBook",
  "type": "info | instruction | join_request",
  "content": "메시지 내용",
  "work_key": "LN-20260406-001"
}

응답 (온라인): {"delivered": true} 응답 (오프라인): {"delivered": false, "queued": true}

mailbox.message (S→C, push)

재연결 시 mailbox 메시지 전달.

{
  "from": "orchestrator@MacBook",
  "type": "join_request",
  "content": "...",
  "work_key": "LN-20260406-001",
  "ts": "2026-04-06T11:00:00Z"
}

state.update (C→S)

Work Key 상태 업데이트.

{
  "status": "running",
  "goal": "iOS 앱 빌드",
  "shared_context": { "branch": "main" }
}

state.get (C→S)

현재 상태 조회. payload: {} 응답: {"state": { ... }}


3-C: REST API

메서드경로설명
GET/api/health서버 상태
GET/api/presence전체 온라인 에이전트 목록
DELETE/api/presence/:agentGhost 에이전트 강제 제거
GET/api/capabilities빌더 capabilities 목록
GET/api/work-keys전체 Work Key 목록
GET/api/work-keys/latest최신 Work Key
POST/api/work-keysWork Key 생성
GET/api/state/:wkWork Key 상태 조회
PATCH/api/state/:wkWork Key 상태 업데이트
GET/api/team/:wk팀 대시보드 (state+agents+tasks)
POST/api/task태스크 생성 및 브로드캐스트
GET/api/task/:task_id태스크 결과 조회
POST/api/task/:task_id/result태스크 결과 저장 (에이전트→서버)
POST/api/task/:task_id/cancel태스크 취소
GET/api/mailbox/:agentmailbox 메시지 수신 (pop)
POST/api/mailbox/:agentmailbox 메시지 전송 (push)

POST /api/task

{
  "work_key": "LN-20260406-001",
  "to": "builder@mac-mini",
  "task_id": "build-001",
  "instructions": "[SHELL] make build",
  "context": {},
  "depends_on": ["analyze-001"]
}

응답:

{ "pending": false, "work_key": "LN-20260406-001", "task_id": "build-001" }
  • pending: false = 에이전트 온라인, 즉시 전달
  • pending: true = 의존성 있음, 조건 충족 시 자동 전달

L4 — 팀 프로토콜

4-A: Task Instruction 형식

[PREFIX] <내용>
접두사실행 방법예시
[SHELL]bash 직접 실행[SHELL] npm run build
[CLAUDE]claude CLI[CLAUDE] 이 파일을 리팩토링해줘
[PI]pi coding agent[PI] fix the failing tests
[GEMINI]gemini CLI[GEMINI] 코드 리뷰 해줘
[AIDER]aider CLI[AIDER] refactor auth module
[ORCHESTRATE]서브 태스크 분해[ORCHESTRATE] 앱 전체 빌드 및 테스트
[PIPELINE]Phase 1/2 파이프라인[PIPELINE] 교육 콘텐츠 분석
(없음)에이전트 기본 AI자연어 지시

4-B: TeamCreate

Work Key 생성 + 팀 초기화.

요청:

{
  "goal": "달성할 목표",
  "pattern": "pipeline | fan-out | supervisor | hierarchical",
  "agents": [
    { "name": "builder@mac-mini", "type": "remote", "role": "builder" },
    { "name": "analyst", "type": "local", "role": "analyst" }
  ]
}

실행 순서:

  1. POST /api/work-keys → WK 발급
  2. PATCH /api/state/{wk} → 팀 매니페스트 저장
  3. 오프라인 에이전트 → POST /api/mailbox/{agent} (join_request)
  4. 반환: { work_key, online_agents, pending_agents }

4-C: SendMessage

에이전트 간 정보 전달 (결과 대기 없음).

{
  "from": "orchestrator@MacBook",
  "to": "builder@mac-mini",
  "type": "info | instruction | warning | join_request",
  "work_key": "LN-20260406-001",
  "content": "메시지 내용"
}

라우팅:

  • 온라인 → WebSocket channel mailbox.post (즉시)
  • 오프라인 → POST /api/mailbox/{agent} (재연결 시 전달)

4-D: TaskCreate

태스크 할당 + 결과 대기.

{
  "work_key": "LN-20260406-001",
  "to": "builder@mac-mini",
  "task_id": "build-001",
  "instructions": "[SHELL] make build",
  "context": { "branch": "main", "version": "2.0" },
  "depends_on": ["analyze-001"]
}

라우팅:

  • 로컬 에이전트 → Agent 도구로 subagent spawn
  • 원격 온라인 → POST /api/task → channel broadcast
  • 원격 오프라인 → POST /api/mailbox/{agent} 큐잉

의존성 체인 자동 실행:

task A (depends_on: [])  → 즉시 dispatch
task B (depends_on: [A]) → A 완료 시 자동 unblock + dispatch
task C (depends_on: [A, B]) → A, B 모두 완료 시 dispatch

에러 코드

코드의미처리
agent_offline에이전트 미연결mailbox 큐잉
task_timeout태스크 타임아웃task.blocked 발생
task_failed태스크 실패재시도 또는 에스컬레이션
missing_dependency의존 태스크 미완료depends_on 대기
unknown_event미정의 이벤트{error: "unknown_event"} 반환
not_foundWK/태스크 없음404 응답

버전 정보

항목
Phoenix vsn2.0.0
Protocol spec1.0
Server version0.3.0