AI 에이전트는 어떻게 계획하고 실행하는가, Planning Design과 Managed Agents 정리

·8분 읽기

들어가며

AI 에이전트를 실제 서비스에 붙이기 시작하면 금방 부딪히는 질문이 있다. 에이전트는 어떻게 계획을 세우고, 도구를 호출하고, 긴 작업을 안정적으로 이어가야 할까. 최근 읽은 두 자료, Anthropic의 Scaling Managed Agents: Decoupling the brain from the hands와 Microsoft의 Planning Design 문서를 함께 보면 이 질문에 대한 큰 그림이 꽤 선명해진다.

이 글에서는 두 문서의 핵심을 빠짐없이 정리하면서, 다음 네 가지를 한 번에 이해해보려 한다.

  • 에이전트의 전체 목표를 어떻게 정의하고 하위 작업으로 분해하는가
  • 구조화된 출력이 왜 중요한가
  • 하네스(harness), 세션(session), 샌드박스(sandbox), 도구(tool)는 각각 어떤 역할을 하는가
  • Managed Agents 구조가 왜 더 안정적이고 보안상 유리한가

Microsoft가 설명하는 Planning Design의 핵심

Microsoft 문서는 에이전트 설계의 출발점을 아주 실용적으로 잡는다. 현실의 작업은 대개 한 번에 끝나지 않으므로, 명확한 전체 목표와 잘게 쪼갠 하위 작업이 필요하다는 것이다.

1) 먼저 전체 목표를 명확하게 정의한다

문서의 예시는 단순하다.

3일짜리 여행 일정을 생성하라.

겉보기에는 충분히 명확해 보이지만, 실제로는 더 구체화가 필요하다. 좋은 결과를 얻으려면 에이전트가 무엇을 완성해야 하는지 분명히 알아야 한다. 예를 들어 단순 일정표가 아니라,

  • 항공편 옵션
  • 호텔 추천
  • 이동 수단
  • 현지 활동 추천

까지 포함된 여행 계획인지가 중요하다.

목표가 선명할수록 사람과 에이전트가 같은 결과물을 바라보게 된다.

2) 큰 작업은 하위 작업으로 분해한다

문서에서는 여행 계획을 다음처럼 나눈다.

  • 항공편 예약
  • 호텔 예약
  • 렌터카 예약
  • 개인화

이 접근의 장점은 분명하다.

  • 각 하위 작업을 별도 에이전트에 맡길 수 있다.
  • 문제를 더 작은 단위로 쪼개서 실패를 국소화할 수 있다.
  • 나중에 음식 추천, 현지 액티비티 추천 같은 에이전트를 덧붙이기 쉽다.

즉, Planning Design은 단순한 체크리스트가 아니라 멀티 에이전트 오케스트레이션의 설계 원리에 가깝다.

Defining Goals and Tasks

3) 구조화된 출력은 계획을 실행 가능한 형태로 만든다

문서가 특히 강조하는 부분은 JSON 같은 구조화된 출력이다. 자연어로만 계획을 쓰면 사람은 읽기 쉽지만, 다음 단계 시스템이 받아 처리하기는 불편하다.

예를 들어 플래너 에이전트가 아래처럼 출력한다고 생각해보자.

{
  "main_task": "Plan a family trip from Singapore to Melbourne.",
  "subtasks": [
    {
      "assigned_agent": "flight_booking",
      "task_details": "Book round-trip flights from Singapore to Melbourne."
    },
    {
      "assigned_agent": "hotel_booking",
      "task_details": "Find family-friendly hotels in Melbourne."
    },
    {
      "assigned_agent": "car_rental",
      "task_details": "Arrange a car rental suitable for a family of four in Melbourne."
    },
    {
      "assigned_agent": "activities_booking",
      "task_details": "List family-friendly activities in Melbourne."
    },
    {
      "assigned_agent": "destination_info",
      "task_details": "Provide information about Melbourne as a travel destination."
    }
  ]
}

이 출력이 좋은 이유는 단순하다.

  • 어떤 작업이 있는지 명확하다.
  • 각 작업이 누구에게 할당되는지 드러난다.
  • 후속 시스템이 assigned_agent를 읽고 바로 라우팅할 수 있다.
  • 결과를 다시 합쳐 최종 응답으로 만들기 쉽다.

여기서 플래너는 단지 “좋은 아이디어를 내는 모델”이 아니라, 실행 가능한 계획을 생성하는 오케스트레이터가 된다.

4) 플래너는 적절한 에이전트에게 일을 배분한다

