跳到主要内容

RailwaySandbox

在临时、隔离的 Railway Sandbox 中执行命令。每个 Sandbox 都是通过 Railway TypeScript SDK 按需配置的隔离 Debian Linux VM。支持执行命令并以 streaming 方式传输输出、命令超时、可配置的空闲超时、ISOLATED/PRIVATE 网络隔离、通过 Railway template builder 使用自定义基础镜像、基于 checkpoint 的恢复、fork 正在运行的 Sandbox,以及按 ID 重新连接到现有 Sandbox。有关接口详情,请参阅 WorkspaceSandbox 接口

安装
安装的直接链接

npm install @mastra/railway

可通过以下三种方式之一设置 Railway 凭据。

export RAILWAY_API_TOKEN=your-api-token
export RAILWAY_ENVIRONMENT_ID=your-environment-id

用法
用法的直接链接

RailwaySandbox 添加到 Workspace,并将其分配给 Agent:

import { Agent } from '@mastra/core/agent'
import { Workspace } from '@mastra/core/workspace'
import { RailwaySandbox } from '@mastra/railway'

const workspace = new Workspace({
sandbox: new RailwaySandbox({
// token + environmentId read from RAILWAY_API_TOKEN / RAILWAY_ENVIRONMENT_ID
idleTimeoutMinutes: 30,
}),
})

const agent = new Agent({
id: 'code-agent',
name: 'Code Agent',
instructions: 'You are a coding assistant working in this workspace.',
model: 'anthropic/claude-sonnet-4-6',
workspace,
})

const response = await agent.generate(
'Print "Hello, world!" and show the current working directory.',
)

console.log(response.text)

私有网络
私有网络的直接链接

加入环境的私有网络,以访问其他 Railway 服务(例如 postgres.railway.internal):

const workspace = new Workspace({
sandbox: new RailwaySandbox({
networkIsolation: 'PRIVATE',
env: { NODE_ENV: 'production' },
}),
})

默认的 ISOLATED 模式仅允许访问外部互联网,不允许连接私有网络。

自定义基础镜像(template)
自定义基础镜像(template)的直接链接

预先安装软件包并运行设置步骤,让每个 Sandbox 启动后即可使用。传入 Railway template builder 的 builder 回调;template 会在首次调用 start() 时构建一次:

const workspace = new Workspace({
sandbox: new RailwaySandbox({
template: t => t.withPackages('git', 'curl').run('npm i -g pnpm').workdir('/app'),
}),
})

也可以传入预先构建的 SandboxTemplate,在多个 Sandbox 之间复用而无需重新构建。设置 sandboxId 时会忽略 template,因为重新连接会使用现有 Sandbox 的文件系统。

Fork 正在运行的 Sandbox
Fork 正在运行的 Sandbox的直接链接

将正在运行的 Sandbox 文件系统克隆到新的独立 Sandbox 中。这会执行全新启动,不会克隆正在运行的进程。返回的 RailwaySandbox 已经启动:

const child = await sandbox.fork({ idleTimeoutMinutes: 15 })

const result = await child.executeCommand('cat', ['/app/state.json'])
console.log(result.stdout)

除非通过 fork() 选项覆盖,否则 fork 后的 Sandbox 会继承父级的凭据和默认值。

Checkpoint 恢复
Checkpoint 恢复的直接链接

设置 checkpointName,可在 Railway Sandbox 被替换后保留其文件系统。调用 start() 时,RailwaySandbox 会首先尝试从 checkpoint 创建 Sandbox。如果 checkpoint 不存在,则会根据配置的 template 或默认镜像创建 Sandbox,然后捕获 checkpoint。

const sandbox = new RailwaySandbox({
checkpointName: 'project-session-42',
idleTimeoutMinutes: 30,
})

RailwaySandbox 会在空闲超时前不久刷新 checkpoint。恢复时会还原最近一次成功的 checkpoint,但不会还原正在运行的进程,也不会还原上次 checkpoint 后写入文件系统的内容。

请为每个独立文件系统使用一个稳定的 checkpoint 名称。不要在不相关的 Session 或项目之间共享 checkpoint 名称。

克隆后的 Sandbox checkpoint
克隆后的 Sandbox checkpoint的直接链接

当已配置的 RailwaySandbox 作为 Sandbox 集群的 template 时,请使用 clone({ checkpointName })

const template = new RailwaySandbox({ idleTimeoutMinutes: 30 })

const sessionSandbox = template.clone({
id: 'session-42',
checkpointName: 'project-session-42',
})

await sessionSandbox.start()

克隆后的 Sandbox 使用传给 clone() 的 checkpoint。如果未传入覆盖值,则继承 template Sandbox 的 checkpointName

Streaming 输出
Streaming 输出的直接链接

通过 onStdoutonStderr 回调实时以 streaming 方式传输命令输出:

