Skip to content

feat(sdk): Go SDK with oapi-codegen for Lifecycle, Execd, and Egress APIs#597

Open
AlexandrePh wants to merge 23 commits intoalibaba:mainfrom
AlexandrePh:feat/go-sdk
Open

feat(sdk): Go SDK with oapi-codegen for Lifecycle, Execd, and Egress APIs#597
AlexandrePh wants to merge 23 commits intoalibaba:mainfrom
AlexandrePh:feat/go-sdk

Conversation

@AlexandrePh
Copy link
Copy Markdown

@AlexandrePh AlexandrePh commented Mar 29, 2026

Summary

Go SDK with oapi-codegen for all 3 OpenSandbox APIs, plus a high-level Sandbox object matching the Python/JS/C#/Java SDKs.

  • Generated clients (opensandbox/api/) from OpenAPI specs via oapi-codegen
  • High-level API: CreateSandbox(), ConnectSandbox(), SandboxManager, CodeInterpreter
  • ConnectionConfig with env var fallbacks, WaitUntilReady() with custom health checks
  • Structured Execution model with stdout/stderr, exit codes, and event handlers
  • Spec-compliant nested error/results parsing with backward compat for legacy flat format
  • SSE/NDJSON hybrid streaming (with StreamEvent.Event populated from NDJSON type field), multipart upload, file download
  • 39 e2e tests across sandbox lifecycle, commands, filesystem, code interpreter, manager, volumes, concurrent creation, error handling
  • 3 real scenario tests using live LLM (Azure OpenAI via Bifrost): agent loop, multi-turn code interpreter, shell tool use
  • 2 runnable examples: examples/agent_loop/ and examples/code_interpreter_agent/

Closes #596

Testing

  • Unit tests (18 tests, httptest mocks)
  • Integration tests (staging, low-level client)
  • e2e / manual verification (39 tests against live K8s staging + Bifrost LLM gateway)
  • All 20 review comments addressed and resolved

Breaking Changes

  • None

Checklist

  • Linked Issue or clearly described motivation
  • Added/updated docs (README.md, examples/)
  • Added/updated tests (18 unit + 39 e2e + 3 scenario tests)
  • Security impact considered (env vars only, no hardcoded credentials, API key rotated)
  • Backward compatibility considered (new SDK, no existing consumers)

Architecture

sdks/sandbox/go/
  opensandbox/
    api/
      specs/                    # Patched OpenAPI specs (3.0.3 for codegen compat)
      lifecycle/gen.go          # Generated from sandbox-lifecycle.yml
      execd/gen.go              # Generated from execd-api.yaml
      egress/gen.go             # Generated from egress-api.yaml
    config.go                   # ConnectionConfig with env var fallbacks
    constants.go                # DefaultExecdPort, DefaultTimeout, etc.
    errors.go                   # SandboxReadyTimeoutError, etc.
    execution.go                # Structured Execution model + nested error/results parsing
    sandbox.go                  # High-level Sandbox object
    manager.go                  # SandboxManager for admin operations
    code_interpreter.go         # CodeInterpreter wrapper
    http.go                     # Base HTTP client with configurable timeout/headers
    streaming.go                # SSE/NDJSON hybrid parser (4MiB buffer, type extraction)
    types.go                    # Type definitions (spec-aligned)
    lifecycle.go, execd.go, egress.go  # Low-level clients
  examples/
    agent_loop/                 # LLM agent: task → code → execute → result
    code_interpreter_agent/     # Multi-turn agent with persistent Python state
tests/go/
  tests/
    sandbox_e2e_test.go         # 13 lifecycle tests
    command_e2e_test.go         # 7 command tests
    filesystem_e2e_test.go      # 6 filesystem tests
    code_interpreter_e2e_test.go # 6 code interpreter tests
    manager_e2e_test.go         # 3 manager tests
    volume_e2e_test.go          # 3 volume mount tests
    concurrent_e2e_test.go      # 1 concurrent creation test
    error_handling_e2e_test.go  # 1 x-request-id test
    scenario_agent_e2e_test.go  # 3 real LLM agent tests

Copilot AI review requested due to automatic review settings March 29, 2026 16:09
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Mar 29, 2026

