> ## Documentation Index
> Fetch the complete documentation index at: https://docs.veadk.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# 代码沙箱

## 功能说明

VeADK 提供一组在 [AgentKit 沙箱](https://console.volcengine.com/agentkit)中远程执行任务的工具：

| 工具 | 说明 |
| :- | :- |
| `run_code` | 执行任意代码或 Shell 命令，适合计算、数据处理、依赖安装等 |
| `execute_skills` | 在预制技能沙箱中运行 `agent.py` 工作流 |
| `coding` | 在 OpenCode 沙箱中运行代码生成工作流 |
| `run_sandbox_agent` | 指定任意 `tool_id` 在远端沙箱执行 `agent.py` |

导入路径：

* `from veadk.tools.builtin_tools.run_code import run_code`
* `from veadk.tools.builtin_tools.execute_skills import execute_skills`
* `from veadk.tools.builtin_tools.coding import coding`
* `from veadk.tools.builtin_tools.run_sandbox_agent import run_sandbox_agent`

## 环境变量与前提

<Warning>
  附加要求：

  1. 配置火山引擎 AK / SK；
  2. 配置用于智能体推理模型的 API Key；
  3. 配置 AgentKit Tool ID（见下文）。
</Warning>

环境变量：

* `MODEL_AGENT_API_KEY`：智能体推理模型的 API Key
* `VOLCENGINE_ACCESS_KEY` / `VOLCENGINE_SECRET_KEY`：火山引擎 AK / SK
* `AGENTKIT_TOOL_ID`：默认 AgentKit 沙箱 ID，作为所有沙箱工具的兜底配置
* `AGENTKIT_TOOL_ID_SCRIPT`：`run_code` 专用沙箱 ID，未配置时回退到 `AGENTKIT_TOOL_ID`
* `AGENTKIT_TOOL_ID_SKILLS`：`execute_skills` 专用沙箱 ID，未配置时回退到 `AGENTKIT_TOOL_ID`
* `AGENTKIT_TOOL_ID_OPENCODE`：`coding` 专用沙箱 ID，未配置时回退到 `AGENTKIT_TOOL_ID`
* `AGENTKIT_TOOL_HOST`：调用 AgentKit Tools 的 Endpoint
* `AGENTKIT_TOOL_SERVICE_CODE`：调用 AgentKit Tools 的 ServiceCode

`config.yaml` 配置项：

```yaml title="config.yaml" lines theme={null}
agentkit:
  tool_id: your-default-tool-id
  tool_id_script: your-script-tool-id
  tool_id_skills: your-skills-tool-id
  tool_id_opencode: your-opencode-tool-id
```

创建沙箱：

<Steps>
  <Step title="创建沙箱工具">
    在控制台创建沙箱工具：自定义名称（如 `AIO_Sandbox_xxxx`），工具集类型选择“一体化工具集”，包含 Browser、Terminal、Code 运行环境。
  </Step>

  <Step title="获取沙箱 ID">
    创建完成后，在控制台获取沙箱 ID（形如 `t-ye8dj82xxxxx`），填入上面的环境变量或 `config.yaml`。
  </Step>
</Steps>

## 使用方法

```python title="examples/tools/run_code/agent.py" lines theme={null}
import asyncio

from veadk import Agent, Runner
from veadk.memory.short_term_memory import ShortTermMemory
from veadk.tools.builtin_tools.run_code import run_code
from veadk.tools.builtin_tools.web_search import web_search

agent = Agent(
    name="data_analysis_agent",
    model_name="doubao-seed-2-1-pro-260628",
    description="A data analysis agent for the stock market.",
    instruction=(
        "你是一名资深工程师，在沙箱中执行代码。可使用 web_search 搜索公司经营数据，"
        "可使用 akshare 等库下载股票数据；缺失依赖时用代码在沙箱中安装。"
    ),
    tools=[run_code, web_search],
)

runner = Runner(agent=agent, short_term_memory=ShortTermMemory())


async def main():
    response = await runner.run("分析阳光电源最近的股价走势")
    print(response)


if __name__ == "__main__":
    asyncio.run(main())
```

## 执行 Shell 命令

`run_code` 除了执行 Python 等代码外，还支持在沙箱中执行 Shell 命令。当 `language` 取值为 `bash` 或 `shell` 时，`code` 将作为 Shell 命令在远端沙箱中执行，适合文件操作、依赖安装、命令行工具调用等场景。

执行 Shell 命令时复用 `run_code` 的沙箱 ID 与凭证配置，`code` 内容会作为命令提交，可在单次执行中串接多条命令。

<Warning>
  Shell 可在远端沙箱中执行任意命令、安装依赖、读写文件，并访问沙箱网络可达的服务。运行前应确认命令来源可信，并限制沙箱可访问的数据、网络和权限；不要在命令或 `env` 中写入长期凭证，需要凭证时使用沙箱支持的凭据托管方式。
</Warning>

### 参数

`run_code` 的完整签名如下：

```python lines theme={null}
def run_code(
    code: str,
    language: str,
    tool_context: ToolContext,
    timeout: int = 30,
    exec_dir: str = "/tmp",
    env: dict[str, str] | None = None,
    hard_timeout: int = 300,
    max_output_length: int = 30000,
) -> str:
    ...
```

| 参数 | 类型 | 默认值 | 说明 |
| :- | :- | :- | :- |
| `code` | `str` | — | 要执行的代码或 Shell 命令。 |
| `language` | `str` | — | 执行语言。执行代码时取 `python3`；执行 Shell 命令时取 `bash` 或 `shell`。 |
| `tool_context` | `ToolContext` | — | 工具运行时上下文，由 VeADK 自动注入。 |
| `timeout` | `int` | `30` | 命令执行的超时时间，单位为秒。 |
| `exec_dir` | `str` | `/tmp` | Shell 执行的工作目录。 |
| `env` | `dict[str, str] \| None` | `None` | Shell 执行使用的环境变量。 |
| `hard_timeout` | `int` | `300` | Shell 执行的硬超时时间，单位为秒。 |
| `max_output_length` | `int` | `30000` | Shell 输出的最大长度。 |

`exec_dir`、`env`、`hard_timeout` 和 `max_output_length` 仅在执行 Shell 命令（`language` 为 `bash` 或 `shell`）时生效；执行代码时由沙箱运行时管理，不适用这些参数。

### 使用示例

```python title="run_code_bash.py" lines theme={null}
import asyncio

from google.adk.tools import ToolContext
from veadk import Agent, Runner
from veadk.memory.short_term_memory import ShortTermMemory
from veadk.tools.builtin_tools.run_code import run_code


def check_python(tool_context: ToolContext) -> str:
    """在远端沙箱中查看 Python 版本。"""
    return run_code(
        code="pwd && python --version",
        language="bash",
        tool_context=tool_context,
        timeout=60,
        exec_dir="/tmp",
        env={"APP_ENV": "test"},
        hard_timeout=120,
        max_output_length=5000,
    )


agent = Agent(
    name="shell_agent",
    instruction="调用工具查看远端沙箱的工作目录和 Python 版本。",
    tools=[check_python],
)
runner = Runner(agent=agent, short_term_memory=ShortTermMemory())


async def main():
    response = await runner.run("检查沙箱环境")
    print(response)


if __name__ == "__main__":
    asyncio.run(main())
```

## 为沙箱执行注入环境变量

`execute_skills` 和 `run_sandbox_agent` 支持向本次沙箱执行注入自定义环境变量，用于向技能或沙箱内的工作流传入运行时参数（如配置项、凭证引用、特性开关等）。注入的环境变量仅在本次执行生效，不会持久化到沙箱基础环境。

`execute_skills` 通过 `env_vars` 参数注入；`run_sandbox_agent` 通过 `extra_env_vars` 参数注入。两者共享同一套校验与合并规则。

### 参数

| 参数 | 类型 | 默认值 | 说明 |
| :- | :- | :- | :- |
| `env_vars` | `Optional[dict[str, str]]` | `None` | `execute_skills` 注入的环境变量，键值均为字符串，仅在本次执行生效。 |
| `extra_env_vars` | `Optional[dict[str, str]]` | `None` | `run_sandbox_agent` 注入的环境变量，键值均为字符串，仅在本次执行生效。 |

### 校验规则

注入的环境变量会与 VeADK 框架自管理变量合并后传给沙箱进程，并按以下规则校验：

* 变量名必须匹配 `^[A-Za-z_][A-Za-z0-9_]*$`，否则初始化会报错。
* `TOOL_USER_SESSION_ID` 与 `USER_SESSION_ID` 由 VeADK 管理，不可通过自定义变量覆盖，否则初始化会报错。
* 变量值必须是字符串；非字符串值会报错。
* 变量值不能包含空字节（`\x00`），否则初始化会报错。
* 自定义变量会覆盖沙箱进程环境中的同名变量（包括 VeADK 默认设置的 `TOS_SKILLS_DIR`、`SKILL_SPACE_ID` 等），可用于按需调整本次执行的资源路径。

### 使用示例

下面的示例将两种调用封装为函数工具。`Runner` 调用函数工具时会注入 `tool_context`，应用只需在封装函数中设置本次执行需要的环境变量：

```python title="sandbox_env.py" lines theme={null}
import asyncio

from google.adk.tools import ToolContext
from veadk import Agent, Runner
from veadk.memory.short_term_memory import ShortTermMemory
from veadk.tools.builtin_tools.execute_skills import execute_skills
from veadk.tools.builtin_tools.run_sandbox_agent import run_sandbox_agent


def run_skill_workflow(workflow_prompt: str, tool_context: ToolContext) -> str:
    """在技能沙箱中运行工作流。"""
    return execute_skills(
        workflow_prompt=workflow_prompt,
        tool_context=tool_context,
        env_vars={
            "SKILL_CONFIG_PATH": "/tmp/skill_config.yaml",
            "MAX_RESULTS": "20",
        },
    )


def run_custom_workflow(workflow_prompt: str, tool_context: ToolContext) -> str:
    """在指定的 AgentKit 沙箱中运行工作流。"""
    return run_sandbox_agent(
        workflow_prompt=workflow_prompt,
        tool_id="t-your-sandbox-tool-id",
        tool_context=tool_context,
        extra_env_vars={"DATA_SOURCE_URL": "https://example.com/data.csv"},
    )


agent = Agent(
    name="sandbox_agent",
    instruction="根据用户要求调用合适的沙箱工作流。",
    skills=["space:your-skill-space-id"],
    skills_mode="skills_sandbox",
    tools=[run_skill_workflow, run_custom_workflow],
)
runner = Runner(agent=agent, short_term_memory=ShortTermMemory())


async def main():
    response = await runner.run("使用技能工作流读取知识库并生成摘要")
    print(response)


if __name__ == "__main__":
    asyncio.run(main())
```

<Warning>
  `env_vars` 和 `extra_env_vars` 的值会传入远端沙箱进程。不要在代码中写入长期凭证；需要凭证时，使用沙箱支持的凭据托管方式。
</Warning>
