delegate-job

자율 에이전트 비동기 위임 및 MQTT 이벤트 관찰 아키텍처 명세서

MQTT 브로커 셋업 가이드 (PoC → Production)

공개 테스트 브로커에서 내부 TLS 암호화 및 ACL 인가 제어를 적용한 사설 프로덕션 브로커로 안전하게 전환하기 위한 단계별 구축 가이드입니다.

가이드 열기 →

시스템 아키텍처 명세

자율 에이전트 위임 모델은 동시성 간섭이 배제된 단방향 이벤트 스트림 구조를 띱니다. 아래 탭을 전환하며 상호작용 가능한 다이어그램들을 확인하실 수 있습니다.

User/Delegator delegate-job submit Wrapper CLI Job Registry .hermes/jobs/<id>.json job_subscriber.py Background Process Agent (tmux/print) claude-code / codex publish_event.py Worker Utility MQTT Broker HiveMQ / Mosquitto jobs/<id>/events Audit Log events.ndjson
CLI Wrapper Registry Subscriber AI Agent (tmux) MQTT Broker Audit Log 1. register_job (pending) 2. spawn subscriber (bg) 3. connect & subscribe QoS 1 4. tmux launch (instructions with JID) 5. publish event="started" 6. deliver event="started" 7. write logs (meta snapshot + events & status = "running") 8. publish event="completed" 9. deliver event="completed" 10. write logs (status = "completed") 11. exit process (exit 0)
delegate-job Bash orchestrator CLI registry.py Registry CRUD CLI/Lib job_subscriber.py MQTT event monitor publish_event.py Status event emitter mqtt_common.py Shared library: Broker configuration, Advisory fcntl lock, logging, files IO

1. 이 스킬이 하는 일

delegate-job 스킬은 복잡한 자율 에이전트 오케스트레이션(작업 위임) 흐름을 단 한 줄의 명령어로 단순화합니다.

자동화 범위

1. Job ID 신규 발급 및 독자적인 샌드박스 레지스트리 레코드 생성
2. 이벤트 전송 유실 방지를 위해 에이전트 시작 전에 백그라운드 수신기를 선(先) 실행
3. 격리된 tmux 인터랙티브 터미널 세션을 열어 작업 위임
4. 에이전트가 발행한 실시간 상태 이벤트를 감지하여 NDJSON 포맷 감사 로그(Audit Log) 축적
5. 최종 성공(completed) 또는 실패(error) 감지 시 자동으로 자원 반환 및 모니터링 해제

2. 설치 & 사전조건

이 스킬은 POSIX 표준 개발 규격을 준수하며, 파이썬 기반의 백그라운드 구독 유틸리티와 통신 드라이버가 필요합니다.

사전 시스템 사양

인프라 항목 기본 요건 활용 세부 영역
OS macOS / Linux (Windows 환경인 경우 WSL 가상 환경 권장) 런타임 커널 지원
Runtime Python 3.9+ Registry / Publisher / Subscriber 연동
Multiplexer tmux (미설치 시 wrapper 기동 시 경고) 인터랙티브 모드 세션 격리 기동
Library paho-mqtt ≥ 2.0 (VERSION2 콜백 API 지원 사양) MQTT 브로커 통신을 위한 로컬 파이썬 모듈

스킬 저장소 파일 디렉터리 구성

Directory layout
~/.hermes/skills/autonomous-ai-agents/delegate-job/
├── SKILL.md              # Claude 에이전트가 해석하는 프롬프트 가이드 지침
├── USER_MANUAL.html      # 사용자 분석용 HTML 지침서 (본 문서)
├── README.md             # 간략한 프로젝트 정보
├── job-protocol.md       # MQTT JSON 페이로드 규격 및 스키마 명세
├── registry.md           # 레지스트리 레코드의 속성 값 정의 및 락 매커니즘
├── mqtt-broker-setup.html # PoC → TLS 운영 브로커 컷오버 가이드 (HTML)
├── delegate-job          # 오케스트레이션 역할을 하는 Bash wrapper script
└── scripts/
    ├── mqtt_common.py    # 브로커 연결 빌드, 파일 락, 감사 로그 공통 모듈
    ├── registry.py       # Job 등록/수정을 관장하는 CLI 헬퍼 라이브러리
    ├── publish_event.py  # 구동 중인 에이전트가 이벤트를 쏠 때 쓰는 송신기
    └── job_subscriber.py # 위임 작업 종료 시점까지 백그라운드에서 감시하는 수신기