CLA assistant check
All committers have signed the CLA.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Go SDK (stdlib-only) for OpenSandbox’s Lifecycle, Execd, and Egress APIs, including an SSE streaming implementation and an httptest-based test suite.

Changes:

  • Introduce typed Go clients for Lifecycle, Execd, and Egress APIs plus shared HTTP/error helpers.
  • Implement SSE streaming support used by Execd streaming endpoints.
  • Add Go module scaffolding, README, Makefile, and a test suite covering core behaviors.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
sdks/sandbox/go/opensandbox/types.go Shared SDK types and error types used across clients
sdks/sandbox/go/opensandbox/http.go Base HTTP client, JSON helpers, and API error handling
sdks/sandbox/go/opensandbox/streaming.go SSE parsing + streaming request helper
sdks/sandbox/go/opensandbox/lifecycle.go Lifecycle API client methods (create/get/list/etc.)
sdks/sandbox/go/opensandbox/egress.go Egress policy client methods
sdks/sandbox/go/opensandbox/execd.go Execd client methods (SSE execution, files, dirs, metrics)
sdks/sandbox/go/opensandbox/opensandbox_test.go httptest-based unit tests for clients + SSE behavior
sdks/sandbox/go/go.mod New Go module definition for the SDK
sdks/sandbox/go/README.md Installation, examples, and API reference documentation
sdks/sandbox/go/Makefile Build/vet/test/lint targets for the SDK module

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@AlexandrePh AlexandrePh marked this pull request as draft March 29, 2026 18:57
@AlexandrePh AlexandrePh marked this pull request as ready for review March 30, 2026 04:05
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 70f495e992

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@AlexandrePh AlexandrePh marked this pull request as draft March 30, 2026 04:50
…APIs

- oapi-codegen generates typed clients from all 3 OpenAPI specs
- Hand-written ergonomic wrapper for SSE/NDJSON streaming, multipart uploads, file downloads
- 18 unit tests + integration test (local) + staging test (remote K8s)
- `make generate` target + `go generate ./...` for spec-driven regeneration
- All review feedback addressed (streaming timeout, scanner buffer, type safety, FileMode encoding)
- No hardcoded credentials — staging tests require STAGING_URL and STAGING_API_KEY env vars

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@AlexandrePh AlexandrePh changed the title feat(sdk): Go SDK for Lifecycle, Execd, and Egress APIs feat(sdk): Go SDK with oapi-codegen for Lifecycle, Execd, and Egress APIs Mar 30, 2026
@Pangjiping
Copy link
Copy Markdown
Collaborator

Great Job! It's great to see the SDK for a new language. 🎉🎉

Perhaps you could refer to the e2e tests under the tests directory for the other languages and add some simple real e2e tests for Golang?

@AlexandrePh
Copy link
Copy Markdown
Author

All review feedback addressed

The branch was squashed into a single clean commit. All 10 Copilot and 2 Codex review comments from the previous revision are addressed:

# Issue Fix
1 Package doc missing Execd types.go:1 — "Lifecycle, Egress, and Execd APIs"
2 30s timeout kills SSE http.godefaultTimeout = 0
3 WithTimeout nil panic http.go — stores *time.Duration, applies after all options with nil guard
4 Silent cursor parse error execd.go — returns fmt.Errorf on invalid cursor header
5 go 1.24 vs 1.24.0 go.modgo 1.24.0
6 64K scanner buffer streaming.go — 4 MiB buffer via scanner.Buffer()
7 Missing JSON content-type on metadata execd.goCreatePart with Content-Type: application/json
8 Local path leaked in upload execd.gofilepath.Base(localPath)
9 Unused recursive param execd.go — removed from DeleteDirectory
10 Port as string, missing proxy param lifecycle.goport int, useServerProxy *bool
11 Codex P1: FileMode string execd.gofmt.Sprintf("%o", mode) sends octal string
12 Codex P1: FileMode decimal Same fix as #11

Additionally:

  • Switched to oapi-codegen — types and clients generated from OpenAPI specs
  • Removed hardcoded credentials — staging tests now require STAGING_URL and STAGING_API_KEY env vars
  • Added make generate target for spec-driven regeneration

@AlexandrePh
Copy link
Copy Markdown
Author

Thanks for the feedback! 🙏

