본문으로 건너뛰기

Subagent 위임

anchor alias

Subagent 위임

delegate_task 도구는 격리된 컨텍스트, 제한된 toolset, 자체 터미널 세션을 가진 child AIAgent 인스턴스를 생성합니다. 각 child는 완전히 새로운 대화를 받고 독립적으로 작업합니다. 부모 컨텍스트에는 child의 최종 요약만 들어갑니다.

단일 작업

delegate_task(
goal="Debug why tests fail",
context="Error: assertion in test_foo.py line 42",
toolsets=["terminal", "file"]
)

병렬 배치

기본적으로 최대 3개의 subagent가 동시에 실행됩니다. 이 값은 설정 가능하며 hard ceiling은 없습니다.

delegate_task(tasks=[
{"goal": "Research topic A", "toolsets": ["web"]},
{"goal": "Research topic B", "toolsets": ["web"]},
{"goal": "Fix the build", "toolsets": ["terminal", "file"]}
])

Subagent 컨텍스트 동작 방식

Critical: Subagents Know Nothing

subagent는 완전히 새 대화로 시작합니다. 부모의 대화 기록, 이전 도구 호출, 위임 전에 논의한 내용에 대해 아무것도 모릅니다. subagent가 받는 컨텍스트는 부모 에이전트가 delegate_task를 호출할 때 채우는 goalcontext 필드뿐입니다.

따라서 부모 에이전트는 subagent에게 필요한 정보를 전부 호출 안에 넣어야 합니다.

# BAD - subagent has no idea what "the error" is
delegate_task(goal="Fix the error")

# GOOD - subagent has all context it needs
delegate_task(
goal="Fix the TypeError in api/handlers.py",
context="""The file api/handlers.py has a TypeError on line 47:
'NoneType' object has no attribute 'get'.
The function process_request() receives a dict from parse_body(),
but parse_body() returns None when Content-Type is missing.
The project is at /home/user/myproject and uses Python 3.11."""
)

subagent는 goal과 context로 구성된 집중된 system prompt를 받습니다. 그 프롬프트는 작업 완료, 수행한 일, 발견한 내용, 수정한 파일, 마주친 문제를 구조화된 요약으로 보고하도록 지시합니다.

실제 예제

병렬 조사

여러 주제를 동시에 조사하고 요약을 모읍니다.

delegate_task(tasks=[
{
"goal": "Research the current state of WebAssembly in 2025",
"context": "Focus on: browser support, non-browser runtimes, language support",
"toolsets": ["web"]
},
{
"goal": "Research the current state of RISC-V adoption in 2025",
"context": "Focus on: server chips, embedded systems, software ecosystem",
"toolsets": ["web"]
},
{
"goal": "Research quantum computing progress in 2025",
"context": "Focus on: error correction breakthroughs, practical applications, key players",
"toolsets": ["web"]
}
])

코드 리뷰 + 수정

새 컨텍스트에 review-and-fix 워크플로를 위임합니다.

delegate_task(
goal="Review the authentication module for security issues and fix any found",
context="""Project at /home/user/webapp.
Auth module files: src/auth/login.py, src/auth/jwt.py, src/auth/middleware.py.
The project uses Flask, PyJWT, and bcrypt.
Focus on: SQL injection, JWT validation, password handling, session management.
Fix any issues found and run the test suite (pytest tests/auth/).""",
toolsets=["terminal", "file"]
)

다중 파일 리팩터링

부모 컨텍스트를 대량 출력으로 채우지 않도록 큰 리팩터링 작업을 위임합니다.

delegate_task(
goal="Refactor all Python files in src/ to replace print() with proper logging",
context="""Project at /home/user/myproject.
Use the 'logging' module with logger = logging.getLogger(__name__).
Replace print() calls with appropriate log levels:
- print(f"Error: ...") -> logger.error(...)
- print(f"Warning: ...") -> logger.warning(...)
- print(f"Debug: ...") -> logger.debug(...)
- Other prints -> logger.info(...)
Don't change print() in test files or CLI output.
Run pytest after to verify nothing broke.""",
toolsets=["terminal", "file"]
)

배치 모드 세부 사항

tasks 배열을 제공하면 subagent는 thread pool을 사용해 병렬로 실행됩니다.

  • 최대 동시성: 기본값은 3개 작업입니다. delegation.max_concurrent_children 또는 DELEGATION_MAX_CONCURRENT_CHILDREN 환경 변수로 설정할 수 있으며, 최솟값은 1이고 hard ceiling은 없습니다. 한도보다 큰 batch는 조용히 잘리는 대신 도구 오류를 반환합니다.
  • Thread pool: 설정된 동시성 한도를 max worker로 사용해 ThreadPoolExecutor를 실행합니다.
  • 진행 표시: CLI mode에서는 tree view가 각 subagent의 도구 호출을 실시간으로 보여주고, 작업별 완료 라인을 표시합니다. gateway mode에서는 progress가 batch 처리되어 부모의 progress callback으로 relay됩니다.
  • 결과 순서: 완료 순서와 관계없이 입력 순서에 맞도록 task index 기준으로 정렬됩니다.
  • Interrupt propagation: 부모가 중단되면, 예를 들어 사용자가 새 메시지를 보내면, 활성 child가 모두 중단됩니다.