3. Quick Start (작업 위임)

단일 통합 명령어를 활용하여 즉시 위임 환경을 기동하거나, 빌드 파이프라인 연동 시 단계별 조작이 용이하도록 파이썬 직접 구동을 지원합니다.

delegate-job submit 명령을 통하여 백그라운드 수신기를 구동하고 에이전트를 안전하게 격리 기동합니다.

bash
delegate-job submit \
  --agent claude-code \
  --prompt "정렬 문제 10개를 만들어 sort_problems.md로 저장" \
  --workdir /path/to/project \
  --agent-session tmux:demo \
  --timeout 600 --idle-timeout 120

위임 시작 시 콘솔 실시간 로그 (stdout 예시)

registered job: 2971fbf8
subscriber pid: 34311 (log: .hermes/jobs/2971fbf8.subscriber.out)
agent launched in tmux session: demo (attach with: tmux attach -t demo)
subscriber output:
2026-06-19T13:16:00Z  job=2971fbf8  seq=1  started               Job 2971fbf8 started
2026-06-19T13:18:20Z  job=2971fbf8  seq=2  completed             saved sort_problems.md
subscriber exit code: 0
/path/to/project/.hermes/delegate_job_logs/2971fbf8   # Audit log 디렉터리 경로 반환

의존 관계 설정 및 디버깅을 위해 단계를 세분화하여 파이썬 런타임 스크립트를 기동할 수 있습니다.

bash
PY=.venv/bin/python
SKILL=~/.hermes/skills/autonomous-ai-agents/delegate-job/scripts

# 1) 작업 정보 레코드 생성
JID=$($PY "$SKILL/registry.py" register \
        --prompt "정렬 파일 구성" --agent claude-code --agent-session tmux:demo \
        --timeout 600 --idle-timeout 120)

# 2) 백그라운드 수신기 우선 실행 (순서 의존성 주의)
$PY "$SKILL/job_subscriber.py" --job "$JID" --timeout 600 --idle-timeout 120 &

# 3) 시작(started) 상태 신호 수동 전송
$PY "$SKILL/publish_event.py" --job "$JID" --event started

# 4) 에이전트 구동 과정... (에이전트가 직접 completed/error 신호를 쏘도록 지시)

# 5) 조회 및 로그 상태 검증
$PY "$SKILL/registry.py" get --job "$JID"
$PY "$SKILL/registry.py" logs "$JID"
$PY "$SKILL/registry.py" logs --list

4. Job Lifecycle

각 위임 작업은 독립적인 분기가 적용되어 라이프사이클을 돌며 수신기의 exit code를 결정 짓습니다.

pending 최초 등록 상태
running 시작 신호 접수
completed 성공 종료
error 실패 종료
cancelled 취소 상태
timeout 제한시간 초과

프로세스 반환 코드(Exit Code) 사양

기동 스크립트 Exit Code 반환 의미 및 트리거 사유
job_subscriber.py 0 에이전트로부터 작업을 성공적으로 마쳤다는 completed 이벤트 수신 완료
job_subscriber.py 1 작업 수행 실패 또는 처리 예외로 에이전트가 error 이벤트를 송출한 경우
job_subscriber.py 2 설정한 허용 제한 시간(timeout_sec) 또는 정체 제한(idle_timeout_sec) 임계치 도달
publish_event.py 0 MQTT 브로커 대상 QoS 1 발행 성공 및 PUBACK 응답 수신 완료
publish_event.py 1 필수 파라미터 누락, 존재하지 않는 JID 참조 등 호출 설정 오류
publish_event.py 2 브로커 접속 실패 또는 네트워크 결함으로 지수 백오프 기반 3회 재시도 유실

5. 이벤트 프로토콜

메시지 전송은 지연 및 간섭을 피하기 위해 1 Job당 1 전용 토픽을 준수합니다.

MQTT 통신 토픽 규격

python/mqtt/jobs/<job_id>/events

메시지 페이로드 스키마 명세

전송하는 모든 데이터는 UTF-8 규격의 JSON 오브젝트 포맷을 따릅니다.

JSON (schema_version = 1)
{
  "schema_version": 1,
  "seq": 7,                              // 동일 JID 내 단조 증가하는 정수형 카운터
  "job_id": "abc12345",
  "event": "started",                    // started | permission_required | progress | completed | error
  "timestamp": "2026-06-19T09:32:00Z",   // ISO-8601 UTC 규격 시각
  "detail": "데이터베이스 쿼리 아티팩트 보관 완료",
  "data": {                              // 확장 요구사항 반영을 위한 옵션 메타 딕셔너리
    "auth_token": "a1b2c3d4..." 
  }
}

