Daytona 샌드박스 도구

Daytona 샌드박스 도구 (Daytona Sandbox Tools)

격리된 Daytona 샌드박스 안에서 셸 명령을 실행하고, Python을 실행하고, 파일을 관리하세요.

출처: 문서

본문

설명 (Description)

Daytona 샌드박스 도구들은 CrewAI 에이전트에게 Daytona가 제공하는 격리되고 일시적인(ephemeral) 컴퓨트 환경에 대한 접근권을 부여합니다. 세 가지 도구가 있어서 에이전트에게 필요한 정확한 기능만을 부여할 수 있어요:

  • DaytonaExecTool — 샌드박스 안에서 아무 셸 명령이나 실행.
  • DaytonaPythonTool — 샌드박스 안에서 Python 소스 코드 블록을 실행.
  • DaytonaFileTool — 샌드박스 안에서 파일을 읽기, 쓰기, 추가, 목록화, 삭제, 검사. 또한 move, find(콘텐츠 grep), search(파일명 glob), chmod(권한), replace(대량 찾기-바꾸기), exists도 지원.

세 도구 모두 동일한 샌드박스 수명주기(lifecycle) 제어를 공유하므로, 단일 영구 샌드박스에 상태를 유지하면서 도구들을 섞어 쓸 수 있어요.

설치 (Installation)

uv add "crewai-tools[daytona]"
# or
pip install "crewai-tools[daytona]"

API 키를 설정하세요:

export DAYTONA_API_KEY="your-api-key"

DAYTONA_API_URL과 DAYTONA_TARGET도 설정되어 있으면 각각 존중됩니다.

샌드박스 수명주기 (Sandbox Lifecycle)

세 도구 모두 DaytonaBaseTool에서 수명주기 제어를 상속합니다:

모드 활성화 방법 샌드박스 생성 샌드박스 삭제
Ephemeral (기본값) persistent=False (기본) 매 _run 호출 시 그 같은 호출이 끝날 때
Persistent persistent=True 첫 사용 시 지연(lazily) 생성 프로세스 종료 시(atexit), 또는 tool.close()로 수동
Attach sandbox_id="<id>" 없음 — 기존 샌드박스에 연결 없음 — 생성하지 않은 샌드박스는 삭제하지 않음

Ephemeral 모드는 안전한 기본값이에요. 에이전트가 정리를 잊어도 아무것도 새지 않습니다. 여러 도구 호출에 걸쳐 파일시스템 상태나 설치된 패키지를 유지하고 싶다면 persistent 모드를 사용하세요 — DaytonaFileTool과 DaytonaExecTool을 함께 쓸 때가 전형적인 경우입니다.

예제 (Examples)

일회성 Python 실행 (ephemeral)

from crewai_tools import DaytonaPythonTool

tool = DaytonaPythonTool()
result = tool.run(code="print(sum(range(10)))")
print(result)
# {"exit_code": 0, "result": "45\n", "artifacts": ExecutionArtifacts(stdout="45\n", charts=[])}

다단계 셸 세션 (persistent)

from crewai_tools import DaytonaExecTool, DaytonaFileTool

# Create the persistent sandbox via the first tool, then attach the second
# tool to it so both share state (installed packages, files, env vars).
exec_tool = DaytonaExecTool(persistent=True)
exec_tool.run(command="pip install httpx -q")
file_tool = DaytonaFileTool(sandbox_id=exec_tool.active_sandbox_id)

file_tool.run(
    action="write",
    path="workspace/script.py",
    content="import httpx; print(f'httpx loaded, version {httpx.__version__}')",
)
exec_tool.run(command="python workspace/script.py")

기본적으로 persistent=True인 각 도구는 첫 사용 시 자체 샌드박스를 지연 생성합니다. 위 패턴은 .run() 호출 후 첫 도구의 active_sandbox_id를 읽어 sandbox_id=...로 다른 도구에 전달함으로써 여러 도구가 단일 샌드박스를 공유하게 합니다. persistent=False(기본값)에서는 매 .run() 호출마다 새 샌드박스를 받고, 그 호출이 끝날 때 삭제됩니다.

기존 샌드박스에 연결하기 (Attach)

from crewai_tools import DaytonaExecTool

tool = DaytonaExecTool(sandbox_id="my-long-lived-sandbox")
result = tool.run(command="ls workspace")

커스텀 샌드박스 파라미터

Daytona의 CreateSandboxFromSnapshotParams kwargs를 create_params로 전달하세요:

from crewai_tools import DaytonaExecTool

tool = DaytonaExecTool(
    persistent=True,
    create_params={
        "language": "python",
        "env_vars": {"MY_FLAG": "1"},
        "labels": {"owner": "crewai-agent"},
    },
)

파일 검색, 이동, 수정

from crewai_tools import DaytonaFileTool

file_tool = DaytonaFileTool(persistent=True)