단일 작업 위임은 thread pool overhead 없이 직접 실행됩니다.

모델 override

config.yaml에서 subagent용 모델을 따로 설정할 수 있습니다. 단순 작업을 더 저렴하고 빠른 모델에 위임할 때 유용합니다.

# In ~/.hermes/config.yaml
delegation:
model: "google/gemini-flash-2.0" # Cheaper model for subagents
provider: "openrouter" # Optional: route subagents to a different provider

생략하면 subagent는 부모와 같은 모델을 사용합니다.

Toolset 선택 팁

toolsets 매개변수는 subagent가 접근할 수 있는 도구를 제어합니다. 작업에 맞춰 선택하세요.

Toolset 패턴사용 사례
["terminal", "file"]코드 작업, 디버깅, 파일 편집, 빌드
["web"]조사, 사실 확인, 문서 조회
["terminal", "file", "web"]full-stack 작업(기본값)
["file"]실행 없이 읽기 전용 분석, 코드 리뷰
["terminal"]시스템 관리, 프로세스 관리

다음 toolset은 지정하더라도 subagent에서는 차단됩니다.

  • delegation - leaf subagent에서는 차단됩니다(기본값). role="orchestrator" child에서는 유지될 수 있지만 max_spawn_depth의 제한을 받습니다. 아래 깊이 제한과 중첩 orchestration을 참고하세요.
  • clarify - subagent는 사용자와 상호작용할 수 없습니다.
  • memory - 공유 영구 메모리에 쓸 수 없습니다.
  • code_execution - child는 step-by-step으로 reasoning하도록 제한됩니다.
  • send_message - Telegram 메시지 전송 같은 cross-platform side effect를 막습니다.

최대 iteration

각 subagent에는 tool-calling turn 수를 제한하는 iteration 한도가 있습니다. 기본값은 50입니다.

delegate_task(
goal="Quick file check",
context="Check if /etc/nginx/nginx.conf exists and print its first 10 lines",
max_iterations=10 # Simple task, don't need many turns
)

Child timeout

subagent가 delegation.child_timeout_seconds wall-clock seconds보다 오래 조용히 있으면 stuck 상태로 판단되어 종료됩니다. 기본값은 600초(10분)입니다. 이전 릴리스의 300초에서 늘어난 이유는, 복잡한 research 작업에서 high-reasoning 모델이 생각하는 중간에 종료되는 일이 있었기 때문입니다. 설치 환경에 맞게 조정하세요.

delegation:
child_timeout_seconds: 600 # default

빠른 로컬 모델에는 낮추고, 어려운 문제를 느린 reasoning 모델로 처리할 때는 올리세요. timer는 child가 API 호출이나 도구 호출을 할 때마다 reset됩니다. 진짜로 idle 상태인 worker만 종료됩니다.

Diagnostic dump on zero-call timeout

subagent가 API 호출을 한 번도 하지 못한 채 timeout되면(보통 provider 접근 불가, auth 실패, tool schema 거부), delegate_task~/.hermes/logs/subagent-timeout-<session>-<timestamp>.log에 구조화된 diagnostic을 씁니다. 여기에는 subagent 설정 snapshot, credential resolution trace, 초기 오류 메시지가 들어가므로, 예전의 조용한 timeout보다 원인 파악이 훨씬 쉽습니다.

실행 중인 subagent 모니터링(/agents)

TUI는 /agents overlay(alias /tasks)를 제공해 recursive delegate_task fan-out을 감사 가능한 표면으로 보여줍니다.

  • 부모별로 묶인 실행 중 및 최근 완료 subagent live tree view
  • branch별 cost, token, touched file rollup
  • kill/pause control - sibling을 중단하지 않고 특정 subagent만 mid-flight 취소
  • 사후 검토 - subagent가 부모에게 반환된 뒤에도 각 subagent의 turn-by-turn history를 단계별로 확인

classic CLI는 /agents를 텍스트 요약으로 출력합니다. overlay가 가장 유용한 곳은 TUI입니다. TUI - Slash commands를 참고하세요.

깊이 제한과 중첩 orchestration

기본적으로 위임은 flat입니다. 부모(depth 0)가 child(depth 1)를 만들고, 그 child는 다시 위임할 수 없습니다. 이는 runaway recursive delegation을 방지합니다.

research -> synthesis 또는 여러 sub-problem을 병렬 orchestration하는 다단계 워크플로에서는 부모가 자신의 worker를 다시 위임할 수 있는 orchestrator child를 만들 수 있습니다.

