tracks
OpenAI의 최신 Agents 샌드박스 워크플로는 에이전트 실행 구조를 바꿉니다. 에이전트, 파일, 도구, 런타임을 하나의 복잡한 루프에 넣는 대신, 신뢰 가능한 오케스트레이션 계층과 실행 환경을 분리합니다.
즉, 애플리케이션은 에이전트 로직, 모델 호출, 의사결정을 담당하고, 실제 작업은 파일, 명령, 생성된 출력에 접근할 수 있는 샌드박스된 워크스페이스 안에서 수행됩니다.
이 구성은 에이전트가 프롬프트 맥락에만 의존하지 않고 더 많은 일을 해야 할 때 특히 유용합니다. 예를 들어, 프로젝트를 확인하고, 파일을 작성·수정하고, 코드를 실행하고, 출력을 테스트하고, 통제된 환경에서 산출물을 생성할 수 있습니다.
이 가이드에서는 OpenAI Agents 프레임워크와 Modal Sandboxes를 결합해 실용적인 에이전트형 애플리케이션을 만드는 방법을 알아봅니다. 에이전트는 격리된 Modal 환경 안에서 실행되고, 명령을 안전하게 수행하며, 파일을 다루고, 유용한 출력을 메인 애플리케이션으로 반환할 수 있습니다.
샌드박스를 사용하지 않는 입문용 자료는 OpenAI Agents SDK 튜토리얼을 참고하세요.
OpenAI Agents SDK의 새로운 점
최신 OpenAI Agents SDK는 실제 파일, 도구, 실행 환경과 함께 작동하는 에이전트를 더 깔끔하게 구축할 수 있게 해줍니다. 모든 것을 하나의 프롬프트 루프에 넣는 대신, 이제 SDK는 작업이 이뤄지는 샌드박스와 에이전트 오케스트레이션 계층을 분리합니다.
주요 업데이트는 다음과 같습니다.
- 네이티브 샌드박스 지원: 격리된 환경에서 에이전트를 실행
- Manifest: 에이전트가 접근할 수 있는 파일, 폴더, 출력을 정의
- SandboxAgent: 에이전트를 샌드박스 워크스페이스와 연결
- SandboxRunConfig: 샌드박스 실행의 위치와 방식을 제어
- Codex 스타일 도구: 파일 편집, 셸 명령, 프로젝트 점검
- MCP 지원: 외부 도구 및 서비스와의 연결 활성화
- Skills 및 AGENTS.md 지원: 프로젝트 지시사항을 더 명확히 제공
- 다양한 샌드박스 제공자 지원: Modal, E2B, Cloudflare, Daytona, Blaxel, Runloop, Vercel
이 업데이트로 프로젝트를 점검하고, 코드를 실행하고, 파일을 편집하며, 통제된 워크스페이스에서 생성된 출력을 반환하는 에이전트형 앱을 더 쉽게 만들 수 있습니다.
1. 프로젝트 설정
이 데모 프로젝트에서는 OpenAI Agents SDK와 Modal Sandboxes를 사용해 간단한 지원 티켓 분류 예제를 만듭니다. 앱은 샌드박스된 워크스페이스를 만들고 몇 개의 프로젝트 파일을 추가한 다음, GPT-5.4-mini 에이전트가 답변하기 전에 해당 파일을 살펴보도록 합니다.
먼저 환경에 필요한 패키지를 설치하세요:
pip install "openai-agents[modal]" modal
프로젝트를 실행하기 전에 두 가지 계정이 필요합니다.
- OpenAI 계정: OpenAI Platform에서 계정을 만들고 신용카드로 API 크레딧을 추가하세요. 최신 지원 모델에 접근하려면 계정 인증이 필요합니다.
- Modal 계정: Modal에 가입하세요. 무료 플랜에는 본 가이드를 테스트하기에 충분한 월간 크레딧이 포함됩니다.
다음으로 OpenAI API 키를 로컬 환경에 추가하세요.
- macOS 또는 Linux:
export OPENAI_API_KEY="your_openai_api_key" - Windows PowerShell:
$env:OPENAI_API_KEY="your_openai_api_key"
그다음 로컬에서 Modal 인증을 진행하세요:
modal setup
브라우저 창이 열리고 Modal에 로그인하라는 메시지가 표시됩니다. 로그인 후 토큰 생성 요청을 승인하세요. Modal이 자격 증명을 자동으로 로컬 환경에 추가합니다.
모든 설정을 마치면 터미널에 Modal 인증이 완료되었다는 성공 메시지가 표시됩니다.