We're actively working on this — the plan is:

  1. High-level Sandbox object — matching the Python/JS/C#/Java SDKs with Sandbox.Create(), WaitUntilReady(), .Commands, .Files, .Metrics accessors, and auto-endpoint resolution
  2. ConnectionConfig — shared config with env var fallbacks (OPEN_SANDBOX_DOMAIN, OPEN_SANDBOX_API_KEY)
  3. SandboxManager — list, filter, kill operations
  4. Structured Execution model — stdout/stderr logs, exit code, event handlers (replacing raw SSE callbacks)
  5. E2E tests in tests/go/ — following the same patterns and env vars as the other language test suites (sandbox lifecycle, command execution, filesystem ops, manager)

Will push an update soon.

High-level API matching Python/JS/C#/Java SDKs:
- ConnectionConfig: shared config with env var fallbacks (OPEN_SANDBOX_DOMAIN, OPEN_SANDBOX_API_KEY)
- Sandbox: high-level object with CreateSandbox(), ConnectSandbox(), auto-endpoint resolution, WaitUntilReady()
- SandboxManager: list, filter, kill, pause, resume, renew operations
- Execution model: structured stdout/stderr, exit codes, event handlers
- Error types: SandboxReadyTimeoutError, SandboxUnhealthyError, InvalidArgumentError
- Constants: DefaultExecdPort, DefaultTimeoutSeconds, DefaultResourceLimits, etc.

E2E tests in tests/go/ (12 tests, all passing against live staging):
- Sandbox lifecycle: create, info, metrics, renew, endpoint, kill
- Command execution: simple run, handlers, exit codes, multi-line
- Filesystem: file info, write + read via commands
- Manager: list, filter by state, get + kill

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@AlexandrePh
Copy link
Copy Markdown
Author

Done! Pushed the high-level API and e2e tests.

What's new

