번역 안내

아래는 Anthropic Engineering의 “Scaling Managed Agents: Decoupling the brain from the hands”(2026-04-08) 원문을 문단 구조와 코드 인터페이스를 최대한 유지해 옮긴 전체 한국어 번역이다.[1]

제품·성능·보안 설계에 관한 수치는 Anthropic이 이 글에서 보고한 주장으로, 별도 독립 검증한 결과가 아니다.[1]

본문 번역

Claude Managed Agents를 시작하려면 공식 문서를 참고하라.[1]

Anthropic Engineering Blog에서는 효과적인 에이전트를 구축하고, 장기 실행 작업을 위한 하네스를 설계하는 방법을 계속 다뤄 왔다.[1]

이 작업들을 관통하는 공통 주제는 하네스가 Claude가 스스로 하지 못하는 일을 가정한다는 점이다.[1]

그러나 모델이 발전하면 그 가정은 낡을 수 있으므로 자주 다시 질문해야 한다.[1]

한 가지 예를 들면, 이전 작업에서 Claude Sonnet 4.5는 컨텍스트 한계가 가까워지는 것을 감지하면 작업을 너무 일찍 마무리하는 모습을 보였다.[1]

이를 때때로 “컨텍스트 불안(context anxiety)”이라고 부른다.[1]

우리는 하네스에 컨텍스트 리셋을 추가해 이 문제를 해결했다.[1]

하지만 같은 하네스를 Claude Opus 4.5에 적용했을 때는 그런 행동이 사라져 있었다.[1]

리셋은 오히려 불필요한 짐이 된 것이다.[1]

하네스는 앞으로도 계속 진화할 것이다.[1]

그래서 우리는 Managed Agents를 만들었다.[1]

Managed Agents는 특정 구현, 현재 우리가 운영하는 구현까지도 수명 이상으로 유지될 수 있도록 설계한 작은 인터페이스 집합을 통해, 장기 실행 에이전트를 사용자를 대신해 실행하는 Claude Platform의 호스팅 서비스다.[1]

Managed Agents를 만드는 일은 컴퓨팅의 오래된 문제, 즉 “아직 생각해내지 못한 프로그램(programs as yet unthought of)”을 위한 시스템을 어떻게 설계할 것인가를 해결하는 일이었다.[1]

수십 년 전 운영체제는 하드웨어를 process, file 같은 추상화로 가상화해 아직 존재하지 않는 프로그램에도 충분히 일반적인 기반을 만들었다.[1]

추상화는 하드웨어보다 오래 살아남았다.[1]

read() 명령은 1970년대의 디스크 팩에 접근하는지 현대의 SSD에 접근하는지 신경 쓰지 않는다.[1]

아래의 구현이 자유롭게 바뀌는 동안 위의 추상화는 안정적으로 남았다.[1]

Managed Agents도 같은 패턴을 따른다.[1]

우리는 에이전트의 구성요소를 가상화했다.[1]

세션은 일어난 모든 일을 기록하는 추가 전용(append-only) 로그이고, 하네스는 Claude를 호출하며 Claude의 도구 호출을 적절한 인프라로 라우팅하는 루프이며, 샌드박스는 Claude가 코드를 실행하고 파일을 편집할 수 있는 실행 환경이다.[1]

이 구조에서는 서로를 방해하지 않고 각 구성요소의 구현을 교체할 수 있다.[1]

우리는 인터페이스의 형태에는 의견을 갖지만, 그 뒤에서 무엇이 실행되는지에는 특정한 의견을 갖지 않는다.[1]

펫을 만들지 말라

처음에는 모든 에이전트 구성요소를 하나의 컨테이너에 넣었다.[1]

따라서 세션·에이전트 하네스·샌드박스가 같은 환경을 공유했다.[1]

파일 편집이 직접 syscall로 이루어지고 설계해야 할 서비스 경계가 없다는 장점이 있었다.[1]

하지만 모든 것을 하나의 컨테이너에 결합하면서 우리는 오래된 인프라 문제에 부딪혔다.[1]

바로 “펫(pet)”을 만든 것이다.[1]

펫과 가축(cattle)의 비유에서 펫은 이름을 붙이고 손으로 돌보며 잃을 수 없는 개별 인스턴스이고, 가축은 서로 대체할 수 있다.[1]

우리 경우에는 서버가 펫이 되었다.[1]

컨테이너가 실패하면 세션도 잃었다.[1]

컨테이너가 응답하지 않으면 다시 건강하게 만들기 위해 돌봐야 했다.[1]

컨테이너를 간호한다는 것은 응답하지 않는 정지 세션을 디버깅한다는 뜻이었다.[1]

