Go SDK

The Go SDK provides context-aware, concurrency-safe access to the installed A3S Box runtime. The v3 module requires Go 1.25 or newer.

Install

go get github.com/A3S-Lab/Box/sdk/go/v3

Install the matching A3S Box runtime and verify it with a3s-box info.

Create a Sandbox

package main

import (
    "context"
    "fmt"
    "log"

    box "github.com/A3S-Lab/Box/sdk/go/v3"
)

func main() {
    ctx := context.Background()

    sandbox, err := box.Create(ctx, "alpine:3.20")
    if err != nil {
        log.Fatal(err)
    }
    defer sandbox.Close(context.Background())

    result, err := sandbox.Run(
        ctx,
        box.Argv("sh", "-lc", "printf 'hello from A3S Box'"),
    )
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(result.StdoutString())
}

Use box.Argv(...) for direct execution. Use box.Shell(...) only when guest shell syntax is intentional.

Builder-style CI/CD

package main

import (
    "context"
    "fmt"
    "log"

    box "github.com/A3S-Lab/Box/sdk/go/v3"
)

func main() {
    if err := run(); err != nil {
        log.Fatal(err)
    }
}

func run() error {
    ctx := context.Background()
    client, err := box.NewClient(ctx)
    if err != nil {
        return err
    }

    image, err := client.
        Image("./ci").
        Dockerfile("Dockerfile").
        Tag("local/go-ci:latest").
        BuildArg("GO_VERSION", "1.25").
        Build(ctx)
    if err != nil {
        return err
    }

    sandbox, err := client.
        Sandbox(image.Reference).
        CPUs(4).
        MemoryMiB(4096).
        Start(ctx)
    if err != nil {
        return err
    }
    defer sandbox.Close(context.Background())

    result, err := sandbox.
        Script("go test ./...\n").
        Interpreter("/bin/sh", "-se").
        Env("CI", "true").
        Directory("/workspace").
        Run(ctx)
    if err != nil {
        return err
    }
    if result.ExitCode != 0 {
        return fmt.Errorf("tests failed: %s", result.StderrString())
    }

    return nil
}

Cancellation and errors

Every runtime I/O method accepts context.Context. Set caller deadlines around guest work and lifecycle operations:

package main

import (
    "context"
    "errors"
    "fmt"
    "log"
    "time"

    box "github.com/A3S-Lab/Box/sdk/go/v3"
)

func main() {
    if err := run(); err != nil {
        log.Fatal(err)
    }
}

func run() error {
    sandbox, err := box.Create(context.Background(), "alpine:3.20")
    if err != nil {
        return err
    }
    defer sandbox.Close(context.Background())

    ctx, cancel := context.WithTimeout(
        context.Background(),
        10*time.Minute,
    )
    defer cancel()

    result, err := sandbox.Run(
        ctx,
        box.Argv("sh", "-lc", "sleep 1; printf done"),
    )
    if errors.Is(err, context.DeadlineExceeded) {
        return fmt.Errorf("job deadline exceeded: %w", err)
    }
    if err != nil {
        return err
    }

    fmt.Println(result.StdoutString())
    return nil
}

Use errors.Is for stable categories such as box.ErrNotFound, box.ErrConflict, and box.ErrUnavailable. Use errors.As to inspect the typed *box.Error.

Runtime selection

The SDK resolves A3S_BOX_BINARY and then a3s-box on PATH:

A3S_BOX_BINARY=/opt/a3s/bin/a3s-box go run ./cmd/worker

Command and file data are binary-safe. String helpers are conveniences for text workloads.

See the complete module guide and Go API reference.