delegate_task(
goal="Survey three code review approaches and recommend one",
role="orchestrator", # Allows this child to spawn its own workers
context="...",
)
  • role="leaf"(기본값): child는 더 이상 위임할 수 없습니다. flat delegation과 동일합니다.
  • role="orchestrator": child가 delegation toolset을 유지합니다. 단, delegation.max_spawn_depth의 gate를 받습니다. 기본값은 1이라 flat이며, 이 상태에서 role="orchestrator"는 효과가 없습니다. max_spawn_depth를 2로 올리면 orchestrator child가 leaf grandchild를 만들 수 있고, 3이면 3단계까지 허용됩니다.
  • delegation.orchestrator_enabled: false: 모든 child를 leaf로 강제하는 전역 kill switch입니다.

비용 경고: max_spawn_depth: 3max_concurrent_children: 3이면 tree가 3 x 3 x 3 = 27개의 동시 leaf agent까지 커질 수 있습니다. 레벨을 하나 늘릴 때마다 비용이 곱해지므로 의도적으로 올리세요.

수명과 내구성

delegate_task is synchronous - not durable

delegate_task부모의 현재 턴 안에서 실행됩니다. 모든 child가 끝나거나 취소될 때까지 부모를 block합니다. 이는 백그라운드 작업 queue가 아닙니다.

  • 부모가 중단되면(사용자가 새 메시지를 보내거나 /stop, /new를 실행), 활성 child가 모두 취소되고 status="interrupted"를 반환합니다. 진행 중이던 작업은 버려집니다.
  • child는 부모 턴이 끝난 뒤 계속 실행되지 않습니다.
  • 취소된 child는 구조화된 결과(status="interrupted", exit_reason="interrupted")를 반환하지만, 부모도 중단된 상태이므로 그 결과가 사용자에게 보이는 응답까지 도달하지 못하는 경우가 많습니다.

interrupt를 견디거나 현재 턴보다 오래 살아야 하는 내구성 있는 장기 작업에는 다음을 사용하세요.

  • cronjob(action="create") - 별도 agent run을 예약합니다. 부모 턴 interrupt의 영향을 받지 않습니다.
  • terminal(background=True, notify_on_complete=True) - 에이전트가 다른 일을 하는 동안 계속 실행되는 장시간 셸 명령입니다.

핵심 속성

  • 각 subagent는 부모와 분리된 자체 터미널 세션을 받습니다.
  • 중첩 위임은 opt-in입니다. role="orchestrator" child만 추가 위임이 가능하고, max_spawn_depth를 기본값 1(flat)에서 올려야 합니다. orchestrator_enabled: false로 전역 비활성화할 수 있습니다.
  • leaf subagent는 delegate_task, clarify, memory, send_message, execute_code를 호출할 수 없습니다. orchestrator subagent는 delegate_task만 유지하고 나머지 네 도구는 여전히 사용할 수 없습니다.
  • Interrupt propagation - 부모를 중단하면 모든 활성 child가 중단됩니다. orchestrator 아래의 grandchild도 포함됩니다.
  • 최종 요약만 부모 컨텍스트에 들어가므로 token 사용이 효율적입니다.
  • subagent는 부모의 API key, provider 설정, credential pool을 상속합니다. 이를 통해 rate limit 시 key rotation이 가능합니다.

Delegation과 execute_code 비교

기준delegate_taskexecute_code
Reasoning전체 LLM reasoning loopPython 코드 실행만
Context새롭고 격리된 대화대화 없음, script만
도구 접근차단되지 않은 도구 + reasoningRPC를 통한 제한된 도구, reasoning 없음
병렬성기본 3개 동시 subagent(설정 가능)단일 script
적합한 작업판단이 필요한 복잡한 작업기계적인 다단계 pipeline
token 비용높음(전체 LLM loop)낮음(stdout만 반환)
사용자 상호작용없음(subagent는 clarify 불가)없음

기준: subtask에 reasoning, 판단, multi-step 문제 해결이 필요하면 delegate_task를 사용하세요. 기계적인 데이터 처리나 scripted workflow가 필요하면 execute_code를 사용하세요.

설정

# In ~/.hermes/config.yaml
delegation:
max_iterations: 50 # Max turns per child (default: 50)
# max_concurrent_children: 3 # Parallel children per batch (default: 3)
# max_spawn_depth: 1 # Tree depth (1-3, default 1 = flat). Raise to 2 to allow orchestrator children to spawn leaves; 3 for three levels.
# orchestrator_enabled: true # Disable to force all children to leaf role.
model: "google/gemini-3-flash-preview" # Optional provider/model override
provider: "openrouter" # Optional built-in provider

# Or use a direct custom endpoint instead of provider:
delegation:
model: "qwen2.5-coder"
base_url: "http://localhost:1234/v1"
api_key: "local-key"

에이전트는 작업 복잡도에 따라 위임을 자동으로 판단합니다. 사용자가 명시적으로 delegate하라고 요청할 필요는 없습니다. 적절하다고 판단되면 에이전트가 스스로 사용합니다.