Microsoft 문서의 흐름은 대체로 이렇다.

  1. 사용자 요청이 들어온다.
  2. 플래너가 시스템 프롬프트와 에이전트 목록을 바탕으로 계획을 세운다.
  3. 구조화된 출력으로 하위 작업을 만든다.
  4. 작업 수와 성격에 따라 개별 에이전트 또는 그룹 채팅 관리자에게 넘긴다.
  5. 결과를 다시 요약해 사용자에게 전달한다.

이 설계는 실제 서비스에서 꽤 중요하다. 모든 일을 하나의 거대한 에이전트가 다 하게 만들기보다,

  • 검색 잘하는 에이전트
  • 예약 잘하는 에이전트
  • 요약 잘하는 에이전트
  • 검증 잘하는 에이전트

처럼 역할을 나누는 쪽이 훨씬 운영하기 쉽기 때문이다.

5) 계획은 한 번 세우고 끝나지 않는다

문서의 마지막 핵심은 반복적 계획(Iterative Planning) 이다. 현실에서는 예상치 못한 일이 늘 생긴다.

예를 들면,

  • 항공권 데이터 형식이 예상과 다를 수 있다.
  • 사용자가 “더 이른 비행편이 좋아요”라고 선호를 바꿀 수 있다.
  • 중간 결과에 따라 이후 단계의 조건이 달라질 수 있다.

그래서 좋은 플래너는 고정된 계획표를 찍어내는 존재가 아니라,

  • 이전 계획
  • 현재 상태
  • 사용자 피드백
  • 새로 발견한 제약

을 반영해 부분 재계획할 수 있어야 한다.

이 지점에서 Planning Design은 단순 프롬프트 엔지니어링이 아니라, 상태와 피드백 루프를 가진 시스템 설계로 확장된다.

Anthropic이 설명하는 Managed Agents의 핵심

Anthropic 문서는 Planning Design보다 한 단계 아래, 즉 에이전트를 실제로 오래 돌릴 때 시스템을 어떻게 설계해야 하는가에 초점을 둔다.

제목부터 핵심을 말한다.

Scaling Managed Agents: Decoupling the brain from the hands

한마디로, 두뇌와 손발을 분리하자는 이야기다.

brain, harness, hands, session을 분리해서 생각하기

Anthropic은 에이전트를 다음 구성요소로 나눠 본다.

  • brain: Claude와 그 추론 능력
  • harness: Claude와 도구 사이를 연결하는 실행 루프
  • hands: 실제 작업을 수행하는 sandbox, MCP, 각종 도구
  • session: 세션 동안 벌어진 모든 일을 남기는 durable log

이 분해가 중요한 이유는, 예전처럼 모든 것을 하나의 컨테이너 안에 넣으면 운영상 문제가 커지기 때문이다.

초기 방식의 문제, 모든 것을 한 컨테이너에 넣으면 생기는 일

처음에는 세션, 하네스, 샌드박스를 한 컨테이너에 넣는 구조를 시도했다고 한다. 이 방식은 구현이 단순해 보인다.

  • 파일 편집이 쉽다.
  • 서비스 경계가 적다.
  • 로컬 호출처럼 빠르게 붙일 수 있다.

하지만 곧 “pet server” 문제가 생긴다.

  • 컨테이너가 죽으면 세션이 함께 날아간다.
  • 멈춘 세션을 살리려면 사람이 직접 간호해야 한다.
  • 장애 원인이 이벤트 스트림 문제인지, 하네스 문제인지, 컨테이너 문제인지 분간하기 어렵다.
  • 고객의 VPC 안 자원과 연결하기도 불편하다.

즉, 처음엔 단순했지만 나중에는 확장성과 복구성, 보안성의 발목을 잡는다.

하네스는 무엇을 하나

여기서 하네스는 자주 헷갈리는 개념인데, Anthropic 문맥에서 하네스는 모델이 직접 바깥세상과 접촉하지 않도록 중개하는 실행 레이어에 가깝다.

정확히 말하면,

  • 무슨 도구를 쓸지 결정하는 것은 Claude다.
  • 그 도구 호출을 실제로 실행하는 것은 harness다.

즉, Claude가 “이 도구를 호출하자”라고 판단하면, 하네스가 그 tool call을 받아 실제 sandbox, MCP 서버, API, 컨테이너로 전달하고, 결과를 다시 Claude에게 돌려준다.

그래서 execute(name, input) -> string 같은 인터페이스는 보통 하네스가 다루는 호출 계층으로 이해하면 맞다.

정리하면,

  • Claude는 의사결정 주체
  • Harness는 중개와 실행 주체
  • Tool/Sandbox는 실제 손발

이다.

왜 brain과 hands를 분리해야 하나

Anthropic이 제시한 핵심 해결책은 brain(Claude + harness)과 hands(실행 환경) 그리고 session(기록)을 독립된 인터페이스로 분리하는 것이다.

