Skip to content

在沙箱中运行程序 ​

本文档介绍如何通过平台 API 在 Mythra Agent Studio 的沙箱中执行文件或命令,并获取其输出与退出状态。

概述 ​

在 Mythra Agent Studio 中,你可以通过 API 在指定沙箱的隔离容器内运行一个可执行文件或命令,例如:

  • 执行脚本文件:python3 /data/main.py、node /data/index.js、/data/run.sh
  • 执行命令:ls、echo hello、pytest
  • 运行构建、测试等工具链

平台提供了两个能力互补的端点:

  • /execute:一次性执行,等待命令结束后一次性返回完整输出。
  • /execute/sse:通过 Server-Sent Events(SSE)逐行流式返回标准输出与标准错误,适合运行时间较长或需要实时查看输出的场景。

先决条件 ​

在调用 API 之前,你需要准备好以下信息:

  • ProjectID:项目 ID
  • SandboxID:沙箱 ID
  • WDS_API_KEY:有效的 WDS API Key,用于身份验证

身份认证 ​

两个端点都要求进行 WDS Token 认证,以下两种方式任选其一:

  • 通过请求头:Authorization: Bearer <WDS_API_KEY>
  • 通过 Cookie:wds_api_key=<WDS_API_KEY>

如果认证失败,平台会返回 401 Unauthorized。

端点概览 ​

方法端点说明
POST/WebIDE/api/v1/projects/{ProjectID}/sandboxes/{SandboxID}/execute一次性执行,返回完整结果
POST/WebIDE/api/v1/projects/{ProjectID}/sandboxes/{SandboxID}/execute/sse流式执行,逐行返回输出

两个端点的请求体格式完全相同。

请求体 ​

请求体为 JSON 对象:

json
{
  "executable": "node",
  "args": ["/data/hello.js", "--name", "Mythra"],
  "workDir": "/data",
  "env": {
    "NODE_ENV": "production"
  },
  "stdin": "",
  "timeout": 30
}

字段说明 ​

字段类型必填说明
executablestring是要运行的可执行文件或命令,例如 node、python3、bash、./main
argsstring[]否传给可执行文件的参数列表
workDirstring否容器内的工作目录,默认为 /data
envobject否以 key-value 形式注入到进程的环境变量
stdinstring否写入进程标准输入的文本
timeoutint否超时时间(秒),默认值与最大值均为 60

执行环境 ​

  • 沙箱目录会被挂载到容器的 /data,默认工作目录也是 /data。
  • 因此,沙箱根目录下的文件在容器内对应 /data/文件名,也可以直接用相对路径引用(例如 python3 main.py)。
  • 平台实际执行的是 [executable, ...args] 组合而成的容器启动命令。
  • 每次执行都会创建一个临时容器(名称形如 mythra-exec-{userId}-{projectId}-{sandboxId}-{nonce})。
  • 如果超过 timeout 指定的时间,平台会停止容器并返回 timedOut: true。

一次性执行:/execute ​

使用 curl ​

bash
#!/bin/bash

WDS_BASE_URL="https://agent.wiseverds.com"
WDS_API_KEY="WDS_**************"

ProjectID=2231
SandboxID=j4urFhRG

curl -i \
  -X POST \
  -H "Authorization: Bearer $WDS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "executable": "node",
    "args": ["-e", "console.log(\"hello from sandbox\")"],
    "workDir": "/data",
    "timeout": 30
  }' \
  "$WDS_BASE_URL/WebIDE/api/v1/projects/$ProjectID/sandboxes/$SandboxID/execute"

响应示例 ​

json
{
  "result": {
    "exitCode": 0,
    "stdout": "hello from sandbox\n",
    "stderr": "",
    "timedOut": false,
    "container": "mythra-exec-12345678-projabcd-sandbox1-XyZ12345"
  }
}

响应字段说明 ​

字段类型说明
exitCodeint进程退出码,0 通常表示成功
stdoutstring标准输出(超过 1MB 会被截断并追加 [Output truncated])
stderrstring标准错误(超过 1MB 会被截断并追加 [Output truncated])
timedOutbool是否超时
containerstring执行本次命令的容器名称

流式执行:/execute/sse ​

当需要实时查看输出、或命令运行时间较长时,推荐使用 /execute/sse。响应以 text/event-stream 流式返回。

使用 curl ​

bash
#!/bin/bash

WDS_BASE_URL="https://agent.wiseverds.com"
WDS_API_KEY="WDS_**************"

ProjectID=2231
SandboxID=j4urFhRG

curl -N -i \
  -X POST \
  -H "Authorization: Bearer $WDS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "executable": "python3",
    "args": ["/data/main.py"],
    "workDir": "/data",
    "timeout": 60
  }' \
  "$WDS_BASE_URL/WebIDE/api/v1/projects/$ProjectID/sandboxes/$SandboxID/execute/sse"

SSE 输出格式 ​

每个事件都使用 message 作为事件名,data 为 JSON 对象:

json
{ "event": "<事件类型>", "data": "<数据>" }

一条常见的流示例如下:

event: message
data: {"event":"stdout","data":"Hello from Python!"}

event: message
data: {"event":"stderr","data":""}

event: message
data: {"event":"exit","data":"{\"exitCode\":0,\"timedOut\":false,\"container\":\"mythra-exec-...\"}"}

事件类型 ​

事件类型说明
stdout一条标准输出,data 为文本行
stderr一条标准错误,data 为文本行
ping心跳保活,data 为时间戳
exit进程结束,data 为 JSON 字符串,包含 exitCode、timedOut、container
error执行失败,data 为错误信息

使用 JavaScript (fetch) 读取 SSE ​

