서브에이전트
서브에이전트는 기존 에이전트 실행에서 생성되는 백그라운드 에이전트 실행입니다. 자체 세션(agent:<agentId>:subagent:<uuid>)에서 실행되며, 완료되면 요청자 채팅 채널에 결과를 공지합니다.
슬래시 명령
/subagents를 사용하여 현재 세션의 서브에이전트 실행을 검사하거나 제어합니다:
/subagents list/subagents kill <id|#|all>/subagents log <id|#> [limit] [tools]/subagents info <id|#>/subagents send <id|#> <message>/subagents steer <id|#> <message>/subagents spawn <agentId> <task> [--model <model>] [--thinking <level>]
스레드 바인딩 제어:
이 명령은 영구 스레드 바인딩을 지원하는 채널에서 작동합니다. 아래 스레드 지원 채널을 참고하세요.
/focus <subagent-label|session-key|session-id|session-label>/unfocus/agents/session idle <duration|off>/session max-age <duration|off>
/subagents info는 실행 메타데이터(상태, 타임스탬프, 세션 ID, 대화 이력 경로, 정리)를 표시합니다.
생성 동작
/subagents spawn은 내부 릴레이가 아닌 사용자 명령으로 백그라운드 서브에이전트를 시작하며, 실행이 완료되면 요청자 채팅에 최종 완료 업데이트를 보냅니다.
- spawn 명령은 비차단이며, 즉시 실행 ID를 반환합니다.
- 완료 시 서브에이전트는 요청자 채팅 채널에 요약/결과 메시지를 공지합니다.
- 수동 생성의 경우, 전달은 복원력 있게 처리됩니다:
- OpenClaw는 안정적인 멱등성 키로 직접
agent전달을 먼저 시도합니다. - 직접 전달이 실패하면 큐 라우팅으로 폴백합니다.
- 큐 라우팅도 불가능하면 짧은 지수 백오프로 재시도한 후 최종 포기합니다.
- OpenClaw는 안정적인 멱등성 키로 직접
- 요청자 세션에 대한 완료 핸드오프는 런타임 생성 내부 컨텍스트(사용자 작성 텍스트가 아닌)이며 다음을 포함합니다:
Result(assistant응답 텍스트, 또는 어시스턴트 응답이 비어 있으면 최신toolResult)Status(completed successfully/failed/timed out/unknown)- 간결한 런타임/토큰 통계
- 요청자 에이전트에게 원시 내부 메타데이터를 전달하지 않고 일반 어시스턴트 어조로 재작성하라는 전달 지침
--model과--thinking은 해당 실행의 기본값을 재정의합니다.- 완료 후 세부 정보와 출력을 검사하려면
info/log를 사용하세요. /subagents spawn은 원샷 모드(mode: "run")입니다. 영구 스레드 바인딩 세션의 경우sessions_spawn에서thread: true와mode: "session"을 사용하세요.- ACP 하네스 세션(Codex, Claude Code, Gemini CLI)의 경우
sessions_spawn에서runtime: "acp"를 사용하고 ACP 에이전트를 참고하세요.
주요 목표:
- 메인 실행을 차단하지 않고 “리서치 / 장기 작업 / 느린 도구” 작업을 병렬화합니다.
- 서브에이전트를 기본적으로 격리합니다(세션 분리 + 선택적 샌드박싱).
- 도구 체계를 남용하기 어렵게 유지합니다: 서브에이전트는 기본적으로 세션 도구를 받지 않습니다.
- 오케스트레이터 패턴을 위한 설정 가능한 중첩 깊이를 지원합니다.
비용 참고: 각 서브에이전트는 자체 컨텍스트와 토큰 사용량을 가집니다. 무거운 반복 작업의 경우 서브에이전트에 저렴한 모델을 설정하고 메인 에이전트는 고품질 모델을 유지하세요.
agents.defaults.subagents.model 또는 에이전트별 재정의를 통해 설정할 수 있습니다.
도구
sessions_spawn을 사용합니다:
- 서브에이전트 실행을 시작합니다 (
deliver: false, 전역 레인:subagent) - 공지 단계를 실행하고 요청자 채팅 채널에 공지 응답을 게시합니다
- 기본 모델:
agents.defaults.subagents.model(또는 에이전트별agents.list[].subagents.model)을 설정하지 않으면 호출자를 상속합니다. 명시적sessions_spawn.model이 여전히 우선합니다. - 기본 사고:
agents.defaults.subagents.thinking(또는 에이전트별agents.list[].subagents.thinking)을 설정하지 않으면 호출자를 상속합니다. 명시적sessions_spawn.thinking이 여전히 우선합니다. - 기본 실행 타임아웃:
sessions_spawn.runTimeoutSeconds가 생략되면, OpenClaw는 설정된agents.defaults.subagents.runTimeoutSeconds를 사용하고, 없으면0(타임아웃 없음)으로 폴백합니다.
도구 매개변수:
task(필수)label?(선택 사항)agentId?(선택 사항; 허용된 경우 다른 에이전트 ID로 생성)model?(선택 사항; 서브에이전트 모델 재정의; 유효하지 않은 값은 건너뛰고 경고와 함께 기본 모델로 실행)thinking?(선택 사항; 서브에이전트 실행의 사고 수준 재정의)runTimeoutSeconds?(설정된agents.defaults.subagents.runTimeoutSeconds가 기본값, 없으면0; 설정 시 N초 후 서브에이전트 실행 중단)thread?(기본값false;true이면 이 서브에이전트 세션에 대한 채널 스레드 바인딩 요청)mode?(run|session)- 기본값은
run thread: true이고mode가 생략되면 기본값이session이 됨mode: "session"은thread: true필요
- 기본값은
cleanup?(delete|keep, 기본값keep)sandbox?(inherit|require, 기본값inherit;require는 대상 자식 런타임이 샌드박스가 아닌 경우 생성 거부)sessions_spawn은 채널 전달 매개변수(target,channel,to,threadId,replyTo,transport)를 받지 않습니다. 전달에는 생성된 실행에서message/sessions_send를 사용하세요.
스레드 바인딩 세션
채널에서 스레드 바인딩이 활성화되면, 서브에이전트가 스레드에 바인딩되어 해당 스레드의 후속 사용자 메시지가 동일한 서브에이전트 세션으로 계속 라우팅될 수 있습니다.
스레드 지원 채널
- Discord (현재 유일하게 지원되는 채널): 영구 스레드 바인딩 서브에이전트 세션(
sessions_spawn에서thread: true), 수동 스레드 제어(/focus,/unfocus,/agents,/session idle,/session max-age), 어댑터 키channels.discord.threadBindings.enabled,channels.discord.threadBindings.idleHours,channels.discord.threadBindings.maxAgeHours,channels.discord.threadBindings.spawnSubagentSessions지원.
빠른 흐름:
sessions_spawn에서thread: true(선택적으로mode: "session")로 생성합니다.- OpenClaw가 활성 채널에서 해당 세션 타겟에 스레드를 생성하거나 바인딩합니다.
- 해당 스레드의 응답과 후속 메시지가 바인딩된 세션으로 라우팅됩니다.
/session idle로 비활동 자동 해제를 검사/업데이트하고/session max-age로 하드 캡을 제어합니다.- 수동으로 분리하려면
/unfocus를 사용합니다.
수동 제어:
/focus <target>는 현재 스레드(또는 새 스레드)를 서브에이전트/세션 타겟에 바인딩합니다./unfocus는 현재 바인딩된 스레드의 바인딩을 제거합니다./agents는 활성 실행과 바인딩 상태(thread:<id>또는unbound)를 나열합니다./session idle과/session max-age는 포커스된 바인딩 스레드에서만 작동합니다.
설정 스위치:
- 전역 기본값:
session.threadBindings.enabled,session.threadBindings.idleHours,session.threadBindings.maxAgeHours - 채널 재정의 및 생성 자동 바인딩 키는 어댑터별로 다릅니다. 위의 스레드 지원 채널을 참고하세요.
설정 참조와 슬래시 명령에서 현재 어댑터 세부 정보를 확인하세요.
허용 목록:
agents.list[].subagents.allowAgents:agentId로 대상 지정할 수 있는 에이전트 ID 목록(["*"]로 모든 에이전트 허용). 기본값: 요청자 에이전트만.- 샌드박스 상속 가드: 요청자 세션이 샌드박스인 경우,
sessions_spawn은 샌드박스 없이 실행될 대상을 거부합니다.
검색:
agents_list를 사용하여sessions_spawn에 현재 허용된 에이전트 ID를 확인합니다.
자동 아카이브:
- 서브에이전트 세션은
agents.defaults.subagents.archiveAfterMinutes(기본값: 60) 후 자동으로 아카이브됩니다. - 아카이브는
sessions.delete를 사용하고 대화 이력을*.deleted.<timestamp>로 이름 변경합니다(같은 폴더). cleanup: "delete"는 공지 직후 아카이브합니다(이름 변경을 통해 대화 이력은 유지).- 자동 아카이브는 최선 노력 방식입니다. 게이트웨이가 재시작되면 보류 중인 타이머가 손실됩니다.
runTimeoutSeconds는 자동 아카이브하지 않습니다. 실행만 중지합니다. 세션은 자동 아카이브까지 유지됩니다.- 자동 아카이브는 depth-1과 depth-2 세션 모두에 동일하게 적용됩니다.
중첩 서브에이전트
기본적으로 서브에이전트는 자체 서브에이전트를 생성할 수 없습니다(maxSpawnDepth: 1). maxSpawnDepth: 2를 설정하면 한 단계의 중첩이 가능하며, 오케스트레이터 패턴: 메인 → 오케스트레이터 서브에이전트 → 워커 서브-서브에이전트를 사용할 수 있습니다.
활성화 방법
{
agents: {
defaults: {
subagents: {
maxSpawnDepth: 2, // 서브에이전트가 자식 생성 허용 (기본값: 1)
maxChildrenPerAgent: 5, // 에이전트 세션당 최대 활성 자식 수 (기본값: 5)
maxConcurrent: 8, // 전역 동시성 레인 제한 (기본값: 8)
runTimeoutSeconds: 900, // sessions_spawn 생략 시 기본 타임아웃 (0 = 타임아웃 없음)
},
},
},
}
깊이 수준
| 깊이 | 세션 키 형태 | 역할 | 생성 가능? |
|---|---|---|---|
| 0 | agent:<id>:main | 메인 에이전트 | 항상 |
| 1 | agent:<id>:subagent:<uuid> | 서브에이전트 (depth 2 허용 시 오케스트레이터) | maxSpawnDepth >= 2인 경우만 |
| 2 | agent:<id>:subagent:<uuid>:subagent:<uuid> | 서브-서브에이전트 (리프 워커) | 불가 |
공지 체인
결과가 체인을 따라 올라갑니다:
- Depth-2 워커 완료 → 부모(depth-1 오케스트레이터)에게 공지
- Depth-1 오케스트레이터가 공지를 받고, 결과를 종합하고, 완료 → 메인에 공지
- 메인 에이전트가 공지를 받고 사용자에게 전달
각 수준은 직접 자식의 공지만 볼 수 있습니다.
깊이별 도구 정책
- 역할과 제어 범위는 생성 시점에 세션 메타데이터에 기록됩니다. 이를 통해 플랫하거나 복원된 세션 키가 실수로 오케스트레이터 권한을 되찾는 것을 방지합니다.
- Depth 1 (오케스트레이터,
maxSpawnDepth >= 2인 경우):sessions_spawn,subagents,sessions_list,sessions_history를 받아 자식을 관리할 수 있습니다. 다른 세션/시스템 도구는 거부됩니다. - Depth 1 (리프,
maxSpawnDepth == 1인 경우): 세션 도구 없음(현재 기본 동작). - Depth 2 (리프 워커): 세션 도구 없음 —
sessions_spawn은 depth 2에서 항상 거부됩니다. 추가 자식을 생성할 수 없습니다.
에이전트별 생성 제한
각 에이전트 세션(모든 깊이)은 한 번에 최대 maxChildrenPerAgent(기본값: 5)개의 활성 자식을 가질 수 있습니다. 이는 단일 오케스트레이터의 과도한 팬아웃을 방지합니다.
캐스케이드 중지
Depth-1 오케스트레이터를 중지하면 모든 depth-2 자식이 자동으로 중지됩니다:
- 메인 채팅에서
/stop은 모든 depth-1 에이전트를 중지하고 depth-2 자식에게 전파합니다. /subagents kill <id>는 특정 서브에이전트를 중지하고 자식에게 전파합니다./subagents kill all은 요청자의 모든 서브에이전트를 중지하고 전파합니다.
인증
서브에이전트 인증은 세션 유형이 아닌 에이전트 ID에 의해 결정됩니다:
- 서브에이전트 세션 키는
agent:<agentId>:subagent:<uuid>입니다. - 인증 저장소는 해당 에이전트의
agentDir에서 로드됩니다. - 메인 에이전트의 인증 프로파일은 폴백으로 병합됩니다. 충돌 시 에이전트 프로파일이 메인 프로파일을 재정의합니다.
참고: 병합은 추가적이므로 메인 프로파일은 항상 폴백으로 사용 가능합니다. 에이전트별 완전 격리 인증은 아직 지원되지 않습니다.
공지
서브에이전트는 공지 단계를 통해 보고합니다:
- 공지 단계는 서브에이전트 세션(요청자 세션이 아닌)에서 실행됩니다.
- 서브에이전트가 정확히
ANNOUNCE_SKIP으로 응답하면 아무것도 게시되지 않습니다. - 그렇지 않으면 전달은 요청자 깊이에 따라 달라집니다:
- 최상위 요청자 세션은 외부 전달(
deliver=true)로 후속agent호출 사용 - 중첩된 요청자 서브에이전트 세션은 내부 후속 주입(
deliver=false)을 받아 오케스트레이터가 세션 내에서 자식 결과를 종합할 수 있음 - 중첩된 요청자 서브에이전트 세션이 없으면, OpenClaw는 사용 가능할 때 해당 세션의 요청자로 폴백
- 최상위 요청자 세션은 외부 전달(
- 자식 완료 집계는 중첩 완료 결과를 구성할 때 현재 요청자 실행으로 범위가 제한되어, 이전 실행의 오래된 자식 출력이 현재 공지에 누출되는 것을 방지합니다.
- 공지 응답은 채널 어댑터에서 사용 가능한 스레드/토픽 라우팅을 보존합니다.
- 공지 컨텍스트는 안정적인 내부 이벤트 블록으로 정규화됩니다:
- 소스 (
subagent또는cron) - 자식 세션 키/ID
- 공지 유형 + 작업 레이블
- 런타임 결과에서 파생된 상태 줄(
success,error,timeout또는unknown) - 공지 단계의 결과 콘텐츠(없으면
(no output)) - 응답 시 vs 침묵 유지 시점을 설명하는 후속 지침
- 소스 (
Status는 모델 출력에서 추론되지 않습니다. 런타임 결과 신호에서 옵니다.
공지 페이로드에는 끝에 통계 줄이 포함됩니다(래핑되어도):
- 런타임 (예:
runtime 5m12s) - 토큰 사용량 (입력/출력/합계)
- 모델 가격이 설정된 경우 예상 비용(
models.providers.*.models[].cost) sessionKey,sessionId, 대화 이력 경로 (메인 에이전트가sessions_history로 이력을 가져오거나 디스크의 파일을 검사할 수 있음)- 내부 메타데이터는 조율 전용입니다. 사용자 대면 응답은 일반 어시스턴트 어조로 재작성해야 합니다.
도구 정책 (서브에이전트 도구)
기본적으로 서브에이전트는 세션 도구와 시스템 도구를 제외한 모든 도구를 받습니다:
sessions_listsessions_historysessions_sendsessions_spawn
maxSpawnDepth >= 2인 경우, depth-1 오케스트레이터 서브에이전트는 자식 관리를 위해 sessions_spawn, subagents, sessions_list, sessions_history를 추가로 받습니다.
설정으로 재정의:
{
agents: {
defaults: {
subagents: {
maxConcurrent: 1,
},
},
},
tools: {
subagents: {
tools: {
// deny가 우선
deny: ["gateway", "cron"],
// allow가 설정되면 allow-only가 됨 (deny가 여전히 우선)
// allow: ["read", "exec", "process"]
},
},
},
}
동시성
서브에이전트는 전용 인프로세스 큐 레인을 사용합니다:
- 레인 이름:
subagent - 동시성:
agents.defaults.subagents.maxConcurrent(기본값8)
중지
- 요청자 채팅에서
/stop을 보내면 요청자 세션이 중단되고 해당 세션에서 생성된 활성 서브에이전트 실행이 중지되며, 중첩된 자식에게 전파됩니다. /subagents kill <id>는 특정 서브에이전트를 중지하고 자식에게 전파합니다.
제한 사항
- 서브에이전트 공지는 최선 노력입니다. 게이트웨이가 재시작되면 보류 중인 “공지 반환” 작업이 손실됩니다.
- 서브에이전트는 여전히 동일한 게이트웨이 프로세스 리소스를 공유합니다.
maxConcurrent를 안전 밸브로 취급하세요. sessions_spawn은 항상 비차단입니다: 즉시{ status: "accepted", runId, childSessionKey }를 반환합니다.- 서브에이전트 컨텍스트는
AGENTS.md+TOOLS.md만 주입합니다(SOUL.md,IDENTITY.md,USER.md,HEARTBEAT.md,BOOTSTRAP.md제외). - 최대 중첩 깊이는 5입니다(
maxSpawnDepth범위: 1–5). 대부분의 사용 사례에는 depth 2를 권장합니다. maxChildrenPerAgent는 세션당 활성 자식을 제한합니다(기본값: 5, 범위: 1–20).