에이전트가 샌드박스에 연결되는 두 가지 패턴
TMThttps://www.langchain.com/blog/the-two-patterns-by-which-agents-connect-sandboxes
요약:
- 점점 더 많은 에이전트가 작업 공간을 필요로 합니다. 코드를 실행하고 패키지를 설치하고 파일에 접근할 수 있는 컴퓨터입니다. 샌드박스가 이것을 제공합니다.
- 에이전트와 샌드박스를 통합하는 아키텍처 패턴은 두 가지입니다.
- 패턴 1(샌드박스 안의 에이전트(Agent IN Sandbox)): 에이전트가 샌드박스 안에서 돌아가고, 네트워크를 통해 에이전트와 통신합니다. 장점은 로컬 개발 환경과 똑같은 모습이 되고 에이전트와 환경이 강하게 결합된다는 점입니다.
- 패턴 2(도구로서의 샌드박스(Sandbox as Tool)): 에이전트가 로컬이나 여러분의 서버에서 돌아가고, 실행이 필요할 때 샌드박스를 원격으로 호출합니다. 장점은 에이전트 로직을 쉽게 업데이트할 수 있고, API 키가 샌드박스 밖에 머물고, 관심사가 더 깔끔하게 분리된다는 점입니다.
- deepagents는 두 패턴 모두를 간단한 설정으로 지원합니다
작업 공간을 필요로 하는 에이전트가 점점 늘고 있습니다. 코드를 실행하고 패키지를 설치하고 파일에 접근할 수 있는 컴퓨터 말입니다. 그 작업 공간은 에이전트가 여러분의 자격 증명과 파일, 네트워크에 접근할 수 없도록 격리되어 있어야 합니다. 샌드박스는 에이전트의 환경과 여러분의 호스트 시스템 사이에 경계를 만들어 이 격리를 제공합니다. 이런 에이전트를 만드는 팀이 마주하는 질문은 샌드박스를 쓸지 말지가 아니라, 그것을 자기 에이전트 아키텍처에 어떻게 통합할지입니다.
에이전트가 어디에서 돌아가는지에 따라 흔히 쓰이는 패턴이 두 가지 있습니다. 샌드박스 안이거나 샌드박스 밖입니다. 두 패턴은 장점과 트레이드오프가 서로 다릅니다.
참고로 이 글은 에이전트에게 온전한 '컴퓨터'를 주는 샌드박스, 즉 도커 컨테이너나 VM처럼 완전한 실행 환경을 다룹니다. bubblewrap 같은 프로세스 수준 샌드박스나 Pyodide 같은 언어 수준 샌드박스는 다루지 않습니다.
패턴 1: 에이전트가 샌드박스 안에서 돌아간다(Agent Runs IN Sandbox)
이 패턴에서는 에이전트가 샌드박스 안에서 돌아갑니다. 여러분은 네트워크를 통해 에이전트와 통신합니다.
실제로는 이런 모습입니다.
에이전트 프레임워크를 미리 설치한 도커나 VM 이미지를 만들고, 그것을 샌드박스 안에서 실행한 뒤, 밖에서 접속해 메시지를 보냅니다. 에이전트는 API 엔드포인트(보통 HTTP나 WebSocket)를 노출하고, 여러분의 애플리케이션은 샌드박스 경계를 넘어 그 에이전트와 통신합니다.
장점
이 패턴은 로컬 개발과 아주 비슷합니다. 로컬 터미널에서 deepagents를 실행한다면 샌드박스 안에서도 같은 명령을 실행하게 됩니다. 에이전트는 파일 시스템에 직접 접근할 수 있고 자기 환경을 수정할 수 있습니다. 에이전트가 특정 라이브러리와 상호작용해야 하거나 복잡한 환경 상태를 유지해야 하는 경우처럼, 에이전트와 실행 환경이 강하게 결합되어 있을 때 유용합니다.
트레이드오프
샌드박스 경계를 넘는 통신에는 인프라가 필요합니다. 이것을 SDK에서 처리해 주는 제공자도 있습니다. 예를 들어 OpenCode 같은 에이전트는 샌드박스 안에서 서버를 돌리고, E2B 같은 제공자는 이를 깔끔한 API로 노출해 줄 수 있습니다. 여러분이 쓰는 제공자가 이를 제공하지 않는다면, 세션 관리와 오류 처리를 포함한 WebSocket 또는 HTTP 계층을 직접 만들어야 합니다.
에이전트가 추론 호출을 할 수 있어야 하므로 API 키가 샌드박스 안에 있어야 합니다. 그래서 샌드박스가 침해될 경우 보안 위험이 생길 수 있습니다. 격리 기술 자체의 취약점을 통해서든, 자격 증명을 빼내는 프롬프트 인젝션 공격을 통해서든 마찬가지입니다. 참고로 E2B와 Runloop 같은 제공자가 시크릿 볼트 기능을 만들고 있고, 이것이 이 문제를 해결해 줍니다.
업데이트하려면 컨테이너 이미지를 다시 빌드해 재배포해야 하므로, 개발 중 반복 주기가 느려질 수 있습니다.
또 다른 단점은 에이전트가 활성화되기 전에 샌드박스를 먼저 다시 시작해야 한다는 점인데, 여기에는 추가 로직이 필요한 경우가 많습니다.
에이전트의 지식 재산(IP)을 보호하는 데 신경 쓰는 분들에게는, 에이전트가 샌드박스 안에서 돌아갈 때 에이전트의 코드와 프롬프트 전체를 빼내기가 훨씬 쉬워진다는 점이 문제가 됩니다.
Witan Labs의 Nuno Campos는 또 다른 보안 위험을 지적합니다. "샌드박스 안의 에이전트 방식이 갖는 또 하나의 단점은, 사실상 에이전트의 어떤 부분도 bash 도구보다 많은 권한을 가질 수 없다는 점이라고 봅니다. 예를 들어 bash 도구와 함께 웹 검색이나 웹 가져오기를 할 수 있는 도구를 가진 에이전트를 만들고 싶다고 해 보죠. 그러면 LLM이 생성한 모든 코드가 웹 가져오기를 무제한으로 할 수 있게 됩니다. 큰 보안 위험이죠. 도구로서의 샌드박스 방식이라면 LLM이 생성한 코드에 주는 권한보다 많은 권한을 가진 도구를 손쉽게 둘 수 있습니다. 많은 에이전트에게 아주 유용하게 들릴 겁니다. 보안 경계가 에이전트 전체가 아니라 bash 도구를 둘러싸고 있기 때문입니다."
패턴 2: 도구로서의 샌드박스(Sandbox as Tool)
이 패턴에서는 에이전트가 여러분의 머신이나 서버에서 돌아갑니다. 코드를 실행해야 할 때 API를 통해 원격 샌드박스를 호출합니다.
실제로는 이런 모습입니다.
에이전트는 로컬이나 여러분의 서버에서 돌아가고, 실행해야 하는 코드를 생성하면 샌드박스 제공자의 API를 호출합니다. E2B나 Modal, Daytona, Runloop 같은 곳입니다. 통신에 관한 세부 사항은 제공자의 SDK가 모두 처리합니다. 에이전트가 보기에 샌드박스는 그저 또 하나의 도구일 뿐입니다.
장점
컨테이너 이미지를 다시 빌드하지 않고 에이전트 코드를 즉시 업데이트할 수 있어서 개발 중 반복 속도가 빨라집니다. API 키는 샌드박스 밖에 머물고, 격리된 곳에서 일어나는 일은 실행뿐입니다. 덕분에 관심사가 더 깔끔하게 분리됩니다. 에이전트의 상태, 즉 대화 이력과 추론 사슬, 메모리는 에이전트가 돌아가는 곳에 샌드박스와 분리되어 남아 있습니다. 그래서 샌드박스에 장애가 생겨도 에이전트의 상태를 잃지 않고, 에이전트의 핵심 로직에 영향을 주지 않으면서 샌드박스 백엔드를 바꿀 수 있습니다.
E2B의 Tomas Beran이 짚어 준 이 방식의 다른 장점 두 가지는 다음과 같습니다.
- 여러 원격 샌드박스에서 작업을 병렬로 돌릴 수 있는 선택지가 생깁니다.
- 프로세스가 돌아가는 시간 전체가 아니라 코드를 실행하는 동안에만 샌드박스 비용을 냅니다.
Ben Guo는 에이전트 런타임과 샌드박스 런타임을 분리하는 장점에 대해 마지막으로 이렇게 덧붙입니다. "저희는 말씀하신 이유들 때문에 패턴 2를 골랐지만, 에이전트 하네스를 GPU 머신에서 돌리는 것이 합리적인 미래에 대비하는 뜻도 있었습니다. 전반적으로 영속 샌드박스와 추론 하네스의 환경 요구사항은 서로 갈라질 것 같다는 느낌이 듭니다."
트레이드오프
네트워크 지연이 주된 단점입니다. 실행 호출마다 네트워크 경계를 넘습니다. 작은 실행이 많은 워크로드에서는 이것이 쌓일 수 있습니다.
많은 샌드박스 제공자가 상태를 유지하는 세션을 제공해서, 같은 세션 안에서는 변수와 파일, 설치한 패키지가 여러 번의 호출에 걸쳐 유지됩니다. 필요한 왕복 횟수가 줄어들기 때문에 지연에 대한 우려를 어느 정도 덜어 줄 수 있습니다.
두 패턴 중 무엇을 고를까
다음과 같을 때 패턴 1을 고르세요.
- 에이전트와 실행 환경이 강하게 결합되어 있습니다. 예를 들어 에이전트가 특정 라이브러리나 복잡한 환경 상태에 계속 접근해야 하는 경우입니다.
- 프로덕션이 로컬 개발과 최대한 비슷하기를 원합니다.
- 여러분이 쓰는 제공자의 SDK가 통신 계층을 대신 처리해 줍니다.
다음과 같을 때 패턴 2를 고르세요.
- 개발 중에 에이전트 로직을 빠르게 반복해서 고쳐야 합니다.
- API 키를 샌드박스 밖에 두고 싶습니다.
- 에이전트 상태와 실행 환경이 더 깔끔하게 분리되는 쪽을 선호합니다.
구현 예시
이 패턴들을 구체적으로 보여 주기 위해, 샌드박스 지원이 내장된 오픈 소스 에이전트 프레임워크 deepagents를 쓴 예시를 보겠습니다. 다른 에이전트 프레임워크에도 비슷한 패턴이 적용됩니다.
패턴 1: 샌드박스 안의 에이전트(Agent IN Sandbox)
패턴 1에서는 먼저 에이전트를 미리 설치한 이미지를 만듭니다.
FROM python:3.11
RUN pip install deepagents-cli그다음 그것을 샌드박스 안에서 실행합니다. 완전한 구현을 위해서는 여러분의 애플리케이션과 샌드박스 안의 에이전트 사이의 통신을 처리할 추가 인프라가 필요합니다. WebSocket이나 HTTP 서버, 세션 관리, 오류 처리 같은 것들입니다. 이는 이 글의 범위를 넘어서지만, 후속 글에서 더 자세히 파고들 예정입니다.
패턴 2: 도구로서의 샌드박스(Sandbox as Tool)
from daytona import Daytona
from langchain_anthropic import ChatAnthropic
from deepagents import create_deep_agent
from langchain_daytona import DaytonaSandbox
# E2B와 Runloop, Modal로도 같은 방식으로 할 수 있습니다
sandbox = Daytona().create()
backend = DaytonaSandbox(sandbox=sandbox)
agent = create_deep_agent(
model=ChatAnthropic(model="claude-sonnet-4-20250514"),
system_prompt="You are a Python coding assistant with sandbox access.",
backend=backend,
)
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "Run a small python script",
}
]
}
)
sandbox.stop()이 코드가 실행되면 다음과 같은 일이 일어납니다.
- 에이전트가 여러분의 머신에서 로컬로 계획을 세웁니다.
- 문제를 풀기 위한 파이썬 코드를 생성합니다.
- Runloop API를 호출하고, 그쪽에서 원격 샌드박스에서 코드를 실행합니다.
- 샌드박스가 결과를 반환합니다.
- 에이전트가 그 출력을 보고 로컬에서 추론을 이어 갑니다.
결론
에이전트는 보안을 위해 격리된 환경에서 코드를 실행해야 합니다. 아키텍처 패턴은 두 가지입니다. 에이전트를 샌드박스 안에서 돌리는 방식(로컬 개발과 똑같은 모습, 강한 결합)과, 샌드박스를 도구로 두고 에이전트를 밖에서 돌리는 방식(업데이트가 쉽고 API 키가 안전하게 유지됨)입니다. 각각 필요에 따라 장점과 트레이드오프가 다릅니다.
deepagents는 두 패턴 모두를 간단한 설정으로 지원합니다. 직접 써 보면서 여러분의 사용 사례에 어떤 패턴이 가장 잘 맞는지 확인해 보세요.