跳转到内容

Daytona Sandbox Tools

Daytona sandbox 工具让 CrewAI agents 能访问由 Daytona 提供支持的隔离、短暂存在的计算环境。共有三种工具可用,因此你可以精确地给 agent 提供所需能力:

  • DaytonaExecTool - 在 sandbox 中运行任意 shell 命令。
  • DaytonaPythonTool - 在 sandbox 中执行一段 Python 源码。
  • DaytonaFileTool - 在 sandbox 中读取、写入、追加、列出、删除和检查文件;还支持 movefind(内容 grep)、search(文件名 glob)、chmod(权限)、replace(批量查找替换)和 exists

这三种工具共享同一套 sandbox 生命周期控制,因此你可以灵活组合它们,同时把状态保存在单个持久 sandbox 中。

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

设置 API key:

Terminal window
export DAYTONA_API_KEY="your-api-key"

如果设置了,DAYTONA_API_URLDAYTONA_TARGET 也会被识别。

这三种工具都继承自 DaytonaBaseTool 的生命周期控制:

ModeHow to enableSandbox createdSandbox deleted
Ephemeral (default)persistent=False (default)每次 _run 调用时创建在同一次调用结束时删除
Persistentpersistent=True第一次使用时懒创建在进程退出时通过 atexit 删除,或手动调用 tool.close()
Attachsandbox_id="<id>"从不创建新 sandbox - 只连接到现有 sandbox从不 - 工具不会删除它没有创建的 sandbox

临时模式是安全的默认选择:如果 agent 忘记清理,不会留下任何残留。需要文件系统状态或已安装包在多次工具调用之间保留时,使用持久模式 - 这通常适合把 DaytonaFileToolDaytonaExecTool 配对使用。

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=[])}
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")
from crewai_tools import DaytonaExecTool
tool = DaytonaExecTool(sandbox_id="my-long-lived-sandbox")
result = tool.run(command="ls workspace")

通过 create_params 传入 Daytona 的 CreateSandboxFromSnapshotParams kwargs:

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")
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()

这三种工具在初始化时都接受以下参数:

ParameterTypeDefaultDescription
api_keystr | None$DAYTONA_API_KEYDaytona API key。会回退到 DAYTONA_API_KEY 环境变量。
api_urlstr | None$DAYTONA_API_URLDaytona API URL 覆盖值。
targetstr | None$DAYTONA_TARGETDaytona 目标区域。
persistentboolFalse在所有调用之间复用一个 sandbox,并在进程退出时删除它。
sandbox_idstr | NoneNone通过 id 或 name 连接到已有 sandbox。
create_paramsdict | NoneNone传给 CreateSandboxFromSnapshotParams 的额外 kwargs(例如 languageenv_varslabels)。
sandbox_timeoutfloat60.0sandbox 创建/删除操作的超时时间(秒)。
ParameterTypeRequiredDescription
commandstr要执行的 shell 命令。
cwdstr | Nonesandbox 内的工作目录。
envdict[str, str] | None该命令的额外环境变量。
timeoutint | None等待命令完成的最长秒数。
ParameterTypeRequiredDescription
codestr要执行的 Python 源码。
argvlist[str] | None通过 CodeRunParams 传递的参数向量。
envdict[str, str] | None通过 CodeRunParams 传递的环境变量。
timeoutint | None等待执行完成的最长秒数。
ParameterTypeRequiredDescription
actionstr取值之一:readwriteappendlistdeletemkdirinfoexistsmovefindsearchchmodreplace
pathstr | None✓ for all actions except replacesandbox 内的绝对路径。
contentstr | None✓ for append要写入或追加的内容。
binarybool如果为 True,写入时 content 会被视为 base64;读取时也会返回 base64。
recursivebool对于 delete:递归删除目录。
modestr | None对于 mkdir:新目录的八进制权限(默认 "0755")。对于 chmod:应用到目标的八进制权限。
destinationstr | None✓ for movemove 的目标路径。
patternstr | None✓ for find, search, replace对于 find:与文件内容匹配的子字符串。对于 search:与文件名匹配的 glob(例如 *.py)。对于 replace:要在文件中替换的文本。
replacementstr | None✓ for replacepattern 的替换文本。
pathslist[str] | None✓ for replace需要执行替换的文件路径列表。
ownerstr | None对于 chmod:新的文件 owner。
groupstr | None对于 chmod:新的文件 group。