-
큰 작업을 혼자 떠안지 않는 에이전트 — OpenClaw가 하위 작업을 격리 세션으로 떼어내는 법IT 2026. 7. 16. 21:00
오픈소스 AI 어시스턴트 OpenClaw를 집 서버에 올려 쓰다 보면, 한 번쯤 "왜 에이전트가 큰 작업 하나를 받으면 점점 멍청해지지?"라는 의문에 부딪힌다. 리서치 5건을 시키고, 그 결과로 코드를 고치고, 다시 테스트를 돌리라고 하면 — 대화가 길어질수록 답변이 흐려지고 토큰 청구서가 불어난다. OpenClaw의 서브에이전트(sub-agent) 도구는 정확히 이 문제를 겨냥한다. 큰 작업을 한 에이전트가 혼자 순차로 떠안는 대신, 하위 작업을 격리된 백그라운드 세션으로 떼어내고(
sessions_spawn) 결과만 회수하는 방식이다. 이 글은 그 문제와 OpenClaw가 고른 답(격리 세션 + 선택적 컨텍스트 fork + 푸시 기반 완료 회수)을 따라간다.배경 — 에이전트의 컨텍스트는 유한하고, 오염된다
LLM 에이전트가 일하는 방식의 핵심 제약은 컨텍스트 윈도(context window, 모델이 한 번에 읽을 수 있는 토큰 분량)가 유한하다는 점이다. 대화가 진행되면 지금까지의 모든 메시지·도구 호출·도구 결과가 이 윈도에 차곡차곡 쌓인다. 작업을 하나 끝낼 때마다 그 중간 산물(긴 검색 결과, 파일 덤프, 실패한 시도)이 모두 기록으로 남아 다음 판단의 입력이 된다.
여기서 두 가지가 동시에 나빠진다. 하나는 비대화 — 윈도가 차면 오래된 메시지가 잘려 나가거나, 모델이 수만 토큰 속에서 정작 중요한 한 줄을 놓친다. 다른 하나는 오염 — A 작업을 하느라 읽은 잡다한 내용이 B 작업의 판단에 끼어든다. 한 사람이 책상 위에 서류 다섯 더미를 다 펼쳐 놓고 동시에 처리하려다 결국 어느 더미 것인지 헷갈리는 상황과 비슷한 발상이다.
다이어그램 설명. 이 그림은 한 에이전트가 큰 작업을 혼자 순차로 처리할 때 맥락이 어떻게 무너지는지를 보여준다. 리서치 결과가 맥락에 쌓이고, 그 잔재를 안은 채 코드 수정으로 넘어가고, 다시 그 둘의 잔재가 누적된 채 테스트로 이어진다 — '답변 품질 저하' 단계에서 윈도가 포화되며 품질이 떨어지고 비용이 치솟는다. 핵심은 각 단계의 중간 산물이 다음 단계로 강제로 흘러든다는 점이다. 흔한 오해가 "어차피 한 모델이니 다 같은 맥락에서 보는 게 효율적이지"인데, 실제로는 리서치의 검색 덤프 같은 일회용 잔재가 코드 판단을 흐리는 부작용이 더 크다. 그래서 무슨 가치인가 — 이 그림이 뒤에 나올 해법(작업을 떼어 격리하기)이 왜 필요한지를 한 장으로 못 박는다.
핵심 문제 — "위임"을 안전하고 비싸지 않게 만들기
하위 작업을 따로 도는 보조 일꾼에게 맡기자는 발상 자체는 자연스럽다. 문제는 그 위임을 안전하게, 그리고 비싸지 않게 구현하는 일이다. 순진하게 만들면 세 가지가 터진다.
다이어그램 설명. 이 그림은 위임을 순진하게 구현했을 때 갈라지는 세 가지 함정을 보여준다. '순진한 위임 구현' 단계에서 세 갈래로 터지는데, 첫째는 보조 일꾼이 부모의 전체 대화를 통째로 물려받아 컨텍스트 격리의 이점이 사라지는 맥락 누수, 둘째는 일꾼이 또 일꾼을 만드는 식으로 통제 없이 번지는 폭주(팬아웃, fan-out — 한 노드에서 여러 자식으로 갈라져 나가는 것), 셋째는 부모가 "끝났니?"를 반복해서 물으며 토큰과 대화 턴을 낭비하는 대기 낭비다. 가장 놓치기 쉬운 건 세 번째다 — 비동기 작업을 폴링(poll, 끝났는지 주기적으로 되묻는 방식)으로 기다리는 건 직관적이지만, LLM 에이전트에서는 그 되묻기 한 번 한 번이 모델 호출이라 비용이 된다. 그래서 무슨 가치인가 — OpenClaw의 서브에이전트 설계는 이 세 함정 각각에 대한 명시적 답(기본 격리·깊이 제한·푸시 기반 완료)으로 읽으면 그대로 이해된다.
해결 방법 — 격리 세션을 띄우고, 결과만 회수한다
OpenClaw의 답은 하위 작업을 자기만의 세션을 가진 백그라운드 실행으로 떼어내는 것이다. 이 보조 실행을 서브에이전트(sub-agent)라 부르고, 띄우는 도구가
sessions_spawn이다. 각 서브에이전트는agent:<에이전트id>:subagent:<uuid>형태의 독립 세션 키를 받아 부모와 분리된 자기 대화 기록 위에서 돈다. 작업이 끝나면 결과를 부모(요청자) 쪽으로 되돌려 알린다(announce).기본은 격리, 필요할 때만 fork
서브에이전트의 첫 번째 설계 원칙은 "기본값은 격리"다. 새로 띄운 서브에이전트는 부모의 대화 기록을 물려받지 않고 깨끗한 빈 맥락(isolated)에서 시작한다. 위임할 일은 작업 지시문(
task)에 다 적어 넘기는 게 원칙이다. 다만 그 작업이 정말로 부모의 진행 중인 대화·직전 도구 결과에 의존할 때만, 한 번의 spawn에 한해context: "fork"를 켜서 부모 기록을 자식 세션으로 분기(fork)해 넣을 수 있다.다이어그램 설명. 이 그림은 서브에이전트를 띄울 때 맥락을 어떻게 줄지 결정하는 분기를 보여준다. 호출에서 출발해 "부모 대화에 의존하는가?"라는 한 갈림길을 지난다 — 대부분은 의존하지 않으므로 깨끗한 빈 맥락(isolated)으로 시작하고, 진짜로 직전 대화·도구 결과가 필요한 드문 경우에만 부모 기록 분기(fork)를 택한다. 이 패턴을 쓰는 이유는 격리가 곧 토큰 절약이자 오염 차단이기 때문이다 — 빈 맥락으로 시작하면 부모의 수만 토큰을 복제할 필요가 없다. 놓치기 쉬운 함정은 부모 기록 분기를 "명확한 지시문을 쓰기 귀찮을 때의 대체재"로 남용하는 것이다. 공식 문서도 이걸 아껴 쓰라고 못 박는다 — 분기는 맥락에 민감한 위임을 위한 것이지, 작업 프롬프트를 제대로 쓰지 않으려는 핑계가 아니다. 그래서 무슨 가치인가 — 기본을 격리로 두면 위임 한 번의 비용과 오염 위험이 동시에 최소화되고, 정말 필요한 순간에만 부모 맥락을 빌려 정확도를 챙길 수 있다.
비차단 + 푸시 기반 완료 — 폴링하지 마라
두 번째 설계 원칙은 기다리는 방식이다.
sessions_spawn은 비차단(non-blocking)이다 — 호출하면 즉시{ status: "accepted", runId, childSessionKey }를 돌려주고, 실제 작업은 백그라운드에서 돈다. 그럼 부모는 결과를 어떻게 받을까? 핵심은 "되묻지 않는다"는 것이다. 부모가 자식 결과 없이는 최종 답을 못 낼 때는sessions_yield를 호출한다 — 이건 지금 턴을 끝내고, 자식의 완료 이벤트가 다음 메시지로 도착하기를 기다리는 대기 기본기(primitive)다.다이어그램 설명. 이 그림은 작업을 띄운 뒤 결과를 회수하기까지의 푸시 기반(push-based) 흐름을 보여준다. 띄우면 곧장 실행 ID만 돌려받고, 부모는 현재 턴을 끝내고 대기하며, 백그라운드 실행이 끝나면 알림 단계가 결과를 부모 쪽으로 밀어 넣어(push), 그 완료가 부모의 다음 턴에 메시지로 도착해 종합으로 이어진다. 푸시 기반이라는 게 핵심이다 — 부모가 "끝났니?"를 주기적으로 묻는 풀(pull) 방식이 아니라, 끝난 쪽이 알아서 알려 주는 방식이다. 문서가 거듭 경고하는 함정이 바로 여기 있다. 띄운 직후 목록 조회 도구나 기록 조회 도구, 셸
sleep을 반복 호출하는 폴링 루프를 만들면 안 된다 — 그건 매 호출이 모델 턴이라 비용만 태우고, 심지어 자기 history를 오염시켜 완료 감지를 더 어렵게 만든다. 대기는 오로지 턴을 끝내고 기다리는 그 기본기로만 한다. 그래서 무슨 가치인가 — 비차단 + 푸시 조합 덕에 부모는 자식이 도는 동안 다른 일을 하거나 조용히 멈춰 있을 수 있고, 위임의 대기 낭비가 사라진다.완료 회수와 검증 — 자식 결과는 "증거"이지 "명령"이 아니다
자식이 끝나면 알림(announce) 단계가 결과를 부모 세션으로 전달한다. 이때 넘어가는 건 자식의 마지막 보이는 어시스턴트 답변 텍스트(
Result), 런타임이 판정한 상태(Status), 토큰·실행 통계, 그리고 "이 결과를 검증한 뒤 원래 작업이 끝났는지 판단하라"는 지시다. 상태는 자식이 "다 됐어요"라고 말해서가 아니라 실제 실행 결과로 판정되고, 자식이 돌려준 텍스트는 부모가 종합할 보고·증거일 뿐 시스템 정책을 덮어쓰지 않는다.다이어그램 설명. 이 그림은 자식의 결과가 부모에게 전달돼 검증을 거치는 회수 경로를 보여준다. '알림' 단계가 자식 세션 안에서 결과와 런타임 판정 상태를 묶어 부모 세션에 전달하면, 부모는 검증 후 갈림길에서 작업이 끝났는지 판단한다 — 끝났으면 일반 어조로 최종 답을 쓰고, 더 할 일이 남았으면 작업을 이어간다. 핵심 패턴은 "자식의 보고는 곧장 사용자에게 가지 않고 반드시 부모의 검증을 거친다"는 점이다. 그래서 무슨 가치인가 — 위임이 늘어도 최종 책임과 판단은 부모에 머물러, 자율 위임의 편의와 통제를 동시에 잡는다.
오케스트레이터 패턴 — 깊이 2까지의 위임 트리
기본적으로 서브에이전트는 또 다른 서브에이전트를 띄울 수 없다(
maxSpawnDepth: 1). 이게 앞서 본 "폭주하는 팬아웃" 함정에 대한 1차 방어다. 다만 큰 작업을 더 잘게 나눠야 할 때를 위해maxSpawnDepth: 2로 한 단계 중첩을 허용할 수 있는데, 이게 오케스트레이터 패턴(orchestrator pattern, 지휘자 한 명이 여러 일꾼에게 일을 나눠 주고 결과를 모으는 구조)이다 — 메인 → 오케스트레이터 서브에이전트 → 말단 일꾼 서브-서브에이전트.다이어그램 설명. 이 그림은 한 단계 중첩을 허용했을 때의 위임 트리와 결과가 거슬러 올라오는 알림 사슬을 보여준다. '메인 에이전트'가 오케스트레이터를 띄우고, 오케스트레이터가 두 말단 일꾼을 나란히 띄운다. 일이 끝나면 말단 일꾼들이 오케스트레이터에게 알리고, 오케스트레이터가 결과를 종합해 메인에게 알리고, 메인이 사용자에게 전달한다. 핵심 패턴은 깊이마다 권한이 다르다는 점이다 — 메인은 항상 띄울 수 있고, 가운데 층은 중첩이 허용될 때만 띄울 수 있으며, 말단은 절대 더 띄우지 못한다. 그래서 무슨 가치인가 — 큰 작업을 "지휘자 한 명 + 병렬 일꾼 여럿"으로 구조화하되, 깊이·자식 수 상한으로 통제 가능한 범위 안에 가둔다.
도구 권한 — 서브에이전트는 세션 도구를 기본으로 못 받는다
세 번째 안전 장치는 도구 표면을 좁게 두는 것이다. 제약 프로파일이 없을 때 서브에이전트는 메시지 도구·세션 도구·시스템 도구를 뺀 모든 도구를 받는다. 즉 사람에게 직접 답을 보내는
message, 그리고 다른 세션을 들여다보거나 또 일꾼을 띄우는sessions_list·sessions_history·sessions_send·sessions_spawn이 기본으로 막혀 있다. 말단 일꾼은 사람에게 직접 말하지 않고, 부모에게 평범한 텍스트로 보고만 한다 — 사람 눈에 보이는 답변은 부모의 정상 전달 정책이 책임진다.다이어그램 설명. 이 그림은 서브에이전트가 깊이와 역할에 따라 어떤 도구를 받는지를 보여준다. 말단 일꾼은 세션 도구와 메시지 도구를 뺀 채 부모에게 텍스트 보고만 할 수 있고, 오케스트레이터는 자식을 거느리기 위해 세션 도구를 추가로 받는다. "권한은 역할에 필요한 만큼만" — 최소 권한 원칙을 도구 표면에 그대로 적용한 구조다. 그래서 무슨 가치인가 — 위임 사슬이 깊어져도 "누가 사람에게 말할 수 있고 누가 일꾼을 띄울 수 있는가"가 명확해, 도구 표면이 좁게 유지된다.
결과 — 무엇이 좋아졌나
서브에이전트와 세션 도구가 들어오면서, 앞서 본 함정들이 이렇게 정리된다.
순진한 단일 에이전트 / 위임 OpenClaw 서브에이전트 설계 큰 작업의 중간 산물이 한 맥락에 누적 → 비대화·오염 하위 작업을 격리 세션으로 떼어 각자 깨끗한 맥락에서 처리 위임 시 부모 대화를 통째로 물려받아 토큰 낭비 기본 격리, 필요할 때만 한 번 fork (토큰·오염 최소) 결과를 폴링으로 기다리며 토큰·턴 낭비 비차단 spawn + 턴을 끝내고 기다리는 푸시 기반 완료 자식이 또 자식을 무한 생성하는 폭주 팬아웃 깊이 2 상한 · 세션당 자식 5 상한 · 연쇄 중단 자식 결과가 검증 없이 사용자·정책에 그대로 반영 런타임 판정 상태 + 부모 검증 + 자식 텍스트는 데이터로 취급 정리하면, OpenClaw의 서브에이전트 도구는 "한 에이전트가 큰 작업을 혼자 떠안아 망가지는 것"을 막는 위임 인프라다. 리서치든 느린 도구 작업이든 독립 구현이든, 하위 작업을 자기 맥락을 가진 격리 세션으로 떼어 병렬·독립으로 돌리고 — 부모는 폴링 없이 결과만 회수해 검증·종합한다. 기본을 격리로 두고, 부모 맥락은 정말 필요할 때만 한 번 빌리고, 깊이와 자식 수에 상한을 박고, 도구 권한을 역할만큼만 주는 이 일관된 설계는 모두 한 방향을 가리킨다 — 위임의 편의를 누리되 통제·안전·비용을 놓지 않는 것. 화려한 단일 에이전트의 추론 능력보다, 큰 작업을 흐트러뜨리지 않고 쪼개어 굴리는 이런 "위임 관리의 기초"가 사실 오래 도는 실용 에이전트의 진짜 전제 조건이다.
이 글은 생성형 AI의 도움을 받아 작성되었습니다. 원본 자료를 기반으로 AI가 초안을 생성하고, 작성자가 검토·편집하였습니다.
'IT' 카테고리의 다른 글
AI로 10배 더 만드는데, 왜 결과를 아무도 안 믿을까 — 이해부채와 이해의 항복 (0) 2026.07.18 외부 시스템마다 도구를 손으로 만들면 안 끝난다 — OpenClaw가 MCP로 남의 도구를 꽂아 쓰는 법 (0) 2026.07.17 텍스트만 뱉는 에이전트는 그림을 못 그린다 — OpenClaw가 미디어 생성을 프로바이더 추상화로 푼 방법 (1) 2026.07.17 지금 시키는 일만 하던 에이전트가 미래의 자기에게 일을 거는 법 — OpenClaw cron 도구 (1) 2026.07.16 세션이 끝나면 다 잊어버리는 AI — OpenClaw가 memory 도구로 의미 기반 기억을 만든 방법 (0) 2026.07.16 에이전트가 답만 뱉던 시절은 끝났다 — OpenClaw가 message 도구로 능동 발신과 채널 액션을 연 방법 (0) 2026.07.15 LLM에게 파일을 통째로 다시 쓰게 두면 안 되는 이유 — OpenClaw가 파일 편집을 4개 도구로 쪼갠 방법 (0) 2026.07.15 AI 에이전트에게 셸을 쥐여 주는 순간 — OpenClaw가 exec 실행과 승인 게이트로 위험을 길들인 방법 (0) 2026.07.15 fetch로는 로그인·동적 페이지를 못 읽는다 — OpenClaw가 격리 브라우저로 푼 방법 (0) 2026.07.14 페이지 한 장 읽자고 브라우저를 통째로 띄울 건가 — OpenClaw가 web_fetch로 본문만 가볍게 긁는 방법 (0) 2026.07.14