High-level API (matching Python/JS/C#/Java SDKs):

sb, err := opensandbox.CreateSandbox(ctx, config, opensandbox.SandboxCreateOptions{
    Image: "python:3.11-slim",
})
defer sb.Kill(ctx)

exec, err := sb.RunCommand(ctx, "echo hello", nil)
fmt.Println(exec.Text())     // "hello"
fmt.Println(*exec.ExitCode)  // 0
  • ConnectionConfig — shared config with env var fallbacks
  • Sandbox — wraps lifecycle + execd + egress with auto-endpoint resolution
  • CreateSandbox() / ConnectSandbox() — factory methods with WaitUntilReady
  • SandboxManager — list, filter, kill, pause, resume, renew
  • Execution model — structured stdout/stderr, exit codes, event handlers
  • Error types, constants, defaults

E2E tests in tests/go/ — 12 tests covering sandbox lifecycle, command execution, filesystem ops, and manager operations. All passing against live K8s staging.

…r, context-aware polling

- Extract clientOpts() helper to deduplicate option building in config.go
- Use strings.Builder in Execution.Text() instead of O(n²) string concat
- waitForRunning now respects context cancellation instead of hardcoded 120 iterations
- Remove SandboxFilter duplication — use ListOptions throughout
- Use SandboxState constants instead of string literals in tests
- Extract createTestSandbox() helper to reduce e2e test boilerplate

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@ninan-nn
Copy link
Copy Markdown
Collaborator

Once you're done with the development, please mark the PR as ready to review (convert it from draft) : >

AlexandrePh and others added 4 commits March 30, 2026 10:13
…directories

New e2e tests (19 total, up from 12):
- Filesystem: write/read/delete cycle, move files, create/delete directories,
  search files, download file
- Sandbox: connect to existing sandbox, bash sessions with state persistence
- Fix CreateDirectory to send mode as int per server spec

New Sandbox methods exposed:
- DeleteFiles, MoveFiles, SearchFiles, SetPermissions, ReplaceInFiles
- UploadFile, DownloadFile, CreateDirectory, DeleteDirectory
- ExecuteCode, CreateContext, ListContexts, DeleteContext
- CreateSession, RunInSession, DeleteSession

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- CodeInterpreter type wrapping Sandbox with code execution capabilities
- CreateCodeInterpreter() factory with opensandbox/code-interpreter:latest image
- Execute() for quick language-based execution
- ExecuteInContext() for persistent state across executions

E2E tests (6 new, 25 total):
- Create and ping code-interpreter sandbox
- Python code execution
- Context persistence (variables survive across calls)
- Context management (create, list, delete)
- Context isolation (variables don't leak between contexts)
- Execution with handlers (streaming stdout)

All 25 e2e tests pass against live K8s staging.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… policy, x-request-id

New e2e tests (35 total, up from 25):
- Command: env injection, background status/logs, interrupt
- Sandbox: manual cleanup, network policy create, egress get/patch, pause/resume
- Volumes: host mount (rw + readonly), PVC mount
- Error: x-request-id passthrough on API errors
- APIError now carries RequestID from X-Request-Id response header

Fix: CreateDirectory sends mode as octal-digits integer per server spec.
Tests that require egress sidecar, PVC, or pause support gracefully skip.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three scenario tests using live Bifrost (Azure OpenAI) + OpenSandbox:

1. SimpleAgentLoop: task → LLM generates Python → execute in sandbox → verify result
   (Fibonacci sequence via gpt-4o-mini generated code)

2. CodeInterpreterAgent: multi-turn agent with persistent Python context
   (Create dataset → LLM analyzes with stdlib → variables persist across turns)

3. SandboxToolUse: LLM as shell command planner
   (LLM decides what command → sandbox executes → LLM interprets output)

All 3 tests pass against live staging (Bifrost → Azure OpenAI gpt-4o-mini).

Also: configured Bifrost with Azure OpenAI provider (gpt-4o, gpt-4o-mini, o4-mini)
via azure-gpt-sharpi endpoint in Brazil South.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AlexandrePh and others added 2 commits March 30, 2026 13:24
…ccuracy

1. OctalMode: panic on invalid FileMode instead of silently returning 0
2. CodeInterpreter timeout: use named constant DefaultCodeInterpreterTimeoutSeconds
3. GetBaseURL doc: fix misleading comment that claimed /v1 suffix
4. resolveExecd/resolveEgress: use sync.Once for goroutine-safe initialization
5. execution.go: rename `init` variable to `initEvent` to avoid shadowing builtin
6. execd.go: remove duplicate doc comment on CreateDirectory
7. types.go: fix SandboxInfo doc comment that still said "Sandbox"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
sync.Once captures the first caller's context permanently — if it fails,
subsequent retries are impossible. Replaced with mutex-guarded check-then-init
which respects each caller's context and retries on failure.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… passes

- TestConcurrent_CreateFiveSandboxes: creates 5 sandboxes in parallel,
  verifies each is healthy and responds independently (requires 3/5 minimum
  for resource-constrained staging clusters)
- TestVolume_PVCMount now passes after provisioning opensandbox-e2e-pvc-test
  PVC via local-path provisioner on staging

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 43 out of 45 changed files in this pull request and generated 8 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

AlexandrePh and others added 2 commits March 30, 2026 15:16
… assertions

8 fixes from Copilot's second review pass:

1. execution.go: Handle nested error/results JSON per execd spec
   ({"type":"error","error":{...}} and {"type":"result","results":{...}})
   with backward compat for flat fields from older servers
2. config.go: Wire RequestTimeout and Headers into clientOpts()
3. http.go: Add WithHeaders option for custom headers on requests
4. streaming.go: Populate StreamEvent.Event from NDJSON type field
5. sandbox.go: Fix doc comment — nil timeout uses client default, not server
6. README.md: Fix streaming example to parse NDJSON type field
7. volume_e2e_test.go: Assert read-only mount actually rejects writes
8. scenario_agent_e2e_test.go: Check error from write command before exec
9. config.go: Append /v1 to lifecycle client base URL

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The execd spec defines error events with a nested `error` object
(`{ename, evalue, traceback}`) and result events with a MIME-keyed
`results` map (`{"text/plain": "4"}`). The SDK was parsing these as
flat top-level fields. Now supports both formats for backward compat.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@AlexandrePh AlexandrePh marked this pull request as ready for review March 30, 2026 18:38
- Update streaming example to use event.Event (now populated from NDJSON type)
- Fix RenewExpiration signature: takes expiresAt, not duration
- Fix GetEndpoint signature: add useServerProxy parameter
- Fix DeleteDirectory signature: remove recursive parameter
- Update StreamEvent docs to reflect NDJSON type extraction

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@AlexandrePh
Copy link
Copy Markdown
Author

@ninan-nn ready for review :)

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d83a932ae6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

…ming

- resolveExecd/resolveEgress now forward all endpoint headers (e.g.
  routing headers like OPEN-SANDBOX-INGRESS) to the client, not just
  the auth token
- doStreamRequest now applies c.headers, matching doRequest behavior

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@AlexandrePh
Copy link
Copy Markdown
Author

AlexandrePh commented Mar 30, 2026

Great Job! It's great to see the SDK for a new language. 🎉🎉

Perhaps you could refer to the e2e tests under the tests directory for the other languages and add some simple real e2e tests for Golang?

done! executed tests against live remote server

Copy link
Copy Markdown
Collaborator

@ninan-nn ninan-nn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for putting together the Go SDK. I have three broader concerns beyond the inline comments below:

  1. The Go SDK is not yet integrated into the repository's standard quality gates. At the moment there is no Go SDK job in sdk-tests.yml, no Go lane in real-e2e.yml, and no scripts/go-e2e.sh equivalent, so the claimed lint / ut / e2e coverage is not enforced in the same way as the other SDKs.

  2. The new tests/go/ suite is directionally in the right place, but I would hesitate to count it as full repository E2E coverage until it is wired into the shared E2E workflow with a standard runner script, reports, and artifact handling comparable to the existing Python / Java / JavaScript / C# lanes.

  3. One structural concern: the handwritten Go SDK layer is currently very flat. Generated code is separated, which is good, but transport concerns, streaming handling, low-level clients, and high-level facades are still all placed directly under a single package path. This is not necessarily wrong in Go, but for a new long-lived SDK in a multi-language repository, I think some internal separation would make the boundaries clearer and the package easier to maintain over time.

AlexandrePh and others added 3 commits April 2, 2026 00:55
…ackage structure

Address all 6 review items from maintainer:
- Add ImageAuth to SandboxCreateOptions for registry credential parity
- Add ManualCleanup mode to omit timeout for no-auto-expiration
- Add ResumeSandbox() and Sandbox.Resume() for pause/resume flow
- Add Go SDK jobs to sdk-tests.yml and real-e2e.yml CI workflows
- Create scripts/go-e2e.sh and tests/go/ E2E test suite
- Split sandbox.go into sandbox_exec.go, sandbox_files.go, sandbox_egress.go
- Add retry with exponential backoff, transport pooling, Retry-After support

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ewrite

- Add EndpointHostRewrite to ConnectionConfig for Docker host.docker.internal → localhost rewriting
- Add integration tests: TestIntegration_PauseResume (full pause→resume→pause→Resume() flow on Docker runtime)
- Add integration tests: TestIntegration_ManualCleanup (verify nil ExpiresAt vs default timeout)
- Add staging tests: TestStaging_PauseResume (verifies 501 error handling on k8s runtime)
- Add staging tests: TestStaging_ManualCleanup (confirmed working on live staging)
- Add e2e tests: TestE2E_PauseResume and TestE2E_ManualCleanup
- Add docker-compose.test.yaml for local OpenSandbox server with Docker runtime
- All tests pass: 40 unit, 3 integration (Docker), 3 staging (live k8s)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add unit, integration, and staging tests for all previously untested
execd endpoints: SandboxManager, file operations (create/delete dir,
delete/move/search/replace/download files, permissions), CodeInterpreter
(contexts CRUD, execute, execute-in-context), sessions (create, run,
delete), command management (status, logs with cursor, interrupt), and
metrics watch (SSE streaming with context cancellation).

Also adds 5 negative-path integration tests verifying error handling:
nonexistent sandbox get/kill, file ops on missing paths, run-in-deleted-
session, and execute-in-deleted-context.

37 new unit tests, 12 new integration tests, 1 new staging test.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@AlexandrePh
Copy link
Copy Markdown
Author

AlexandrePh commented Apr 2, 2026

Thanks for the detailed review @ninan-nn !
all three points + inline comments where addressed.

  1. CI: Added a go-sdk-quality job to sdk-tests.yml (runs go vet + go test -race) and a go-e2e lane to real-e2e.yml backed by scripts/go-e2e.sh. Same env var contract as the other language runners.
  2. E2E depth: The Go suite is now wired into the shared workflow and the latest push closes every remaining test gap.
  3. Structure: Split sandbox.go into sandbox_exec.go, sandbox_files.go, sandbox_egress.go for domain separation, plus retry.go, transport.go, and config.go for infra. Still a single importable idomatic golang package but with clearer file boundaries now.

@AlexandrePh AlexandrePh requested a review from ninan-nn April 2, 2026 18:30
AlexandrePh and others added 4 commits April 2, 2026 16:05
Add tests for 6 operations that every other SDK (Python, JS, C#, Java)
covers against real servers but Go previously only had mock or no coverage:

- Command with env vars: verify Envs map propagated to process
- Command interrupt: background command → interrupt → verify stopped
- Network policy: create with policy → get → patch → verify rules
- Volume mounts: host rw, host ro, PVC rw, PVC ro, PVC subPath
- Multi-language code execution: Python with context persistence + errors
- X-Request-ID passthrough: verify RequestID captured in APIError

Unit tests added: RunCommand_WithEnvs, RunCommand_Background,
APIError_RequestID, CreateSandbox_WithNetworkPolicy,
CreateSandbox_WithVolumes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Verified against live k3s cluster (sandbox.az.arpi.sh):
- PVC read-write: write file to mounted PVC, read back ✓
- PVC read-only: verify write fails with "Read-only file system" ✓
- PVC subPath: write to subdirectory mount ✓
- Network policy: graceful skip (egress sidecar not configured)
- Command env vars: verify Envs map propagated to process ✓

Created PVC "go-sdk-e2e-pvc" in sandbox namespace for test use.
Updated integration tests to use same PVC name.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When UseServerProxy is true, requests are routed through a reverse proxy
(e.g. Caddy) that requires the API key header. The execd client correctly
inherited the auth header override, but the egress client used
clientOpts(false) which skipped it — causing 401s on all egress calls
through the proxy.

Fix: pass UseServerProxy as the includeAuthHeader flag so the egress
client gets the same auth header treatment as execd when proxied.

Also configured egress sidecar image (opensandbox/egress:v1.0.4) on
staging k3s cluster. NetworkPolicy staging test now passes:
create with policy → get policy → patch rules → verify.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reverts the clientOpts(c.UseServerProxy) change from the previous commit.
The other SDKs (Python, JS, C#) don't pass the lifecycle API key to the
egress client — they rely on the OPENSANDBOX-EGRESS-AUTH token from the
endpoint response. The 401 was caused by our Caddy config blocking proxy
paths, not a missing SDK feature.

Fix: updated Caddy to pass through /sandboxes/{id}/proxy/* paths without
requiring X-API-Key, since the OpenSandbox server authenticates proxied
requests internally via endpoint tokens.

Verified: TestStaging_NetworkPolicy passes with clean SDK + fixed Caddy.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@AlexandrePh AlexandrePh force-pushed the feat/go-sdk branch 2 times, most recently from ec3f558 to f900bb6 Compare April 5, 2026 23:44
}

metaHeader := make(textproto.MIMEHeader)
metaHeader.Set("Content-Disposition", `form-data; name="metadata"`)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In other SDKs, file metadata is sent as a separate file part in a multipart request.

For example:
https://github.com/alibaba/OpenSandbox/blob/main/sdks/sandbox/javascript/src/adapters/filesystemAdapter.ts#L141

defer f.Close()

var body bytes.Buffer
writer := multipart.NewWriter(&body)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file content is fully loaded into memory before sending, which can be a problem for large files. It would be worth trying to accept file metadata (name, size, etc.) and an io.Reader in the function for streaming the file content.

@hittyt
Copy link
Copy Markdown
Collaborator

hittyt commented Apr 8, 2026

image Please fix the e2e error

@Pangjiping
Copy link
Copy Markdown
Collaborator

image Please fix the e2e error

@AlexandrePh you could remove this cache-dependency-path: sdks/sandbox/go/go.sum

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Go SDK for OpenSandbox (Lifecycle, Execd, Egress)

7 participants