Event Catalogue

이벤트명 의무 여부 발행 유발 시점 detail 기술 방식
started 필수 (seq=1) 에이전트가 작업을 할당받아 수행에 착수할 때 "Job <id> started"
permission_required 옵션 에이전트가 시스템 파일 수정 등 사용자 승인이 필요할 때 "needs to write sort_problems.md"
progress 옵션 중간 단계 수행 결과 알림 "creating problem 5/10"
completed 종단 필수 위임 요구 명세를 온전히 이행하고 정상 종료할 때 "saved sort_problems.md"
error 종단 필수 수행 도중 예외가 발생하거나 에이전트가 실패 종료될 때 "internal exception occurred"

방어적 메시지 파싱 규칙 (Defensive Parsing)

공개 인터넷 브로커(HiveMQ 등)는 제3자의 데이터 변조가 손쉽게 가능하므로, job_subscriber.py는 아래 검증을 거쳐 맞지 않는 유해 메시지를 무시하도록 설계되었습니다.

  • JSON 구문 포맷 에러 감지 시 무시 및 폐기
  • schema_version 속성이 구독자 지원 범위(1)와 불일치 시 기각
  • 수집 대기 중인 대상 JID가 아닌 엉뚱한 job_id를 가진 페이로드 차단

6. Audit Log 자동 기록

작업 실행 주기 동안 실시간 상태 흐름을 추적할 수 있도록 .hermes/delegate_job_logs/<job_id>/ 폴더에 3종의 감사 추적 파일이 자동 축적됩니다.

감사 기록 파일 정의

감사 로그 파일 포맷 규격 기록 내용 및 정보 범위
meta.json JSON Object 최초 작업 할당 시점의 프롬프트 전문, 타임아웃 구성, 브로커 접속 스냅샷
events.ndjson NDJSON 생성, 송신, 수신, 상태 전이의 단계별 세부 이력이 발생 시간순으로 한 줄씩 적재
status.json JSON Object 현재 시점의 최종 런타임 결과값 저장 (속도 개선을 위한 포인트 필터용)

시간 흐름별 감지 포인트

기록 액션 시점 events.ndjson 저장 포맷 쓰기 명령의 수행 주체
Job 등록 완료 시 registered (메타 데이터 구성 및 status.json 상태 pending 선 생성) registry.py
작업 상태 변경 시 status_changed (이전 상태 → 변경 상태 흐름) job_subscriber.py / registry.py
에이전트 송신 완료 published (송출 타임스탬프와 페이로드 스냅샷 포함) publish_event.py
수신기 수신 완료 received (수신 감지 성공 시각 및 세부 속성) job_subscriber.py

💡 운영 전환 검증 가이드: 위 종단 검증 시나리오는 공개 PoC 브로커를 활용한 테스트입니다. 사설 운영 브로커로 전환하여 이를 검증하고자 한다면, MQTT 브로커 셋업 가이드 →의 연동 검증 시나리오 절차를 확인하십시오.

로그 쓰기 트랜잭션 격리

감사 로그 아티팩트 파일 쓰기는 메인 에이전트 동작 및 MQTT 발행 스레드를 보호하기 위해 철저한 Best-effort 방식으로 감싸져 실행됩니다. 파일 쓰기 중 동시성 경합 시 try/except 처리 및 OS fcntl 락, logger.warning 백업 처리를 통해 메인 통신 채널을 보장합니다.

7. 명령어 Reference

통합 오케스트레이션 및 상태 점검을 지원하는 CLI 명령어입니다.

서브 커맨드 상세 역할 설명 기본 사용 기법
submit 작업 등록, 수신기 실행, 에이전트 tmux 기동 단계를 일괄 지시합니다. delegate-job submit --agent claude-code --prompt "..."
status 레지스트리 레코드를 질의하여 작업의 세부 구성 정보를 조회합니다. delegate-job status --job <id>
list 저장소에 보관된 작업 내역을 목록 형태로 일괄 조회합니다. delegate-job list
verify 에이전트가 추출한 작업 산출물 아티팩트의 무결성 검증 스크립트를 작동시킵니다. delegate-job verify --job <id> --validate ./validate.sh
wait 위임된 작업이 종단(completed/error) 상태를 맞이할 때까지 동기 대기합니다. delegate-job wait --job <id>
logs 감사 로그 이력을 판독하여 타임라인 순으로 가공된 수행 기록을 출력합니다. delegate-job logs <id> 또는 delegate-job logs --list