이렇게 되면 어떤 일이 가능해질까.

1) 컨테이너가 죽어도 세션이 안 죽는다

세션 로그가 하네스 밖에 있기 때문에, 하네스나 샌드박스가 죽어도 다시 이어붙일 수 있다.

  • 새 하네스를 띄운다.
  • getSession(id) 같은 방식으로 이벤트 로그를 읽는다.
  • 마지막 이벤트부터 다시 이어간다.

즉, 세션은 프로세스보다 오래 살아남는 상태 저장소가 된다.

2) 샌드박스는 필요할 때만 붙인다

모든 세션이 항상 샌드박스를 필요로 하지는 않는다. 그런데 이전 구조에서는 세션이 시작될 때마다 컨테이너 준비 비용을 먼저 치러야 했다.

Anthropic은 분리 구조를 통해,

  • 우선 추론을 시작하고
  • 정말 필요할 때만 sandbox를 tool call로 붙이는 방식

으로 바꿨다. 그 결과 TTFT(Time to First Token) 가 크게 줄었다고 설명한다.

즉, 첫 응답까지의 체감 속도가 더 빨라진다.

3) 고객 인프라와 연결하기 쉬워진다

하네스가 컨테이너 안에 있으면, 에이전트가 고객 VPC 안의 리소스를 다루기 어렵다. 하지만 하네스와 hands가 분리되면 각 hand를 외부 도구처럼 연결할 수 있다.

이 말은 곧,

  • 어떤 hand는 컨테이너일 수 있고
  • 어떤 hand는 외부 API일 수 있고
  • 어떤 hand는 MCP 서버일 수 있고
  • 어떤 hand는 심지어 다른 실행 환경일 수도 있다는 뜻이다.

Anthropic은 이를 many brains, many hands로 표현한다.

session은 단순한 context window가 아니다

이 부분이 꽤 중요하다. Anthropic은 세션은 모델의 context window와 같은 것이 아니다라고 분명히 말한다.

긴 작업을 하다 보면 context window는 언젠가 한계에 도달한다. 이를 해결하려고 보통 다음 같은 방법을 쓴다.

  • 요약(compaction)
  • trimming
  • memory tool에 기록

그런데 이 방식은 모두 어느 정도 무엇을 버릴지 결정하는 비가역적 선택을 포함한다. 나중에 필요했던 정보를 너무 일찍 잃을 수 있다는 뜻이다.

Managed Agents에서는 session이 context window 밖에 존재하는 외부 상태 객체처럼 동작한다. 필요할 때 getEvents() 같은 방식으로 이벤트를 다시 가져와 읽을 수 있다.

이 구조의 장점은,

  • 과거 이벤트를 위치 기준으로 다시 읽을 수 있고
  • 특정 시점 직전 몇 개 이벤트를 되감아 볼 수 있고
  • 필요한 부분만 잘라 Claude의 현재 context에 넣을 수 있다는 점이다.

즉, session은 단순 로그가 아니라 재조회 가능한 기억 저장소다.

보안 관점에서 왜 더 나은가

Anthropic은 보안 설명도 꽤 직설적이다. 예전의 결합 구조에서는 Claude가 생성한 코드가 자격증명과 같은 컨테이너에서 실행될 수 있었다. 이 경우 프롬프트 인젝션이 성공하면 모델이 자기 환경 변수나 토큰을 읽는 방향으로 유도될 수 있다.

Managed Agents 구조에서는 이를 줄이기 위해 credential이 sandbox 안에 직접 노출되지 않도록 구조적으로 분리한다.

예를 들어,

  • Git 토큰은 저장소 초기화 시 remote 설정에만 연결하고 에이전트가 직접 만지지 않게 하거나
  • OAuth 토큰은 vault에 저장하고 MCP 프록시가 세션 토큰으로 대신 조회해서 호출하거나
  • 하네스 자체도 credential을 직접 들고 있지 않게 설계한다.

핵심은 “모델이 이 토큰으로 무엇을 못 하게 막을까”가 아니라, 애초에 토큰에 닿지 못하게 구조를 짠다는 데 있다.

이건 점점 더 강해지는 모델 시대에는 특히 중요한 방향이다.

Planning Design과 Managed Agents를 함께 보면 보이는 것

이 두 문서는 서로 다른 층위를 다루지만 아주 잘 맞물린다.

Microsoft 문서가 답하는 것

  • 목표를 어떻게 정의할까
  • 작업을 어떻게 분해할까
  • 어떤 에이전트에게 무엇을 맡길까
  • 결과가 바뀌면 어떻게 재계획할까

즉, 인지적 오케스트레이션에 가깝다.