우리가 안으로 들어갈 수 있는 유일한 창은 WebSocket 이벤트 스트림이었지만, 그 스트림만으로는 실패가 어디에서 발생했는지 알 수 없었다.[1]

하네스의 버그, 이벤트 스트림의 패킷 손실, 컨테이너 오프라인이 모두 같은 모습으로 보였다.[1]

무엇이 잘못됐는지 확인하려면 엔지니어가 컨테이너 안에서 셸을 열어야 했는데, 그 컨테이너에는 사용자 데이터도 들어 있는 경우가 많았으므로 사실상 디버깅할 수 없는 구조였다.[1]

두 번째 문제는 하네스가 Claude가 작업하는 대상이 반드시 자신과 같은 컨테이너 안에 있다고 가정했다는 점이다.[1]

고객이 자신의 가상 사설 클라우드(VPC)에 Claude를 연결하고 싶어 하면 우리 네트워크와 피어링하거나, 우리 하네스를 고객 환경에서 실행해야 했다.[1]

하네스에 내장된 가정이 다른 인프라에 연결하려는 순간 문제가 된 것이다.[1]

뇌와 손을 분리하라

우리가 도달한 해법은 “뇌”(Claude와 그 하네스)라고 생각하던 것을 행동을 수행하는 “손”(샌드박스와 도구) 및 “세션”(세션 이벤트 로그) 모두에서 분리하는 것이었다.[1]

각각은 다른 구성요소에 대해 거의 가정하지 않는 인터페이스가 되었고, 각자 독립적으로 실패하거나 교체될 수 있게 됐다.[1]

하네스가 컨테이너를 떠나다. 뇌와 손을 분리하자 하네스는 더 이상 컨테이너 안에 살지 않게 됐다.[1]

하네스는 컨테이너를 다른 도구와 똑같이 호출했다.[1]

execute(name, input) → string이다.[1]

컨테이너는 가축이 됐다.[1]

컨테이너가 죽으면 하네스는 그 실패를 도구 호출 오류로 받아 Claude에게 전달한다.[1]

Claude가 재시도하기로 하면 provision({resources})라는 표준 레시피로 새 컨테이너를 초기화할 수 있다.[1]

더 이상 실패한 컨테이너를 간호해 복구할 필요가 없다.[1]

하네스 실패에서 복구하기. 하네스도 가축이 됐다.[1]

세션 로그가 하네스 바깥에 있으므로 하네스 안의 어떤 것도 충돌 이후 살아남을 필요가 없다.[1]

하네스 하나가 실패하면 새 하네스를 wake(sessionId)로 다시 깨우고, getSession(id)으로 이벤트 로그를 가져와 마지막 이벤트부터 재개할 수 있다.[1]

에이전트 루프가 실행되는 동안 하네스는 emitEvent(id, event)로 세션에 기록해 이벤트의 내구성 있는 기록을 유지한다.[1]

보안 경계. 결합된 설계에서는 Claude가 생성한 신뢰할 수 없는 코드가 자격 증명과 같은 컨테이너에서 실행됐다.[1]

따라서 프롬프트 인젝션은 Claude가 자신의 환경을 읽도록 설득하기만 하면 됐다.[1]

공격자가 토큰을 얻으면 새롭고 제한 없는 세션을 만들고 그 세션에 작업을 위임할 수 있다.[1]

권한 범위를 좁히는 것은 명백한 완화책이지만, 이는 제한된 토큰으로 Claude가 무엇을 하지 못할 것인지에 대한 가정을 다시 코드에 넣는 일이다.[1]

Claude는 점점 더 똑똑해지고 있다.[1]

구조적 해결책은 Claude가 생성한 코드가 실행되는 샌드박스에서 토큰에 절대 접근할 수 없게 만드는 것이었다.[1]

우리는 이를 보장하기 위해 두 가지 패턴을 사용했다.[1]

인증 정보를 리소스에 묶거나 샌드박스 바깥의 vault에 보관할 수 있다.[1]

Git의 경우 각 저장소의 액세스 토큰을 사용해 샌드박스 초기화 중 저장소를 clone하고, 로컬 git remote에 연결한다.[1]

그러면 에이전트가 토큰을 직접 다루지 않아도 샌드박스 안에서 git pushgit pull을 실행할 수 있다.[1]

사용자 정의 도구에는 MCP를 지원하고 OAuth 토큰을 보안 vault에 저장한다.[1]

Claude는 전용 프록시를 통해 MCP 도구를 호출한다.[1]

프록시는 세션과 연결된 토큰을 받아 vault에서 해당 자격 증명을 가져와 외부 서비스에 호출한다.[1]