8. 종단 Smoke 검증 결과

실제 로컬 호스트 및 공개 HiveMQ 브로커 상에서 정상 구동된 종단 검증 데이터(job cb32569f)의 정합성 리포트입니다.

검증 재현 시나리오 명령어

bash
# 1) human 에이전트 용 임시 smoke 작업 생성
JID=$(.venv/bin/python skills/delegate-job/scripts/registry.py \
        --registry-dir .hermes/jobs register \
        --prompt "smoke: flatten+resplit" --agent human --agent-session tmux:flatten-smoke \
        --timeout 60 --idle-timeout 30 | tail -1)

# 2) 백그라운드 이벤트 감시 모니터 기동
.venv/bin/python skills/delegate-job/scripts/job_subscriber.py \
  --registry-dir .hermes/jobs --job "$JID" --timeout 60 --idle-timeout 30 &

# 3)started 라이프사이클 이벤트 강제 발행
.venv/bin/python skills/delegate-job/scripts/publish_event.py \
  --registry-dir .hermes/jobs --job "$JID" --event started \
  --detail "flatten smoke started"

# 4) completed 종단 이벤트 강제 발행
.venv/bin/python skills/delegate-job/scripts/publish_event.py \
  --registry-dir .hermes/jobs --job "$JID" --event completed \
  --detail "flatten smoke done"

# 5) 모니터 프로세스가 completed 접수 후 자동으로 자원 회수 종료 확인
wait %1

실제 생성된 로그 아티팩트 명세 (job cb32569f)

events.ndjson 감사 기록 전문:

{"event": "registered", "status": "pending", "agent": "human", "agent_session": "tmux:flatten-smoke", "topic_prefix": "python/mqtt/jobs/cb32569f", "timestamp": "2026-06-19T04:09:50Z", "logged_at": "2026-06-19T04:09:50.846Z"}
{"event": "received", "source_event": "started", "seq": 1, "topic": "python/mqtt/jobs/cb32569f/events", "timestamp": "2026-06-19T04:10:03Z", "detail": "flatten smoke started", "logged_at": "2026-06-19T04:10:11.548Z"}
{"event": "published", "source_event": "started", "seq": 1, "topic": "python/mqtt/jobs/cb32569f/events", "retain": false, "timestamp": "2026-06-19T04:10:03Z", "detail": "flatten smoke started", "payload": {"schema_version": 1, "seq": 1, "job_id": "cb32569f", "event": "started", "timestamp": "2026-06-19T04:10:03Z", "detail": "flatten smoke started", "data": {}}, "logged_at": "2026-06-19T04:10:12.555Z"}
{"event": "status_changed", "from": "pending", "to": "running", "timestamp": "2026-06-19T04:10:12Z", "logged_at": "2026-06-19T04:10:12.558Z"}
{"event": "received", "source_event": "completed", "seq": 2, "topic": "python/mqtt/jobs/cb32569f/events", "timestamp": "2026-06-19T04:10:13Z", "detail": "flatten smoke done", "logged_at": "2026-06-19T04:10:16.927Z"}
{"event": "published", "source_event": "completed", "seq": 2, "topic": "python/mqtt/jobs/cb32569f/events", "retain": true, "timestamp": "2026-06-19T04:10:13Z", "detail": "flatten smoke done", "payload": {"schema_version": 1, "seq": 2, "job_id": "cb32569f", "event": "completed", "timestamp": "2026-06-19T04:10:13Z", "detail": "flatten smoke done", "data": {}}, "logged_at": "2026-06-19T04:10:17.932Z"}
{"event": "status_changed", "from": "running", "to": "completed", "timestamp": "2026-06-19T04:10:17Z", "logged_at": "2026-06-19T04:10:17.935Z"}

status.json 실시간 결과 캐시 스냅샷:

{
  "job_id": "cb32569f",
  "status": "completed",
  "updated_at": "2026-06-19T04:10:17Z"
}
  • 이벤트 정합성 검증 완료: 등록 → 구독 → 2회 발행 후 수신기가 정상 복귀 코드 0을 반환하며 종료
  • 감사 로그 누락 방지 확인: events.ndjson 파일 내 시간순 정합 기록 확인 완료
  • 데이터 캐싱 정합성 검증: 레지스트리의 status와 감사 로그 내 status.json 캐시 값이 완성 동기화됨

