Sandboxes (ScaiBunker)
ScaiBunker is the sandboxed-compute integration. When a flow needs to execute untrusted-ish code (running a user's Python snippet, sandboxing a tool plugin's side effects, materializing files), it provisions a Bunker, does its work, and tears it down.
The five compute nodes#
| Node | Plugin call | Returns |
|---|---|---|
compute_provision |
scaibunker.create(image, lifecycle, ...) |
bunker handle |
compute_exec |
scaibunker.exec(command, timeout_s) |
exec result |
compute_file_upload |
scaibunker.write_file(path, content) |
— |
compute_file_download |
scaibunker.read_file(path) |
content |
compute_destroy |
scaibunker.destroy() |
— |
All five compile to plugin_call statements (inside the parent rigid block, no nested wrappers).
Lifecycle#
Tied to the Core's activation mode:
ephemeral— provisioned per-invocation, destroyed when the flow exits. The right choice for stateless workloads.session— provisioned per-conversation (entity-mode Cores). Persists across multiple invocations to the same instance.persistent— long-lived, shared across invocations. Use carefully.appliance— v0.2 NetworkSegment-bound profile. Pinned to a specific cluster slice.
The flow-level bunker capability#
In addition to the per-node compute_provision config (which sets the args for the scaibunker.create plugin call), the flow-level flow.config.bunker block declares the manifest-time capability ScaiGrid needs to know about at deploy time:
"bunker": {
"lifecycle": "ephemeral",
"image": "python-3.12",
"cpu_millicores": 1000,
"memory_mb": 512,
"disk_mb": 2048,
"gpu_count": 0,
"network_profile": "registry"
}
The canvas's BunkerCapability editor exposes this in the Flow properties panel. If you leave it unset but have any compute_* node on the canvas, the compiler auto-defaults to {lifecycle: "ephemeral", image: "python-3.12"} so the deploy doesn't fail. Set explicit limits if you need anything bigger.
Network profiles#
Coarse policy on what the Bunker can reach:
| Profile | What it allows |
|---|---|
isolated |
Loopback only. Sandbox can't reach anything. |
registry |
Image registry + a small allowlist for fetching dependencies. Default. |
allowlisted |
network_allowlist is consulted (wildcard subdomains supported). |
unrestricted |
Full egress. Use carefully. |
transit |
Reserved for NetworkSegment-bound profiles. |
Implicit plugin registration#
When any compute_* node lands on the canvas, the compiler auto-adds scaibunker to flow.config.plugins if it isn't there. You don't have to manually maintain that list.
Resources at the flow level vs. per-call args#
The flow-level bunker is the capability declaration — core.capabilities[].bunker in the YAML manifest. The per-compute_provision-node config is the actual args to the scaibunker.create plugin call at runtime. They typically agree, but if you're provisioning multiple distinct Bunkers in one flow you might set different per-call args while the flow-level capability sets the upper bound the cluster allows.
Reading state from the canvas#
The proxy GET /v1/scaibunker/bunkers lists currently-active bunkers visible to your tenant. Wired into the canvas's Live Runs panel as a deferred feature; for now you can hit the proxy directly for ops insight.