2. 샌드박스 워크스페이스 정의
이제 main.py 같은 Python 파일을 만들고 필요한 임포트를 추가하세요. 이 임포트는 OpenAI Agents SDK, 샌드박스 구성 클래스, Modal 샌드박스 클라이언트를 불러옵니다.
import asyncio
from agents import ModelSettings, Runner
from agents.run import RunConfig
from agents.sandbox import Manifest, SandboxAgent, SandboxRunConfig
from agents.sandbox.entries import File
from agents.extensions.sandbox import ModalSandboxClient, ModalSandboxClientOptions
이제 샌드박스 워크스페이스를 정의해야 합니다. 이 예제의 워크스페이스에는 README.md, 앱 파일, 릴리스 체크리스트가 포함된 작은 지원 티켓 분류 프로젝트가 들어 있습니다.
manifest = Manifest(
entries={
"README.md": File(
content=(
b"# Support Ticket Triage\n\n"
b"Small service that labels customer tickets by urgency and team.\n"
)
),
"src/app.py": File(
content=(
b"def route_ticket(subject: str, customer_tier: str) -> dict:\n"
b" urgent = customer_tier == \"enterprise\" or \"outage\" in subject.lower()\n"
b" return {\n"
b" \"priority\": \"high\" if urgent else \"normal\",\n"
b" \"team\": \"support-ops\" if urgent else \"customer-care\",\n"
b" }\n"
)
),
"docs/release-checks.md": File(
content=(
b"# Release Checks\n\n"
b"- Confirm routing rules match the current support escalation policy.\n"
)
),
}
)
Manifest는 샌드박스 안에 어떤 파일이 존재하는지 에이전트에게 알려줍니다. 이는 단지 프롬프트 텍스트에만 의존하는 대신, 에이전트가 실제 프로젝트 구조를 점검하고 편집하며 추론할 수 있도록 합니다.
이 경우 에이전트는 지원 티켓 라우팅 로직을 검토하고 문서를 확인하며 샌드박스 워크스페이스 안에서 변경을 수행할 수 있습니다.
3. 샌드박스 에이전트 생성
워크스페이스를 정의했으면 샌드박스 기반 에이전트를 만듭니다. SandboxAgent는 실제 워크스페이스와 함께 작업하도록 설계되어, 파일을 점검하고, 프로젝트 구조를 이해하며, 샌드박스 내부에 존재하는 내용에 근거해 응답할 수 있습니다.
agent = SandboxAgent(
name="Modal Sandbox Assistant",
model="gpt-5.4-mini",
instructions=(
"You are a coding assistant reviewing a small production service. "
"Inspect the sandbox workspace before answering. "
"Keep the answer short and practical."
),
default_manifest=manifest,
model_settings=ModelSettings(tool_choice="required"),
)
여기서는 에이전트 이름을 Modal Sandbox Assistant로 지정하고, 더 빠른 응답을 위해 gpt-5.4-mini 모델을 사용합니다. 지시문은 답변 전에 샌드박스 워크스페이스를 점검하라고 안내하며, 이는 응답이 프로젝트의 실제 파일에 의존할 때 중요합니다.
default_manifest=manifest는 앞서 만든 워크스페이스를 에이전트에 연결합니다. tool_choice="required" 설정은 에이전트가 기억이나 프롬프트 맥락만으로 답변하지 않고 사용 가능한 샌드박스 도구를 활용하도록 유도합니다.
4. Modal 샌드박스 클라이언트 생성
이제 Modal 샌드박스 클라이언트를 만듭니다. 이는 실제 파일 및 명령 실행이 이뤄지는 Modal 샌드박스와 OpenAI Agents 워크플로 사이의 연결 고리입니다.
client = ModalSandboxClient()
options = ModalSandboxClientOptions(
app_name="openai-agents-modal-demo",
workspace_persistence="tar",
)
ModalSandboxClient()는 샌드박스 제공자로 Modal을 사용하도록 에이전트에 지시합니다. 즉, 에이전트는 로컬 머신에서 직접 실행되는 대신 격리된 Modal 환경에서 실행됩니다.
ModalSandboxClientOptions는 Modal 샌드박스의 구성을 제어합니다. 여기서 app_name은 Modal 앱의 명칭을 명확히 하고, workspace_persistence="tar"는 실행 중 워크스페이스 파일을 패키징·보존하는 방식을 지정합니다.
5. 샌드박스 세션 시작
클라이언트와 옵션이 준비되면 manifest로부터 샌드박스를 생성하고 세션을 시작합니다.
sandbox = await client.create(
manifest=manifest,
options=options,
)
await sandbox.start()
client.create() 호출은 Manifest에 정의한 파일을 사용해 새 Modal 샌드박스를 생성합니다. 즉, 샌드박스는 README.md, src/app.py, docs/release-checks.md 등을 포함한 동일한 프로젝트 구조로 시작합니다.
그다음 await sandbox.start()로 샌드박스 세션을 시작합니다. 이제 Modal에서 격리된 라이브 워크스페이스가 실행 중이며, 에이전트가 파일을 점검하고 명령을 실행하며 프로젝트와 상호작용할 준비가 된 상태입니다.
6. 샌드박스에서 에이전트 실행
샌드박스가 활성화되면, 라이브 샌드박스 세션을 SandboxRunConfig로 전달해 에이전트를 실행합니다. 이는 실행 중 에이전트가 Modal 샌드박스 워크스페이스를 사용해야 함을 OpenAI Agents SDK에 알려줍니다.
result = await Runner.run(
agent,
(
"Explain what this service does and name one production check "
"before release. Keep it under 3 sentences."
),
run_config=RunConfig(
sandbox=SandboxRunConfig(session=sandbox),
workflow_name="Modal sandbox example",
),
)
print(result.final_output)
여기서 모든 것이 결합됩니다. 모델은 추론을 담당하고, 샌드박스는 실제 워크스페이스 파일에 대한 접근을 제공합니다.
이 예제에서 에이전트는 지원 티켓 분류 프로젝트를 점검하고, 서비스가 무엇을 하는지 파악하며, 릴리스 노트를 확인하고, Modal 샌드박스 내 파일을 기반으로 짧은 답변을 반환할 수 있습니다.
7. 샌드박스 정리
에이전트 실행이 끝나면 Modal에 사용하지 않는 세션이 남지 않도록 샌드박스를 삭제하세요.
await client.aclose(sandbox)
이는 작업 완료 후 샌드박스 세션을 제거합니다. 샌드박스 세션은 활성 상태에서 컴퓨팅 리소스를 사용할 수 있으므로 정리하는 습관이 좋습니다.
실제 프로젝트에서는 이를 finally 블록 안에 두는 것이 좋습니다. 이렇게 하면 에이전트 호출이 실패하거나 스크립트에 오류가 발생해도 정리가 수행됩니다.
8. 전체 코드 예제
다음은 전체 스크립트입니다. 워크스페이스를 만들고 Modal 샌드박스를 시작한 뒤, 그 안에서 에이전트를 실행하고 최종 출력을 출력한 다음 샌드박스 세션을 정리합니다.
import asyncio
from agents import ModelSettings, Runner
from agents.extensions.sandbox import ModalSandboxClient, ModalSandboxClientOptions
from agents.run import RunConfig
from agents.sandbox import Manifest, SandboxAgent, SandboxRunConfig
from agents.sandbox.entries import File
async def main():
manifest = Manifest(
entries={
"README.md": File(
content=(
b"# Support Ticket Triage\n\n"
b"Small service that labels customer tickets by urgency and team.\n"
)
),
"src/app.py": File(
content=(
b"def route_ticket(subject: str, customer_tier: str) -> dict:\n"
b" urgent = customer_tier == \"enterprise\" or \"outage\" in subject.lower()\n"
b" return {\n"
b" \"priority\": \"high\" if urgent else \"normal\",\n"
b" \"team\": \"support-ops\" if urgent else \"customer-care\",\n"
b" }\n"
)
),
"docs/release-checks.md": File(
content=(
b"# Release Checks\n\n"
b"- Confirm routing rules match the current support escalation policy.\n"
)
),
}
)
agent = SandboxAgent(
name="Modal Sandbox Assistant",
model="gpt-5.4-mini",
instructions=(
"You are a coding assistant reviewing a small production service. "
"Inspect the sandbox workspace before answering. "
"Keep the answer short and practical."
),
default_manifest=manifest,
model_settings=ModelSettings(tool_choice="required"),
)
client = ModalSandboxClient()
options = ModalSandboxClientOptions(
app_name="openai-agents-modal-demo",
workspace_persistence="tar",
)
sandbox = await client.create(
manifest=manifest,
options=options,
)
await sandbox.start()
try:
result = await Runner.run(
agent,
(
"Explain what this service does and name one production check "
"before release. Keep it under 3 sentences."
),
run_config=RunConfig(
sandbox=SandboxRunConfig(session=sandbox),
workflow_name="Modal sandbox example",
),
)
print(result.final_output)
finally:
await sandbox.aclose()
if __name__ == "__main__":
asyncio.run(main())
이 스크립트는 현재 OpenAI 샌드박스 구조를 따르며 실행 백엔드로 Modal을 사용합니다. 에이전트 로직은 Python 앱 내에 유지되고, 실제 워크스페이스는 Modal 샌드박스 안에서 실행됩니다.
finally 블록은 에이전트 실행이 실패하더라도 샌드박스를 닫고 삭제하므로 중요합니다. 이를 통해 Modal 환경을 깔끔하게 유지하고 미사용 세션이 남지 않도록 할 수 있습니다.
9. 로컬에서 앱 테스트
스크립트를 준비했으면, main.py가 저장된 동일한 폴더의 터미널에서 로컬로 실행하세요:
python main.py
모든 구성이 올바르면 스크립트는 Modal 샌드박스를 만들고, 그 안에 매니페스트를 로드하고, 워크스페이스에 대해 OpenAI 에이전트를 실행하고, 응답을 출력한 다음 샌드박스를 정리합니다.
다음과 유사한 출력을 볼 수 있습니다.
This service triages customer support tickets by assigning urgency and routing them to the right team. One production check before release is to confirm the routing rules still match the current support escalation policy.
실행에는 몇 초가 걸릴 수 있습니다. 실행 중에는 Modal 대시보드를 열고 openai-agents-modal-demo 앱을 클릭해 로그를 확인하세요. 샌드박스가 생성·시작되어 에이전트가 사용했고 성공적으로 정리되었는지 확인하는 데 유용합니다.