하네스는 어떤 자격 증명도 알 필요가 없다.[1]

세션은 Claude의 컨텍스트 윈도우가 아니다

장기 실행 작업은 Claude의 컨텍스트 윈도우 길이를 자주 초과한다.[1]

이를 해결하는 표준적인 방법은 무엇을 남길지에 대해 되돌릴 수 없는 결정을 내리는 것과 관련된다.[1]

우리는 이전의 컨텍스트 엔지니어링 작업에서 이런 기법을 탐구했다.[1]

예를 들어 컴팩션은 Claude가 컨텍스트 윈도우의 요약을 저장하도록 하고, 메모리 도구는 Claude가 컨텍스트를 파일에 써서 세션을 넘어 학습하도록 한다.[1]

여기에 오래된 도구 결과나 사고 블록 같은 토큰을 선택적으로 제거하는 컨텍스트 트리밍을 결합할 수도 있다.[1]

하지만 컨텍스트를 선택적으로 보존하거나 버리는 되돌릴 수 없는 결정은 실패로 이어질 수 있다.[1]

미래의 어느 턴에서 어떤 토큰이 필요할지 알기 어렵기 때문이다.[1]

컴팩션 단계에서 메시지가 변환되면 하네스는 압축된 메시지를 Claude의 컨텍스트 윈도우에서 제거한다.[1]

그 메시지가 저장돼 있지 않다면 다시 가져올 수 없다.[1]

이전 연구에서는 컨텍스트를 윈도우 바깥에 존재하는 객체로 저장하는 방식으로 이 문제를 다뤘다.[1]

예를 들어 컨텍스트를 REPL 안의 객체로 두고, LLM 프로그램이 코드를 작성해 컨텍스트를 필터링하거나 잘라서 접근하게 할 수 있다.[1]

Managed Agents에서 세션은 같은 이점을 제공한다.[1]

세션은 Claude의 컨텍스트 윈도우 바깥에 존재하는 컨텍스트 객체 역할을 한다.[1]

다만 샌드박스나 REPL 내부에 저장하는 대신, 컨텍스트를 세션 로그에 내구성 있게 저장한다.[1]

getEvents() 인터페이스를 사용하면 뇌가 이벤트 스트림의 위치 기반 구간을 선택해 컨텍스트를 조회할 수 있다.[1]

마지막으로 읽던 곳에서 다시 시작하거나, 특정 시점 직전의 이벤트를 몇 개 되감아 맥락을 확인하거나, 특정 행동 직전의 컨텍스트를 다시 읽는 등 유연하게 사용할 수 있다.[1]

가져온 이벤트는 Claude의 컨텍스트 윈도우에 전달되기 전에 하네스에서 변환할 수도 있다.[1]

높은 프롬프트 캐시 적중률을 위한 컨텍스트 구성과 컨텍스트 엔지니어링을 포함해, 하네스가 인코딩하는 어떤 변환도 가능하다.[1]

우리는 복구 가능한 컨텍스트 저장을 세션에, 임의의 컨텍스트 관리를 하네스에 분리했다.[1]

미래 모델에 어떤 컨텍스트 엔지니어링이 필요할지 예측할 수 없기 때문이다.[1]

인터페이스는 컨텍스트 관리를 하네스로 밀어내고, 세션이 내구성 있게 유지되며 조회 가능하다는 것만 보장한다.[1]

많은 뇌, 많은 손

많은 뇌. 뇌와 손을 분리하자 초기 고객 불만 중 하나가 해결됐다.[1]

팀이 자신의 VPC 안에 있는 리소스를 대상으로 Claude를 작업시키고 싶을 때, 하네스를 담은 컨테이너가 모든 리소스가 옆에 있다고 가정했기 때문에 기존에는 우리 네트워크와 피어링하는 수밖에 없었다.[1]

하네스가 컨테이너 밖으로 나오자 이 가정이 사라졌다.[1]

같은 변화는 성능에도 이득을 줬다.[1]

처음에 뇌를 컨테이너 안에 넣었을 때는 많은 뇌를 만들려면 그만큼 많은 컨테이너가 필요했다.[1]

각 뇌는 컨테이너가 프로비저닝될 때까지 추론을 시작할 수 없었고, 모든 세션이 컨테이너 설정 비용을 처음부터 전부 지불했다.[1]

샌드박스를 전혀 사용하지 않을 세션까지도 저장소를 clone하고 프로세스를 부팅하고 서버에서 대기 중인 이벤트를 가져와야 했다.[1]

이렇게 낭비되는 시간은 TTFT(time-to-first-token)로 표현된다.[1]