9. 자주 빠지는 함정

자율 에이전트 비동기 위임 환경 구성 및 운영 셋업 중에 봉착하기 쉬운 결함 시나리오입니다.

① 오래된 Job ID의 에이전트 프롬프트 하드코딩 에러

사유: 에이전트 기동 시 무작위 ID가 새로이 발급됩니다. 과거 세션의 ID를 에이전트 기동 프롬프트에 고정 지정해 주면, 에이전트가 다른 Job ID 채널로 이벤트를 쏘고, 감시 수신기는 무반응 타임아웃(exit 2)에 처하게 됩니다.

→ 해결책: 래퍼 실행 프롬프트에 --job "$JOB_ID" 옵션을 넘겨 신규 JID 값을 주입 하십시오.

② 수신기 실행 전 이벤트 선 송출 유실 결함

사유: MQTT 브로커 통신의 일반 비영속화 메시지는 구독 대기 중인 채널이 없으면 소멸합니다. 수신기를 백그라운드에 올리지 않은 상태에서 에이전트가 이벤트를 쏘면 데이터가 소실되어 프로세스가 정지합니다.

→ 해결책: 래퍼 submit 동작을 쓰거나, completed 발행 시 MQTT retain=true 처리를 병행하십시오.

③ tmux 인터랙티브 모드에서의 세션 명칭 중복 간섭

사유: --agent-session에 고정 문자열(예: tmux:claude)을 기입한 채 복수 작업을 동시 실행하면, tmux 세션이 이미 점유 상태여서 프로세스가 기동 실패를 반환합니다.

→ 해결책: 위임 건수마다 UUID 또는 JID 기반 고유 세션명을 매핑 기동하십시오.

④ 공개 테스트 브로커 보안 위협 요소

사유: HiveMQ 공개 브로커는 누구든지 메시지를 구독/발행 가능하므로 스니핑 및 인젝션 해킹 위협에 완전 노출되어 있습니다.

→ 해결책: 내부망에 전용 Mosquitto 브로커를 올리고 TLS 8883 및 Bearer auth_token 인증 로직을 전개하십시오.

⑤ detail / data 속성 내 보안 자격 키 노출 위험

사유: MQTT 전송 페이로드의 detail 및 data에 로컬 절대 경로, 액세스 토큰 등을 여과 없이 주입하면, 타인에게 시스템 정보가 노출됩니다.

→ 해결책: 전송 값은 추상화된 이력 텍스트만 싣고, 기밀 파라미터는 로컬 Registry 레코드를 통해서만 참조 하십시오.

10. 운영 Broker 전환

보안 통제 및 격리가 요구되는 비즈니스 인프라로 이관하기 위한 독립 브로커 구성 기법입니다. 스크립트 수정 없이 환경변수 조율만으로 이행됩니다.

자세한 단계별 가이드: MQTT 브로커 셋업 (Mosquitto/EMQX, TLS, ACL, Cut-over)
가이드 읽기 →

환경 주입 파일 (mqtt.env 예시)

bash
export MQTT_BROKER=mqtt.internal.example.com
export MQTT_PORT=8883
export MQTT_TLS=1
export MQTT_CA_CERTS=/etc/ssl/certs/internal-ca.pem
export MQTT_USERNAME=hermes-operator
export MQTT_PASSWORD=secure_token_key

# 환경 주입
source mqtt.env

# 위임 submit 스크립트 재시동 (스크립트 소스코드 수정 무)
delegate-job submit --agent claude-code --prompt "운영 서버 이관 점검"

우선순위 역전 장애 (Broker Precedence Pitfall)

공통 모듈인 broker_config_from_job()는 환경 변수 로드 후 레지스트리 JSON 파일의 broker.* 속성을 덮어씌워 합성(Merge)합니다.

즉, 쉘 터미널 상에 새로운 MQTT_BROKER 호스트 환경변수를 주입하더라도, 이미 등록되어 구동 대기 중이던 과거 레지스트리 레코드 파일 내부에 HiveMQ PoC 브로커 주소가 하드코딩 되어 있다면, 변경된 주소가 무시되어 과거 브로커로 접속하게 됩니다. 반드시 신규 작업을 다시 등록(register)하거나, 레코드 JSON 파일(.hermes/jobs/<id>.json)을 수동 편집하여 broker.host 항목을 수동 업데이트한 후 구동 하십시오.

최종 검증 및 정합 완료일: 2026-06-19
참조 데이터 Job ID: cb32569f
인프라: broker.hivemq.com:1883