10. 대화형 웹 앱 만들기
첫 번째 스크립트는 정적이어서 한 번의 요청과 한 번의 응답만 처리하고 종료합니다. 프로젝트 사용성을 높이기 위해 Gradio를 사용해 대화형 웹 앱으로 바꿀 수 있습니다. 이렇게 하면 샌드박스 에이전트와 대화하고, 후속 질문을 하며, 파일을 생성·편집하고, 간단한 브라우저 인터페이스에서 테스트를 실행할 수 있습니다.
먼저 Gradio 최신 버전을 설치합니다:
pip install gradio
그다음 app.py라는 새 파일을 만들고 Gradio 앱 코드(OpenAI-Agents-in-Modal/app.py)를 복사해 넣으세요. 이 앱은 동일한 OpenAI Agents와 Modal 샌드박스 구성을 사용하지만, 이를 채팅 인터페이스 안에 감쌉니다. 또한 가능한 경우 샌드박스 세션을 재사용해 매 메시지마다 완전히 새로운 샌드박스를 만들 필요가 없도록 합니다.
앱은 다음 명령으로 실행합니다:
python app.py
터미널에 로컬 URL이 표시됩니다:
* Running on local URL: http://127.0.0.1:7860
* To create a public link, set share=True in launch().
브라우저에서 로컬 URL을 열어 채팅 앱을 사용하세요. 에이전트에게 프로젝트 점검을 요청하고, 서비스가 무엇을 하는지 설명을 요구하고, 보조 파일을 새로 만들거나 기존 파일을 편집하고, Modal 샌드박스 내부에서 테스트를 실행할 수 있습니다.

