Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Sandboxes

Accessor: client.Sandboxes()

Manage sandbox lifecycle: create, inspect, delete, attach/detach providers, wait for readiness, watch state changes, and retrieve logs.

Create

Creates a new sandbox with the given name, spec, and labels.

sb, err := client.Sandboxes().Create(ctx, "my-sandbox", &v1.SandboxSpec{
    Template: &v1.SandboxTemplate{
        Image: "nvcr.io/nvidia/openshell:latest",
    },
    Providers: []string{"openai"},
}, map[string]string{
    "team": "platform",
})

Get

Retrieves a sandbox by name.

sb, err := client.Sandboxes().Get(ctx, "my-sandbox")
fmt.Println(sb.Status.Phase) // "Ready", "Provisioning", etc.

List

Lists sandboxes with optional pagination and label filtering.

// List all sandboxes
sandboxes, err := client.Sandboxes().List(ctx)

// With pagination and label filtering
sandboxes, err := client.Sandboxes().List(ctx, v1.ListOptions{
    Limit:         10,
    Offset:        0,
    LabelSelector: "team=platform",
})

Delete

Deletes a sandbox by name.

err := client.Sandboxes().Delete(ctx, "my-sandbox")

AttachProvider

Attaches a provider to a sandbox. The expectedResourceVersion enables optimistic concurrency control: pass the sandbox’s current ResourceVersion to ensure no other client has modified it since your last read.

sb, _ := client.Sandboxes().Get(ctx, "my-sandbox")

result, err := client.Sandboxes().AttachProvider(ctx,
    "my-sandbox",
    "openai",
    sb.ResourceVersion,
)
fmt.Println(result.Attached) // true if newly attached

DetachProvider

Detaches a provider from a sandbox. Uses the same optimistic concurrency pattern as AttachProvider.

sb, _ := client.Sandboxes().Get(ctx, "my-sandbox")

result, err := client.Sandboxes().DetachProvider(ctx,
    "my-sandbox",
    "openai",
    sb.ResourceVersion,
)
fmt.Println(result.Detached) // true if actually detached

ListProviders

Lists all providers currently attached to a sandbox.

providers, err := client.Sandboxes().ListProviders(ctx, "my-sandbox")
for _, p := range providers {
    fmt.Printf("provider: %s (type: %s)\n", p.Name, p.Type)
}

WaitReady

Blocks until the sandbox reaches the Ready phase, returning the final sandbox state. Under the hood, WaitReady polls via Get at a configurable interval (default 500ms). Use context cancellation or deadlines to set a timeout.

If the sandbox enters the Error phase, WaitReady returns immediately with a StatusError.

// Wait with a 30-second timeout
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()

sb, err := client.Sandboxes().WaitReady(ctx, "my-sandbox")
if err != nil {
    log.Fatal(err)
}
fmt.Println(sb.Status.Phase) // "Ready"

// Custom poll interval
sb, err := client.Sandboxes().WaitReady(ctx, "my-sandbox", v1.WaitOptions{
    PollInterval: 2 * time.Second,
})

There is no dedicated WaitReady RPC. The SDK implements this by polling GetSandbox until the sandbox phase is Ready or Error.

Watch

Opens a server-streaming connection to observe sandbox state changes in real time. Returns a WatchInterface[*Sandbox] that delivers events through a channel.

The WatchInterface[T] provides:

  • ResultChan() <-chan Event[T] returns the channel of events
  • Stop() closes the stream and the channel

Each Event[T] carries:

  • Type: one of EventAdded, EventModified, EventDeleted, or EventError
  • Object: the *Sandbox at that point in time (nil for EventError)
watcher, err := client.Sandboxes().Watch(ctx, "my-sandbox")
if err != nil {
    log.Fatal(err)
}
defer watcher.Stop()

for event := range watcher.ResultChan() {
    switch event.Type {
    case v1.EventModified:
        fmt.Printf("phase: %s\n", event.Object.Status.Phase)
    case v1.EventDeleted:
        fmt.Println("sandbox deleted")
        return
    case v1.EventError:
        fmt.Println("watch error")
        return
    }
}

Setting StopOnTerminal: true causes the watcher to close automatically once the sandbox reaches a terminal phase (Ready or Error). This is useful for provisioning flows where you only care about the outcome.

watcher, err := client.Sandboxes().Watch(ctx, "my-sandbox", v1.WatchOptions{
    StopOnTerminal: true,
})
if err != nil {
    log.Fatal(err)
}

for event := range watcher.ResultChan() {
    fmt.Printf("phase: %s\n", event.Object.Status.Phase)
}
// Channel closes after Ready or Error

GetLogs

Retrieves log entries from a sandbox. The sandbox is looked up by name (the SDK resolves the name to an internal ID automatically). Use functional options to filter results.

Available options:

OptionDescription
WithLogLines(n uint32)Maximum number of log lines to return
WithLogSince(t time.Time)Only include entries at or after this time
WithLogSources(sources ...string)Filter by source (e.g., "gateway", "sandbox")
WithLogMinLevel(level string)Minimum log level (e.g., "WARN", "ERROR")
// Get the last 50 log lines
result, err := client.Sandboxes().GetLogs(ctx, "my-sandbox",
    v1.WithLogLines(50),
)
for _, line := range result.Lines {
    fmt.Printf("[%s] %s: %s\n", line.Level, line.Source, line.Message)
}

// Filter by source and level since a specific time
result, err := client.Sandboxes().GetLogs(ctx, "my-sandbox",
    v1.WithLogSources("gateway"),
    v1.WithLogMinLevel("WARN"),
    v1.WithLogSince(time.Now().Add(-1*time.Hour)),
)

The LogResult contains:

  • Lines []LogLine: log entries in chronological order
  • BufferTotal uint32: total number of lines available in the server’s buffer

Each LogLine has Timestamp, Level, Target, Message, Source, and Fields (structured key-value data).

See also: Error Handling, Testing