# Find every TODO in the source tree (grep file contents recursively)
file_tool.run(action="find", path="workspace/src", pattern="TODO:")

# Find all Python files (glob match on filenames)
file_tool.run(action="search", path="workspace", pattern="*.py")

# Make a script executable
file_tool.run(action="chmod", path="workspace/run.sh", mode="755")

# Rename or move a file
file_tool.run(
    action="move",
    path="workspace/draft.md",
    destination="workspace/final.md",
)

# Bulk find-and-replace across multiple files
file_tool.run(
    action="replace",
    paths=["workspace/src/a.py", "workspace/src/b.py"],
    pattern="old_function",
    replacement="new_function",
)

# Quick existence check before a destructive op
file_tool.run(action="exists", path="workspace/cache.db")

에이전트 통합 (Agent integration)

from crewai import Agent, Task, Crew
from crewai_tools import DaytonaExecTool, DaytonaPythonTool, DaytonaFileTool

exec_tool = DaytonaExecTool(persistent=True)
python_tool = DaytonaPythonTool(persistent=True)
file_tool = DaytonaFileTool(persistent=True)

coder = Agent(
    role="Sandbox Engineer",
    goal="Write and run code in an isolated environment",
    backstory="An engineer who uses Daytona sandboxes to safely execute code and manage files.",
    tools=[exec_tool, python_tool, file_tool],
    verbose=True,
)

task = Task(
    description="Write a Python script that prints the first 10 Fibonacci numbers, save it to workspace/fib.py, and run it.",
    expected_output="The first 10 Fibonacci numbers printed to stdout.",
    agent=coder,
)

crew = Crew(agents=[coder], tasks=[task])
result = crew.kickoff()

파라미터 (Parameters)

공통 (DaytonaBaseTool)

세 도구 모두 초기화 시 다음 파라미터를 받습니다:

파라미터 타입 기본값 설명
api_key str | None $DAYTONA_API_KEY Daytona API 키. DAYTONA_API_KEY 환경 변수로 대체됩니다.
api_url str | None $DAYTONA_API_URL Daytona API URL 오버라이드.
target str | None $DAYTONA_TARGET Daytona 대상 리전.
persistent bool False 모든 호출에 걸쳐 샌드박스 하나를 재사용하고 프로세스 종료 시 삭제.
sandbox_id str | None None id 또는 이름으로 기존 샌드박스에 연결.
create_params dict | None None CreateSandboxFromSnapshotParams에 전달되는 추가 kwargs (예: language, env_vars, labels).
sandbox_timeout float 60.0 샌드박스 생성/삭제 작업의 타임아웃(초).

DaytonaExecTool

파라미터 타입 필수 설명
command str ✓ 실행할 셸 명령.
cwd str | None 샌드박스 안의 작업 디렉터리.
env dict[str, str] | None 이 명령에 대한 추가 환경 변수.
timeout int | None 명령을 기다릴 최대 초.

DaytonaPythonTool

파라미터 타입 필수 설명
code str ✓ 실행할 Python 소스 코드.
argv list[str] | None CodeRunParams를 통해 전달되는 인자 벡터.
env dict[str, str] | None CodeRunParams를 통해 전달되는 환경 변수.
timeout int | None 실행을 기다릴 최대 초.

DaytonaFileTool

파라미터 타입 필수 설명
action str ✓ 다음 중 하나: read, write, append, list, delete, mkdir, info, exists, move, find, search, chmod, replace.
path str | None replace 제외 모두에 필요 샌드박스 안의 절대 경로.
content str | None append에 필요 쓰거나 추가할 콘텐츠.
binary bool True면 쓰기 시 content가 base64이고, 읽기 시 base64를 반환.
recursive bool delete에서 디렉터리를 재귀적으로 제거.
mode str | None mkdir: 새 디렉터리의 8진수 권한(기본값 "0755"). chmod: 대상에 적용할 8진수 권한.
destination str | None move에 필요 move의 대상 경로.
pattern str | None find, search, replace에 필요 find: 파일 콘텐츠에 매칭되는 부분 문자열. search: 파일 이름에 매칭되는 glob(예: *.py). replace: 파일 안에서 바꿀 텍스트.
replacement str | None replace에 필요 pattern의 교체 텍스트.
paths list[str] | None replace에 필요 텍스트를 바꿀 파일 경로 리스트.
owner str | None chmod: 새 파일 소유자.
group str | None chmod: 새 파일 그룹.

chmod의 경우 mode, owner, group 중 하나 이상을 전달하세요 — None으로 남겨둔 필드는 대상에서 그대로 유지됩니다.

몇 KB를 넘는 파일은 먼저 action="write"로 빈 콘텐츠의 파일을 만든 뒤, 약 4KB씩 여러 번의 action="append" 호출로 본문을 전송해서 도구 호출 페이로드 한도를 지키세요.

더 알아보기 (Learn more)