안전한 코드 실행
안전한 코드 실행 (Secure code execution)
[!TIP] 에이전트 만들기가 처음이라면 먼저 에이전트 소개와 smolagents 둘러보기를 읽어보세요.
코드 에이전트
여러 연구 논문이 LLM이 동작(도구 호출)을 코드로 작성하는 것이 업계 표준 도구 호출 형식보다 훨씬 낫다고 보여줬어요. 이유는 다음과 같아요.
- 구성 가능성(Composability): JSON 동작을 서로 중첩하거나 재사용할 JSON 동작 집합을 정의할 수 있나요? Python 함수를 정의하는 것처럼요.
- 객체 관리:
generate_image같은 동작의 출력을 JSON에 어떻게 저장하나요? - 일반성: 코드는 컴퓨터가 할 수 있는 어떤 것이든 단순하게 표현하도록 만들어졌어요.
- LLM 학습 코퍼스에서의 표현: 이미 많은 고품질 동작이 LLM 학습 코퍼스에 포함돼 있다는 축복을 활용하지 않을 이유가 없죠?
이 그림은 Executable Code Actions Elicit Better LLM Agents에서 가져온 것입니다. 그래서 우리는 코드 에이전트(여기선 Python 에이전트)를 제안하는 데 중점을 뒀고, 이는 안전한 Python 인터프리터를 만드는 데 더 많은 노력을 기울였다는 뜻이에요.
로컬 코드 실행??
기본적으로 CodeAgent는 LLM이 생성한 코드를 당신의 환경에서 실행해요. 이는 본질적으로 위험합니다. LLM 생성 코드는 환경에 해로울 수 있어요. 악성 코드 실행은 여러 방식으로 일어날 수 있습니다.
- 평범한 LLM 오류: LLM은 아직 완벽과 거리가 멀어 도움이 되려다 의도치 않게 유해한 명령을 생성할 수 있어요. 위험은 낮지만, LLM이 잠재적 위험 코드를 실행하려 한 사례가 관찰됐어요.
우리의 로컬 Python 실행기
첫 보안 계층으로, smolagents에서 코드 실행은 바닐라 Python 인터프리터가 수행하지 않아요. 우리는 더 안전한 LocalPythonExecutor를 처음부터 다시 만들었습니다. 정확히는 이 인터프리터는 코드에서 **추상 구문 트리(AST)**를 로드해 연산 단위로 실행하며, 항상 특정 규칙을 따릅니다.
random처럼 겉보기에 무해한 패키지도random._os같은 잠재적 위험 하위 모듈에 접근을 줄 수 있다는 점에 유의하세요.- 처리되는 기본 연산의 총 개수에 상한을 두어 무한 루프와 리소스 비대화를 방지합니다.
from smolagents.local_python_executor import LocalPythonExecutor
# Set up custom executor, authorize package "numpy"
custom_executor = LocalPythonExecutor(["numpy"])
# Utility for pretty printing errors
def run_capture_exception(command: str):
try:
custom_executor(harmful_command)
우리 인터프리터가 표준 Python 인터프리터보다 훨씬 안전하지만, 결심한 공격자나 미세조정된 악성 LLM이 취약점을 찾아 환경을 해칠 가능성은 여전히 있어요. 예를 들어 Pillow 같은 패키지로 이미지를 처리하도록 허용했다면요.
안전한 코드 실행을 위한 샌드박스 접근
코드를 실행하는 AI 에이전트를 다룰 때 보안은 가장 중요해요. smolagents에는 코드 실행을 샌드박싱하는 두 가지 주요 접근 방식이 있으며, 각각 다른 보안 속성과 기능을 가집니다.
- 개별 코드 스니펫을 샌드박스에서 실행: 이 접근(그림 왼쪽)은 에이전트가 생성한 Python 코드 스니펫만 샌드박스에서 실행하고 나머지 에이전틱 시스템은 로컬 환경에 둡니다.
executor_type="blaxel",executor_type="e2b",executor_type="modal",executor_type="docker"로 설정하기 쉬우나, 멀티 에이전트를 지원하지 않고 환경과 샌드박스 사이에 상태 데이터를 전달해야 합니다. - 전체 에이전틱 시스템을 샌드박스에서 실행: 이 접근(그림 오른쪽)은 에이전트·모델·도구를 포함한 전체 에이전틱 시스템을 샌드박스 환경에서 실행합니다.
Blaxel 설정
설치:
- blaxel.ai에서 Blaxel 계정 생성
- 필수 패키지 설치:
pip install 'smolagents[blaxel]'
Blaxel로 에이전트 실행: 빠른 시작 — Blaxel은 25ms 미만의 하이버네이션 부팅과 비활성 후 0으로 스케일 백(메모리 상태 유지)을 제공하는 빠른 시작 가상 머신을 제공해, 빠르고 안전한 코드 실행이 필요한 에이전트 앱에 적합합니다.
E2B 설정
설치:
- e2b.dev에서 E2B 계정 생성
- 필수 패키지 설치:
pip install 'smolagents[e2b]'
E2B에서 에이전트 실행: 빠른 시작 — 에이전트 초기화에 executor_type="e2b"만 추가하면 됩니다.
from smolagents import InferenceClientModel, CodeAgent
with CodeAgent(model=InferenceClientModel(), tools=[], executor_type="e2b") as agent:
agent.run("Can you give me the 100th Fibonacci number?")
다만 관리되는 에이전트에 대한 어떤 호출도 모델 호출을 필요로 하므로, 비밀을 원격 샌드박스로 전송하지 않기 때문에 모델 호출에 자격 증명이 없을 수 있어요. 그래서 이 해결책은 더 복잡한 멀티 에이전트 구성에서는 (아직은) 동작하지 않습니다.
E2B에서 멀티 에이전트 — E2B에서 멀티 에이전트를 쓰려면 에이전트를 완전히 E2B 안에서 실행해야 해요.
from e2b_code_interpreter import Sandbox
import os
# Create the sandbox
sandbox = Sandbox()
# Install required packages
sandbox.commands.run("pip install smolagents")
def run_code_raise_errors(sandbox, code: str, verbose: bool = False) -> str:
execution = sandbox.run_code(
code,
envs={'HF_TOKEN': os.getenv('HF_TOKEN')}
)
if execution.error:
execution_logs = "\n".join([str(log) for log in execution.logs.stdout])
logs = execution_logs
logs += execution.error.traceback
raise ValueError(logs)
return "\n".join([str(log) for log in execution.logs.stdout])
# Define your agent application
agent_code = """
import os
from smolagents import CodeAgent, InferenceClientModel
# Initialize the agents
agent = CodeAgent(
model=InferenceClientModel(token=os.getenv("HF_TOKEN"), provider="together"),
tools=[],
name="coder_agent",
description="This agent takes care of your difficult algorithmic problems using code."
)
manager_agent = CodeAgent(
model=InferenceClientModel(token=os.getenv("HF_TOKEN"), provider="together"),
tools=[],
managed_agents=[agent],
)
# Run the agent
response = manager_agent.run("What's the 20th Fibonacci number?")
print(response)
"""
# Run the agent code in the sandbox
Modal 설정
설치:
- modal.com에서 Modal 계정 생성
- 필수 패키지 설치:
pip install 'smolagents[modal]'
Modal에서 에이전트 실행: 빠른 시작 — 에이전트 초기화에 executor_type="modal"만 추가하면 됩니다.
from smolagents import InferenceClientModel, CodeAgent
with CodeAgent(model=InferenceClientModel(), tools=[], executor_type="modal") as agent:
agent.run("What is the 42th Fibonacci number?")
[!TIP] 에이전트를 컨텍스트 매니저로(
with문) 사용하면 Modal 샌드박스가 작업 완료 직후 정리됩니다. 아니면 에이전트의cleanup()메서드를 직접 호출하세요.
Docker 설정
설치:
- 시스템에 Docker 설치
- 필수 패키지 설치:
pip install 'smolagents[docker]'
Docker에서 에이전트 실행: 빠른 시작 — 초기화에 executor_type="docker"만 추가하면 됩니다.
from smolagents import InferenceClientModel, CodeAgent
with CodeAgent(model=InferenceClientModel(), tools=[], executor_type="docker") as agent:
agent.run("Can you give me the 100th Fibonacci number?")
[!TIP]
with문으로 에이전트를 컨텍스트 매니저로 쓰면 Docker 컨테이너가 작업 완료 직후 정리됩니다. 아니면cleanup()메서드를 직접 호출하세요.
고급 Docker 사용법 — Docker에서 멀티 에이전트 시스템을 실행하려면 샌드박스에 커스텀 인터프리터를 설정해야 해요.
FROM python:3.10-bullseye
# Install build dependencies
RUN apt-get update && \
apt-get install -y --no-install-recommends \
build-essential \
python3-dev && \
pip install --no-cache-dir --upgrade pip && \
pip install --no-cache-dir smolagents && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# Set working directory
WORKDIR /app
# Run with limited privileges
USER nobody
# Default command
CMD ["python", "-c", "print('Container ready')"]
보안 접근 방식 비교
접근 1: 코드 스니펫만 샌드박스에서 실행
- 장점:
- 간단한 파라미터(
executor_type="blaxel",executor_type="e2b",executor_type="docker")로 설정 용이 - API 키를 샌드박스로 전송할 필요 없음
- 로컬 환경 보호에 더 좋음