TTFT는 세션이 작업을 수락한 시점부터 첫 응답 토큰을 생성할 때까지 기다리는 시간을 측정한다.[1]

TTFT는 사용자가 가장 직접적으로 느끼는 지연 시간이다.[1]

뇌와 손을 분리하면 컨테이너는 필요한 경우에만 뇌가 도구 호출 (execute(name, input) → string)로 프로비저닝한다.[1]

따라서 당장 컨테이너가 필요하지 않은 세션은 컨테이너를 기다리지 않는다.[1]

오케스트레이션 계층이 세션 로그에서 대기 중인 이벤트를 가져오는 즉시 추론을 시작할 수 있다.[1]

Anthropic은 이 아키텍처를 사용해 p50 TTFT가 약 60%, p95가 90% 이상 감소했다고 보고한다.[1]

많은 뇌로 확장하려면 상태 없는 하네스를 많이 시작하고, 필요한 경우에만 손에 연결하면 됐다.[1]

많은 손. 우리는 각 뇌를 여러 손에 연결할 수 있기를 원했다.[1]

실제로 이는 Claude가 여러 실행 환경을 추론하고 작업을 어디로 보낼지 결정해야 한다는 뜻이다.[1]

하나의 셸에서 작업하는 것보다 더 어려운 인지 과제다.[1]

우리는 초기 모델이 이 일을 수행할 수 없었기 때문에 처음에는 뇌를 하나의 컨테이너에 넣었다.[1]

하지만 지능이 향상되자 단일 컨테이너가 오히려 한계가 됐다.[1]

컨테이너가 실패하면 뇌가 연결하고 있던 모든 손의 상태를 잃었기 때문이다.[1]

뇌와 손을 분리하면 각 손이 execute(name, input) → string이라는 도구가 된다.[1]

이름과 입력이 들어가고 문자열이 반환된다.[1]

이 인터페이스는 모든 사용자 정의 도구, 모든 MCP 서버, 그리고 Anthropic 자체 도구를 지원한다.[1]

하네스는 손이 컨테이너인지, 휴대전화인지, 포켓몬 에뮬레이터인지 알 필요가 없다.[1]

어떤 손도 특정 뇌에 결합돼 있지 않으므로 뇌가 서로 손을 넘겨줄 수도 있다.[1]

결론

우리가 마주한 과제는 “아직 생각해내지 못한 프로그램”을 위한 시스템을 어떻게 설계할 것인가라는 오래된 문제다.[1]

운영체제는 아직 존재하지 않는 프로그램에도 충분히 일반적인 추상화로 하드웨어를 가상화했기 때문에 수십 년 동안 지속됐다.[1]

Managed Agents에서도 Claude를 둘러싼 미래의 하네스·샌드박스·기타 구성요소를 수용할 수 있는 시스템을 설계하려 했다.[1]

Managed Agents는 같은 정신을 가진 메타-하네스다.[1]

Claude가 미래에 필요로 할 구체적인 하네스에 대해서는 특정한 의견을 갖지 않는다.[1]

대신 여러 하네스를 허용하는 일반적인 인터페이스를 가진 시스템이다.[1]

예를 들어 Claude Code는 우리가 다양한 작업에서 널리 사용하는 훌륭한 하네스다.[1]

특정 도메인에 특화된 에이전트 하네스가 좁은 영역에서 뛰어난 성능을 보인다는 것도 이미 확인했다.[1]

Managed Agents는 이런 하네스를 모두 수용하며, 시간이 지나 Claude의 지능 변화에 맞춰갈 수 있다.[1]

메타-하네스 설계는 Claude 주변의 인터페이스에 대해서는 의견을 갖는다.[1]

Claude는 상태를 조작하는 능력(세션)과 계산을 수행하는 능력(샌드박스)이 필요할 것이라고 예상한다.[1]

또한 많은 뇌와 많은 손으로 확장할 수 있어야 한다고 예상한다.[1]

우리는 이를 장기간 안정적이고 안전하게 실행할 수 있도록 인터페이스를 설계했다.[1]

그러나 Claude가 필요로 할 뇌와 손의 수 또는 위치에 대해서는 어떤 가정도 하지 않는다.[1]

감사의 말

글: Lance Martin, Gabe Cemaj, Michael Cohen.[1]

이 주제에 관해 유익한 대화를 나눠 준 Nodir Turakulov와 Jeremy Fox에게 감사한다.[1]

기여해 준 Agents API 팀과 Jake Eaton에게 특별히 감사한다.[1]

관련 링크

Sources

[1] https://www.anthropic.com/engineering/managed-agents — Scaling Managed Agents: Decoupling the brain from the hands