Anthropic 문서가 답하는 것

  • 긴 세션을 어떻게 복구 가능하게 만들까
  • 도구 실행을 어떻게 안전하게 중개할까
  • 샌드박스를 언제 붙이고 어떻게 분리할까
  • 세션 상태를 어떻게 durable하게 유지할까

즉, 운영 시스템 설계에 가깝다.

둘을 합치면 꽤 강한 그림이 나온다.

  • 플래너가 목표를 하위 작업으로 나눈다.
  • 각 작업은 적절한 에이전트 또는 도구로 라우팅된다.
  • 하네스는 이 호출을 실제 인프라에 연결한다.
  • 세션은 모든 이벤트를 내구성 있게 저장한다.
  • 사용자 피드백이나 실패가 생기면 일부만 재계획한다.
  • credential은 sandbox 밖에서 관리한다.

이렇게 보면 현대적인 에이전트 시스템은 “좋은 프롬프트 하나”가 아니라,

  • 계획 계층
  • 실행 계층
  • 상태 계층
  • 보안 계층

이 분리된 시스템 아키텍처에 더 가깝다.

하네스는 도구를 직접 호출하나, Claude가 호출하나

이 질문은 실제로 많이 헷갈린다. 정리하면 다음이 가장 정확하다.

짧은 답

도구 사용을 결정하는 것은 Claude이고, 실제 호출을 수행하는 것은 harness다.

흐름으로 보면

  1. Claude가 현재 목표와 상태를 보고 “어떤 도구가 필요하다”고 판단한다.
  2. Claude는 tool call 형식의 출력을 만든다.
  3. Harness가 그 호출을 받아 실제 도구나 샌드박스에 전달한다.
  4. 실행 결과를 Claude에게 돌려준다.
  5. Claude는 결과를 해석하고 다음 행동을 정한다.

즉, 모델이 모든 것을 직접 실행하는 것처럼 보일 수 있지만, 실제 시스템에서는 하네스가 실행을 책임지는 중개층이다.

실무적으로 얻을 수 있는 설계 원칙

이 두 문서를 함께 읽고 나면, 에이전트를 만들 때 최소한 아래 원칙은 가져가는 게 좋다.

1) 목표를 먼저 쓰고, 성공 기준을 분명히 하자

“좋은 답변을 해줘”보다

  • 어떤 산출물이 필요한지
  • 어떤 제약이 있는지
  • 무엇이 성공인지

를 먼저 적는 편이 훨씬 낫다.

2) 플래너 출력은 자연어만 쓰지 말고 구조화하자

JSON, 스키마, enum, assigned_agent 같은 구조가 있으면 후속 자동화가 쉬워진다.

3) 긴 작업은 상태를 외부에 저장하자

컨텍스트 윈도우만 믿지 말고,

  • 이벤트 로그
  • 작업 상태 저장소
  • 체크포인트
  • 메모리 파일

같은 durable state를 두는 편이 낫다.

4) 도구 실행은 모델과 분리하자

모델이 직접 credential과 실행 환경에 닿는 구조는 장기적으로 위험하다. 실행은 하네스, 권한은 프록시나 vault, 상태는 세션 로그처럼 역할을 나누는 편이 안전하다.

5) 재계획은 예외가 아니라 기본 기능으로 생각하자

실제 작업은 항상 바뀐다. 좋은 시스템은 한 번 세운 계획을 고집하지 않고, 중간 결과와 사용자 피드백을 반영해 유연하게 바꾼다.

마무리

Microsoft의 Planning Design은 에이전트가 무엇을 할지를 더 잘 정하게 만들어준다. Anthropic의 Managed Agents는 그 에이전트가 어떻게 오래, 안전하게, 복구 가능하게 일할지를 설명해준다.

둘을 합쳐 보면 오늘날의 에이전트 설계는 이렇게 요약할 수 있다.

  • 목표를 명확히 정의하고
  • 작업을 하위 단위로 쪼개고
  • 구조화된 출력으로 라우팅 가능하게 만들고
  • 하네스로 도구 실행을 중개하고
  • 세션 로그로 상태를 유지하며
  • 샌드박스와 credential을 분리해 보안을 확보하고
  • 필요할 때 재계획한다

에이전트는 점점 “프롬프트를 잘 쓰는 기술”보다 “분리된 계층을 가진 시스템을 잘 설계하는 기술”에 가까워지고 있다. 지금 에이전트 아키텍처를 고민하고 있다면, 이 두 문서는 그 큰 흐름을 이해하는 데 꽤 좋은 출발점이다.

참고 자료

  • Anthropic Engineering, Scaling Managed Agents: Decoupling the brain from the hands
  • Microsoft, AI Agents for Beginners - Planning Design
  • Microsoft Research, Magentic One - A Generalist Multi-Agent System for Solving Complex Tasks