javascript
const baseUrl = 'https://agent.wiseverds.com';
const apiKey = 'WDS_**************';
const projectId = 2231;
const sandboxId = 'j4urFhRG';

const url = `${baseUrl}/WebIDE/api/v1/projects/${projectId}/sandboxes/${sandboxId}/execute/sse`;

const response = await fetch(url, {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
    'Accept': 'text/event-stream',
  },
  body: JSON.stringify({
    executable: 'python3',
    args: ['/data/main.py'],
    workDir: '/data',
    timeout: 60,
  }),
});

const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
  const { value, done } = await reader.read();
  if (done) break;
  process.stdout.write(decoder.decode(value, { stream: true }));
}

完整示例 ​

假设你的沙箱根目录下有一个 main.py 文件:

python
import sys

print("hello from sandbox")
print("args:", sys.argv[1:], file=sys.stderr)

你可以通过以下请求执行它:

bash
curl -i \
  -X POST \
  -H "Authorization: Bearer $WDS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "executable": "python3",
    "args": ["main.py", "--foo", "bar"],
    "workDir": "/data"
  }' \
  "$WDS_BASE_URL/WebIDE/api/v1/projects/$ProjectID/sandboxes/$SandboxID/execute"

如果文件位于沙箱子目录中,使用对应的相对路径即可,例如 "args": ["scripts/run.py"](相对于 /data),或使用绝对路径 "/data/scripts/run.py"。

执行 Shell 命令 ​

平台是直接以 [executable, ...args] 的形式启动容器进程的,不会经过 Shell 解析。因此 不能 把 executable 直接写成 Shell 内置命令或复合命令,例如:

text
{ "executable": "cd" } ❌
{ "executable": "ls -la | grep foo > out.txt" } ❌

如果需要执行 Shell 命令,请显式调用 Shell,并把完整命令放到 -c 后面的参数中:

json
{
  "executable": "/bin/sh",
  "args": ["-c", "ls -la | grep foo > out.txt"]
}

也可以使用 /bin/bash,用于需要 Bash 特有特性的场景(例如 [[ ]]、数组、$RANDOM 等):

json
{
  "executable": "/bin/bash",
  "args": ["-c", "for f in *.txt; do echo \"$f\"; done"]
}

Shell命令是否需要转义 ​

分两层来看:

  1. JSON 层:整个请求体必须是合法 JSON,命令字符串里出现的双引号、反斜杠、换行等需要按 JSON 规则转义(例如 \"、\\、\n)。这是唯一一层“额外”转义。
  2. Shell 层:命令字符串本身交给 /bin/sh -c 解释,其中 $、|、>、<、&&、引号等符号会按照 Shell 的正常语义生效。也就是说,命令字符串本身就是“最终要交给 Shell 的脚本内容”,不需要再做第二层转义。

例如,以下两种写法是等价的:

写法一(JSON 中把命令里的双引号写成 \"):

json
{ "executable": "/bin/sh", "args": ["-c", "echo \"hello\""] }

写法二(命令里改用单引号,避免转义双引号):

json
{ "executable": "/bin/sh", "args": ["-c", "echo 'hello'"] }

两者最终交给 Shell 的都是 echo "hello"(写法二等价为 echo 'hello'),都能输出 hello。

注意事项 ​

  • 优先使用 /bin/sh:/bin/sh(POSIX)在绝大多数镜像中都可用;只有确实用到 Bash 独有语法时才使用 /bin/bash,因为部分精简镜像可能没有安装 Bash。
  • 不要省略 -c:Shell 的 -c 选项表示“把下一个参数当作命令字符串执行”。如果写成 "args": ["ls -la"],Shell 会把它当作脚本文件名去执行,而不是命令。
  • 多条命令请使用 ;、&& 或 ||:例如 "cd /data && ls -la && python3 main.py",控制执行顺序和错误处理。
  • 建议在脚本开头使用 set -e:如果希望任意一条命令失败即停止并返回非零退出码,可以写成 "set -e; command1; command2"。默认情况下 /bin/sh -c 会继续执行后续命令并返回最后一条命令的退出码。
  • 环境变量可通过 env 字段传入:也可以直接在 Shell 命令中使用 VAR=value command 的临时赋值写法。
  • 重定向与管道是允许的,但写入位置要确认:容器工作目录默认为 /data,重定向生成的 out.txt 会自动落在 /data 下,即对应你的沙箱根目录,之后可在沙箱中查看或同步。
  • 通配符由 Shell 展开:*.txt、$HOME、$(...) 等只有在走 /bin/sh -c 时才会被展开;直接传 executable + args 不会展开。
  • 非交互式 Shell 不会加载启动文件:/bin/sh -c 通常不会读取 ~/.bashrc、~/.profile 等启动文件,若有依赖,请在命令中显式设置。

常见问题 ​

返回 401 Unauthorized ​

请检查 Authorization 头中的 API Key 是否有效,或 Cookie 中是否正确携带了 wds_api_key。

返回 400 Bad Request ​

请检查请求体是否为合法 JSON,以及 executable 字段是否已填写。executable 是必填字段。

返回 404 Not Found ​

指定的沙箱不存在。请确认 ProjectID 和 SandboxID 是否正确。

返回 500 Internal Server Error ​

可能原因包括:Docker 配置加载失败、命令执行失败等。响应中的 error 字段会包含更多信息。

输出被截断 ​

/execute 端点对 stdout 和 stderr 分别设置了 1MB 的返回上限,超过部分会被截断并追加 [Output truncated]。如果需要完整输出,建议改用 /execute/sse 流式读取。

命令运行时间超过 600 秒 ​

两个API端点的超时时间最大为 600 秒。超时后平台会停止容器并返回 timedOut: true。

相关文档 ​

Happy Coding!