await sandbox.executeCommand('bash', ['-c', 'for i in 1 2 3; do echo "line $i"; sleep 1; done'], {
onStdout: chunk => process.stdout.write(chunk),
onStderr: chunk => process.stderr.write(chunk),
})

两个回调均为可选,并且可以单独使用。

重新连接到现有 Sandbox
重新连接到现有 Sandbox的直接链接

Railway Sandbox 的生命周期可以超过创建它的进程。通过 Railway ID 重新连接,而无需配置新的 Sandbox:

const sandbox = new RailwaySandbox({ sandboxId: 'existing-railway-sandbox-id' })
await sandbox._start()

const result = await sandbox.executeCommand('cat', ['/tmp/state.txt'])

构造函数参数
构造函数参数的直接链接

id?:

string
= 自动生成
此 Sandbox 实例的唯一标识符。

token?:

string
用于身份验证的 Railway API token。未提供时使用 RAILWAY_API_TOKEN 环境变量。

environmentId?:

string
Railway 环境 ID。未提供时使用 RAILWAY_ENVIRONMENT_ID 环境变量。

sandboxId?:

string
按 Railway ID 重新连接到现有 Railway Sandbox,而不是创建新 Sandbox。设置后,start() 会调用 Sandbox.connect()。

checkpointName?:

string
命名的 Railway checkpoint,用于初始化新 Sandbox,并在因空闲而拆除前保留文件系统。请为每个独立文件系统使用唯一且稳定的名称。

idleTimeoutMinutes?:

number
Railway 自动销毁 Sandbox 前,Sandbox 可保持空闲(无 exec 交互)的时长。有效范围和默认值取决于你的 Railway 套餐。

networkIsolation?:

'ISOLATED' | 'PRIVATE'
= 'ISOLATED'
网络访问模式。'ISOLATED' 仅允许访问外部互联网;'PRIVATE' 会加入环境的私有网络。

env?:

Record<string, string>
= {}
写入 Sandbox 并可供每个命令使用的环境变量。

template?:

SandboxTemplate | (base: SandboxTemplate) => SandboxTemplate
使用 Railway template builder 构建的自定义基础镜像来配置 Sandbox。接受 builder 回调或预先构建的 template。设置 sandboxId 时会忽略。

timeout?:

number
应用于未指定自身超时时间的命令的默认执行超时时间(以毫秒为单位)。省略时,命令会一直运行到退出。

instructions?:

string | (opts) => string
覆盖默认 Agent instructions。字符串会将其完全替换;函数会接收默认 instructions 并返回最终文本。

属性
属性的直接链接

id:

string
Sandbox 实例标识符。

name:

string
Provider 名称('RailwaySandbox')。

provider:

string
Provider 标识符('railway')。

status:

ProviderStatus
'pending' | 'initializing' | 'ready' | 'stopped' | 'destroyed' | 'error'

railway:

Sandbox
用于直接访问 SDK 的底层 Railway Sandbox 实例。如果 Sandbox 尚未启动,则抛出 SandboxNotReadyError。

processes:

RailwayProcessManager
后台进程管理器。请参阅 SandboxProcessManager 参考

方法
方法的直接链接

fork:

(options?) => Promise<RailwaySandbox>
将此正在运行的 Sandbox 克隆到新的独立 RailwaySandbox。返回的 Sandbox 已启动,并已重新连接到 fork 后的 Railway Sandbox。接受可选的 id、idleTimeoutMinutes、networkIsolation 和 env 覆盖值。如果此 Sandbox 尚未启动,则抛出 SandboxNotReadyError。

clone:

(options?) => RailwaySandbox
构造一个尚未启动、继承凭据和默认值的同级 Sandbox。接受可选的 id、sandboxId、env、idleTimeoutMinutes 和 checkpointName 覆盖值。设置 options.checkpointName 时,克隆后的 Sandbox 使用该值,否则继承 template 的 checkpointName。

后台进程
后台进程的直接链接

RailwaySandbox 内置了用于生成和管理后台进程的进程管理器。每个生成的进程都作为一个 Railway exec Session 运行。

const sandbox = new RailwaySandbox()
await sandbox.start()

// Spawn a background process
const handle = await sandbox.processes.spawn('node server.js', {
env: { PORT: '3000' },
onStdout: data => console.log(data),
})

// Interact with the process
console.log(handle.stdout)
await handle.kill()

Railway 的 exec API 不支持 streaming stdin,因此不支持 sendStdin()

有关完整 API,请参阅 SandboxProcessManager 参考

Editor Provider
Editor Provider的直接链接

MastraEditor 中注册该 Provider,可将已存储的 Sandbox 配置还原为运行时实例:

import { railwaySandboxProvider } from '@mastra/railway'

const editor = new MastraEditor({
sandboxes: { [railwaySandboxProvider.id]: railwaySandboxProvider },
})

有关注册自定义 Sandbox Provider 的详情,请参阅 Sandbox Provider 参考