예를 들어, 먼저 프로젝트 서비스가 무엇을 하는지 설명해 달라고 요청했고, 몇 초 만에 샌드박스 파일을 기반으로 한 상세한 응답이 돌아왔습니다.

그다음 에이전트에게 새로운 라우팅 헬퍼 파일을 만들도록 요청했습니다. 이 요청은 에이전트가 샌드박스 워크스페이스를 수정하고, 테스트를 추가하고, 테스트 스위트를 실행해야 했기 때문에 조금 더 오래 걸렸습니다.
에이전트는 src/routing_rules.py를 생성하고, tests/test_routing_rules.py에 새 테스트 파일을 추가했으며, pytest로 변경 사항을 검증했습니다. 총 6개의 테스트가 모두 통과해, 새 헬퍼가 올바르게 동작하고 기존 티켓 라우팅 로직도 그대로 유지됨을 확인했습니다.

큰 틀에서 보면, 이 Gradio 앱은 Modal을 백엔드로 사용하는 OpenAI 에이전트와 작업할 수 있는 간단한 프런트엔드를 제공합니다. 사용자가 브라우저에서 메시지를 보내면 앱이 이를 SandboxAgent에 전달하고, 에이전트는 Modal 샌드박스 안에서 작업한 뒤 최종 응답이 채팅 인터페이스에 표시됩니다.
마무리
Modal Sandboxes와 함께 사용하는 OpenAI Agents는 격리된 환경에서 실제 파일을 다루고, 명령을 실행하며, 유용한 출력을 반환하는 에이전트형 앱을 깔끔하게 구축할 수 있게 해줍니다.
Modal 설정 과정은 매끄러웠고, 샌드박스 생성도 간단했습니다. 모든 것이 연결되자 에이전트는 프로젝트를 점검하고, 새로운 라우팅 헬퍼 파일을 만들고, 테스트를 추가한 뒤, 6개 테스트 모두 통과했음을 확인할 수 있었습니다.
다만 대화형 앱을 구축하고 모델을 구성하는 데 예상보다 손이 많이 갔습니다. 또한 파일 생성 및 테스트 단계가 길어지는 경우가 있었는데, 때때로 Modal 샌드박스가 타임아웃되었기 때문입니다. 전체 워크플로를 완료할 충분한 시간을 주기 위해 샌드박스 타임아웃을 300초에서 600초로 늘려야 했습니다.
또 다른 어려움은 로깅과 가시성이었습니다. 에이전트가 끝나기를 기다리는 동안, 백그라운드에서 Agents SDK가 무엇을 하는지 항상 명확하지 않았습니다. Modal 로그 역시 에이전트가 파일을 점검 중인지, 코드를 편집 중인지, 테스트를 실행 중인지 이해하기엔 충분한 세부 정보를 보여주지 않을 때가 있었습니다.
앞으로는 각 단계를 더 명확히 따라갈 수 있도록, Claude Code와 같은 도구를 사용할 때 보이는 것과 유사한 보다 상세한 에이전트 로그가 있으면 좋겠습니다.
전반적으로, 파일, 코드, 생성된 출력과 함께 작업해야 하는 에이전트형 앱을 구축하기에 강력한 워크플로입니다. 전체 프로젝트는 GitHub에서 확인할 수 있으며, 로컬로 클론해 직접 실행해 보세요: kingabzpro/OpenAI-Agents-in-Modal.
고급 AI 시스템 구축의 요령을 배우고 싶다면 Building Scalable Agentic Systems 과정을 추천합니다.
OpenAI Agents SDK 샌드박스 FAQ
에이전트 오케스트레이션 계층과 샌드박스 실행 환경의 차이는 무엇인가요?
오케스트레이션 계층은 Python 애플리케이션 안에 있으며 에이전트 로직, 모델 호출, 의사결정을 처리합니다. 샌드박스는 실제 작업(예: 파일 읽기/쓰기, 셸 명령, 코드 실행)이 이뤄지는 격리된 환경입니다. 둘을 분리하면 신뢰할 수 없거나 예측 불가능한 코드가 메인 애플리케이션에 영향을 주지 않고 샌드박스에서 실행됩니다.
꼭 Modal을 사용해야 하나요, 아니면 다른 샌드박스 제공자를 사용할 수 있나요?
Modal은 지원되는 여러 제공자 중 하나입니다. OpenAI Agents SDK는 Modal, E2B, Cloudflare, Daytona, Blaxel, Runloop, Vercel을 지원합니다. 클라이언트 클래스를 변경(ModalSandboxClient 대신 E2BSandboxClient 등)하면 나머지 에이전트 코드는 대부분 그대로 두고 제공자를 교체할 수 있습니다.
Manifest란 무엇이며, 에이전트에게 왜 필요한가요?
Manifest는 샌드박스 워크스페이스에 존재하는 파일과 폴더 구조를 정의합니다. 이것이 없으면 에이전트는 프롬프트 맥락에 포함된 정보에만 접근할 수 있습니다. Manifest를 전달하면 에이전트에게 실제 프로젝트를 제공해 점검, 편집, 추론을 수행하게 할 수 있으며, 단순한 텍스트 설명에 의존할 때보다 훨씬 근거 있고 정확한 응답을 얻을 수 있습니다.
OpenAI Agents SDK 샌드박스 업데이트가 ChatGPT의 Code Interpreter 도구와 같은 것인가요?
아닙니다. Code Interpreter 도구는 최종 사용자용 ChatGPT 내장 기능입니다. Agents SDK 샌드박스는 개발자 대상 프레임워크로, 사용자가 직접 실행 환경(예: Modal, E2B)을 가져와 구축·제어하는 에이전트에 연결할 수 있게 합니다. 워크스페이스, 파일, 샌드박스 세션의 생명주기를 사용자가 직접 관리합니다.