Skip to content
CrewAI 文档版本 跟随上游 源快照 336f5d14 更新于 2026-10-18

Daytona 沙箱工具

在隔离的 Daytona 沙箱中运行 shell 命令、执行 Python 以及管理文件。

Daytona 沙箱工具

描述

Daytona 沙箱工具让 CrewAI 智能体可以访问由 Daytona 提供支持的隔离、临时计算环境。共有三个工具可用,因此你可以精确地赋予智能体所需的能力:

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

这三个工具共享相同的沙箱生命周期控制,因此你可以混合搭配使用它们,同时将状态保存在单个持久化沙箱中。

安装

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

设置你的 API key:

shell
export DAYTONA_API_KEY="your-api-key"

如果设置了 DAYTONA_API_URL 和 DAYTONA_TARGET,它们也会被采用。

沙箱生命周期

这三个工具都从 DaytonaBaseTool 继承生命周期控制:

模式启用方式创建沙箱删除沙箱
临时(默认)persistent=False(默认)每次调用 _run 时在同一次调用结束时
持久persistent=True首次使用时惰性创建进程退出时(通过 atexit),或通过 tool.close() 手动删除
附加sandbox_id="<id>"从不创建 —— 附加到现有沙箱从不删除 —— 工具不会删除非自己创建的沙箱

临时模式是安全的默认值:即使智能体忘记清理,也不会有任何残留。当你希望文件系统状态或已安装的包在多次工具调用之间保留时,请使用持久模式——这在将 DaytonaFileTool 与 DaytonaExecTool 搭配使用时很典型。

示例

一次性 Python 执行(临时)

python
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=[])}

多步骤 shell 会话(持久)

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

NOTE

默认情况下,每个设置了 persistent=True 的工具都会在首次使用时惰性创建它自己的沙箱。上面的模式通过在调用 .run() 后读取第一个工具的 active_sandbox_id,并通过 sandbox_id=... 将其传给其他工具,从而在多个工具之间共享同一个沙箱。当 persistent=False(默认值)时,每次 .run() 调用都会获得一个新的沙箱,并在该次调用结束时被删除。

附加到现有沙箱

python
from crewai_tools import DaytonaExecTool

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

自定义沙箱参数

通过 create_params 传入 Daytona 的 CreateSandboxFromSnapshotParams 关键字参数:

python
from crewai_tools import DaytonaExecTool

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

搜索、移动和修改文件

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

智能体集成

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

参数

共享参数(DaytonaBaseTool)

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

参数类型默认值描述
api_keystr | None$DAYTONA_API_KEYDaytona API 密钥。回退到 DAYTONA_API_KEY 环境变量。
api_urlstr | None$DAYTONA_API_URLDaytona API URL 覆盖值。
targetstr | None$DAYTONA_TARGETDaytona 目标区域。
persistentboolFalse在所有调用之间复用一个沙箱,并在进程退出时删除它。
sandbox_idstr | NoneNone通过 id 或名称附加到现有沙箱。
create_paramsdict | NoneNone转发给 CreateSandboxFromSnapshotParams 的额外关键字参数(例如 language、env_vars、labels)。
sandbox_timeoutfloat60.0沙箱创建/删除操作的超时时间(秒)。

DaytonaExecTool

参数类型是否必填描述
commandstr✓要执行的 shell 命令。
cwdstr | None沙箱内的工作目录。
envdict[str, str] | None该命令的额外环境变量。
timeoutint | None等待该命令的最长秒数。

DaytonaPythonTool

参数类型是否必填描述
codestr✓要执行的 Python 源代码。
argvlist[str] | None通过 CodeRunParams 转发的参数向量。
envdict[str, str] | None通过 CodeRunParams 转发的环境变量。
timeoutint | None等待执行的最长秒数。

DaytonaFileTool

参数类型是否必填描述
actionstr✓以下之一:read、write、append、list、delete、mkdir、info、exists、move、find、search、chmod、replace。
pathstr | None除 replace 外的所有操作必填沙箱内的绝对路径。
contentstr | Noneappend 时必填要写入或追加的内容。
binarybool若为 True,写入时 content 为 base64;读取时返回 base64。
recursivebool用于 delete:递归删除目录。
modestr | None用于 mkdir:新目录的八进制权限(默认为 "0755")。用于 chmod:应用于目标的八进制权限。
destinationstr | Nonemove 时必填move 的目标路径。
patternstr | Nonefind、search、replace 时必填用于 find:与文件内容匹配的子串。用于 search:与文件名匹配的 glob(例如 *.py)。用于 replace:在文件中要替换的文本。
replacementstr | Nonereplace 时必填pattern 的替换文本。
pathslist[str] | Nonereplace 时必填要在其中替换文本的文件路径列表。
ownerstr | None用于 chmod:新的文件所有者。
groupstr | None用于 chmod:新的文件组。

NOTE

对于 chmod,至少传入 mode、owner 或 group 之一——任何留为 None 的字段在目标上保持不变。

TIP

对于大于几 KB 的文件,先用 action="write" 和空内容创建文件,然后通过多次每次 ~4 KB 的 action="append" 调用发送正文,以保持在工具调用负载限制之内。

BytesRouter 是社区翻译站点,所有译文仅供参考,一切以官方英文原文为准。