# Communication Flow Between the OpenSandbox SDK, Server, and execd Component: A Complete Guide

> Understand the OpenSandbox communication flow. Learn how the SDK, server, and execd component interact for sandboxes, endpoints, files, commands, and metrics.

- Repository: [Alibaba/OpenSandbox](https://github.com/alibaba/OpenSandbox)
- Tags: deep-dive
- Published: 2026-03-08

---

**The SDK communicates with the OpenSandbox server to create sandboxes and discover endpoints, then talks directly to the execd daemon inside the sandbox for file, command, and metrics operations.**

The communication flow between the SDK, the OpenSandbox server, and the execd component forms the backbone of the alibaba/OpenSandbox architecture. This article breaks down how the Python SDK orchestrates sandbox lifecycles through the FastAPI server, how the server launches and tracks the execd daemon, and how the SDK establishes direct connections to execd for low-latency I/O operations.

## High-Level Architecture Overview

Three primary participants coordinate to provide secure, isolated execution environments:

| Participant | Primary Responsibility | Key API Surface |
|-------------|------------------------|-----------------|
| **SDK (Python/JS)** | User-facing client library. Manages sandbox lifecycle and execd I/O. | `opensandbox.sandbox.Sandbox` → `create_sandbox()`, `get_sandbox_endpoint()`, `run_command()` |
| **OpenSandbox Server** | FastAPI service orchestrating Docker/Kubernetes containers and endpoint discovery. | [`server/src/api/lifecycle.py`](https://github.com/alibaba/OpenSandbox/blob/main/server/src/api/lifecycle.py) – `/sandboxes`, `/sandboxes/{id}/endpoint/{port}`, `/sandboxes/{id}/proxy/...` |
| **execd** | Lightweight Go daemon running *inside* each sandbox. Handles file, command, and metrics requests. | [`components/execd/pkg/web/router.go`](https://github.com/alibaba/OpenSandbox/blob/main/components/execd/pkg/web/router.go) – Gin router registering `/files`, `/code`, `/command`, `/metrics` |

The flow follows this pattern:

```

SDK  →  Server (lifecycle)  →  sandbox container (execd)
      ↘  Server returns execd endpoint                ↘  SDK calls execd API (direct or via Server proxy)

```

## Step-by-Step Communication Sequence

### SDK Creates a Sandbox via the Server

The communication flow begins when the SDK requests a new sandbox:

```python
from opensandbox import Sandbox

sandbox = await Sandbox.create(
    image="ghcr.io/opensandbox/platform:latest"
)

```

Under the hood, the SDK sends a `POST /v1/sandboxes` request to the Server. In [`server/src/api/lifecycle.py`](https://github.com/alibaba/OpenSandbox/blob/main/server/src/api/lifecycle.py), the `create_sandbox` implementation invokes the `sandbox_service` to launch a container (Docker or Kubernetes pod) that runs the `execd` binary. The Server records metadata (ID, image, state) and returns the **sandbox ID** to the SDK.

### SDK Discovers the execd Endpoint

Before performing I/O, the SDK must resolve the execd network location:

```python
endpoint = await sandbox.get_endpoint(port=8080)  # default execd port

```

The SDK calls `GET /v1/sandboxes/{sandbox_id}/endpoints/8080`. The Server looks up the sandbox runtime, obtains the internal IP and port where execd listens, and returns an `Endpoint` model containing `{endpoint: "10.0.2.15:8080", headers: {...}}`. This logic resides in [`server/src/api/lifecycle.py`](https://github.com/alibaba/OpenSandbox/blob/main/server/src/api/lifecycle.py) within the `get_sandbox_endpoint` function.

### SDK Communicates Directly with execd

Once the endpoint is known, the SDK bypasses the Server for performance-critical operations. All execd-related adapters (`FilesystemAdapter`, `CommandAdapter`, `HealthAdapter`, `MetricsAdapter`) receive the `SandboxEndpoint` object and construct URLs using the helper `_get_execd_url`.

For example, uploading a file:

```python
await sandbox.filesystem.upload_file(
    local_path="script.py", 
    remote_path="/home/user/script.py"
)

```

The `FilesystemAdapter` in [`sdks/sandbox/python/src/opensandbox/sync/adapters/filesystem_adapter.py`](https://github.com/alibaba/OpenSandbox/blob/main/sdks/sandbox/python/src/opensandbox/sync/adapters/filesystem_adapter.py) sends an HTTP `POST /files/upload` request directly to the execd host. The execd daemon, via its Gin router in [`components/execd/pkg/web/router.go`](https://github.com/alibaba/OpenSandbox/blob/main/components/execd/pkg/web/router.go), dispatches the request to `controller.FilesystemController`, which performs the file operation inside the sandbox's filesystem.

Similarly, running a command:

```python
result = await sandbox.command.run(
    command="python /home/user/script.py",
    background=False,
)

```

This invokes `CommandAdapter.run_command`, which POSTs to `/command` on the execd instance, as defined in [`components/execd/pkg/web/router.go`](https://github.com/alibaba/OpenSandbox/blob/main/components/execd/pkg/web/router.go) and implemented in the code interpreting controller.

### Optional Server Proxy Path

If direct internal IP access is undesirable, the SDK can route traffic through the Server:

```python
proxy_ep = await sandbox.get_endpoint(port=8080, use_server_proxy=True)

```

When `use_server_proxy=True`, the Server's `get_sandbox_endpoint` (lines 12-17 in [`server/src/api/lifecycle.py`](https://github.com/alibaba/OpenSandbox/blob/main/server/src/api/lifecycle.py)) rewrites the `endpoint` field to a proxy URL like `/sandboxes/{id}/proxy/{port}`. Subsequent SDK calls use this URL, and the Server's `proxy_sandbox_endpoint_request` handler (lines 31-73) forwards the request to the real execd host, filtering hop-by-hop headers and streaming the response back.

### Lifecycle Changes and Reconnection

When the SDK pauses a sandbox:

```python
await sandbox.pause()

```

The SDK sends `POST /v1/sandboxes/{id}/pause` to the Server. The Server pauses the container; execd remains in memory but becomes unreachable.

Upon resuming:

```python
await sandbox.resume()

```

The SDK calls `POST /v1/sandboxes/{id}/resume`. The Server restarts the container, re-resolves the execd endpoint, and the SDK re-creates its adapters with the new endpoint (see `resume_sandbox` in [`server/src/api/lifecycle.py`](https://github.com/alibaba/OpenSandbox/blob/main/server/src/api/lifecycle.py)).

## Code Implementation Details

### Python SDK Example

The Python SDK abstracts the communication flow through the `Sandbox` class in [`sdks/sandbox/python/src/opensandbox/sync/services/sandbox.py`](https://github.com/alibaba/OpenSandbox/blob/main/sdks/sandbox/python/src/opensandbox/sync/services/sandbox.py):

```python
from opensandbox import Sandbox

async def workflow():
    # Lifecycle: Server communication

    sandbox = await Sandbox.create(image="python:3.11")
    
    # Endpoint discovery: Server communication

    endpoint = await sandbox.get_endpoint(port=8080)
    
    # I/O operations: Direct execd communication

    await sandbox.filesystem.write_file("/app/main.py", "print('hello')")
    result = await sandbox.command.run("python /app/main.py")
    
    # Cleanup: Server communication

    await sandbox.delete()

```

### Server Lifecycle API

The FastAPI server exposes the coordination layer in [`server/src/api/lifecycle.py`](https://github.com/alibaba/OpenSandbox/blob/main/server/src/api/lifecycle.py). Key functions include:

- `create_sandbox`: Launches containers via `sandbox_service` and injects the execd binary.
- `get_sandbox_endpoint`: Resolves the internal IP:port of execd and optionally returns a proxy URL.
- `proxy_sandbox_endpoint_request`: Forwards SDK requests to execd when using the server proxy mode.
- `resume_sandbox`: Re-resolves execd endpoints after container restart.

### execd Router Implementation

The execd daemon uses Gin to route SDK requests to the appropriate controllers. In [`components/execd/pkg/web/router.go`](https://github.com/alibaba/OpenSandbox/blob/main/components/execd/pkg/web/router.go):

```go
func RegisterRoutes(r *gin.Engine, ctrl *controller.Controller) {
    // Filesystem operations
    r.POST("/files/upload", ctrl.Filesystem.UploadFile)
    r.GET("/files/download", ctrl.Filesystem.DownloadFile)
    
    // Command execution
    r.POST("/command", ctrl.CodeInterpreting.RunCommand)
    
    // Health and metrics
    r.GET("/health", ctrl.Health.Check)
    r.GET("/metrics", ctrl.Metrics.GetMetrics)
}

```

This router handles the direct SDK-to-execd communication that occurs after endpoint discovery.

## Key Source Files Reference

| Component | File | Role |
|-----------|------|------|
| **execd – HTTP router** | [[`components/execd/pkg/web/router.go`](https://github.com/alibaba/OpenSandbox/blob/main/components/execd/pkg/web/router.go)](https://github.com/alibaba/OpenSandbox/blob/main/components/execd/pkg/web/router.go) | Registers all execd routes (`/files`, `/code`, `/command`, `/metrics`). |
| **execd – Controllers** | [[`components/execd/pkg/web/controller/filesystem.go`](https://github.com/alibaba/OpenSandbox/blob/main/components/execd/pkg/web/controller/filesystem.go)](https://github.com/alibaba/OpenSandbox/blob/main/components/execd/pkg/web/controller/filesystem.go) (and [`code_interpreting.go`](https://github.com/alibaba/OpenSandbox/blob/main/code_interpreting.go), [`command.go`](https://github.com/alibaba/OpenSandbox/blob/main/command.go), [`metric.go`](https://github.com/alibaba/OpenSandbox/blob/main/metric.go)) | Implements the actual sandbox file/command logic. |
| **Server – Lifecycle API** | [[`server/src/api/lifecycle.py`](https://github.com/alibaba/OpenSandbox/blob/main/server/src/api/lifecycle.py)](https://github.com/alibaba/OpenSandbox/blob/main/server/src/api/lifecycle.py) | Handles sandbox CRUD, pause/resume, endpoint discovery, and proxying. |
| **Server – Sandbox Service** | [[`server/src/services/k8s/kubernetes_service.go`](https://github.com/alibaba/OpenSandbox/blob/main/server/src/services/k8s/kubernetes_service.go)](https://github.com/alibaba/OpenSandbox/blob/main/server/src/services/k8s/kubernetes_service.go) (Docker equivalent in [`docker.py`](https://github.com/alibaba/OpenSandbox/blob/main/docker.py)) | Launches the sandbox container and injects the execd binary. |
| **Python SDK – Sandbox Service** | [[`sdks/sandbox/python/src/opensandbox/sync/services/sandbox.py`](https://github.com/alibaba/OpenSandbox/blob/main/sdks/sandbox/python/src/opensandbox/sync/services/sandbox.py)](https://github.com/alibaba/OpenSandbox/blob/main/sdks/sandbox/python/src/opensandbox/sync/services/sandbox.py) | Provides `create()`, `get_endpoint()`, and high-level sandbox object. |
| **Python SDK – Filesystem Adapter** | [[`sdks/sandbox/python/src/opensandbox/sync/adapters/filesystem_adapter.py`](https://github.com/alibaba/OpenSandbox/blob/main/sdks/sandbox/python/src/opensandbox/sync/adapters/filesystem_adapter.py)](https://github.com/alibaba/OpenSandbox/blob/main/sdks/sandbox/python/src/opensandbox/sync/adapters/filesystem_adapter.py) | Builds execd URLs and calls `/files` endpoints. |
| **Python SDK – Command Adapter** | [[`sdks/sandbox/python/src/opensandbox/sync/adapters/command_adapter.py`](https://github.com/alibaba/OpenSandbox/blob/main/sdks/sandbox/python/src/opensandbox/sync/adapters/command_adapter.py)](https://github.com/alibaba/OpenSandbox/blob/main/sdks/sandbox/python/src/opensandbox/sync/adapters/command_adapter.py) | Builds execd URLs and calls `/command` endpoints. |
| **OpenAPI spec for execd** | [[`specs/execd-api.yaml`](https://github.com/alibaba/OpenSandbox/blob/main/specs/execd-api.yaml)](https://github.com/alibaba/OpenSandbox/blob/main/specs/execd-api.yaml) | Contract that both execd and SDK adapters follow. |

## Summary

- **Two-phase communication**: The SDK first communicates with the OpenSandbox server for lifecycle management (create, pause, resume) and endpoint discovery, then communicates directly with the execd daemon for file, command, and metrics operations.
- **Endpoint discovery**: The server resolves the internal IP and port of the execd container and returns it via `GET /v1/sandboxes/{id}/endpoints/{port}` in [`server/src/api/lifecycle.py`](https://github.com/alibaba/OpenSandbox/blob/main/server/src/api/lifecycle.py).
- **Direct vs. proxied**: By default, the SDK connects directly to execd for performance. Alternatively, setting `use_server_proxy=True` routes traffic through the server's `proxy_sandbox_endpoint_request` handler.
- **Lifecycle resilience**: When a sandbox resumes after pausing, the server re-resolves the execd endpoint in `resume_sandbox`, and the SDK adapters update their connection strings accordingly.

## Frequently Asked Questions

### Does the SDK always communicate directly with execd?

No. While the default mode uses direct communication for low-latency I/O, the SDK can optionally route all execd traffic through the OpenSandbox server. When calling `get_endpoint(port=8080, use_server_proxy=True)`, the server returns a proxy URL like `/sandboxes/{id}/proxy/8080` instead of the direct IP, and the `proxy_sandbox_endpoint_request` function in [`server/src/api/lifecycle.py`](https://github.com/alibaba/OpenSandbox/blob/main/server/src/api/lifecycle.py) forwards requests to the execd daemon.

### What happens to execd when a sandbox is paused?

When the SDK calls `pause()`, the OpenSandbox server pauses the underlying container (Docker or Kubernetes pod). The execd process remains in memory but becomes unreachable because the container's network stack is frozen. The SDK loses its connection to the execd endpoint. Upon `resume()`, the server restarts the container, re-resolves the potentially new IP address in `resume_sandbox`, and returns the updated endpoint to the SDK, which then reinitializes its adapters.

### How does the server handle execd endpoint discovery in Kubernetes?

In [`server/src/services/k8s/kubernetes_service.go`](https://github.com/alibaba/OpenSandbox/blob/main/server/src/services/k8s/kubernetes_service.go), the server creates a pod running the sandbox image with the execd binary injected. When the SDK requests the endpoint via `GET /v1/sandboxes/{id}/endpoints/{port}`, the server queries the Kubernetes API to obtain the pod's cluster IP or node IP and the mapped container port. It returns this address in the `Endpoint` model. If `use_server_proxy` is enabled, the server instead returns a proxy path that routes through the OpenSandbox API.

### Can I use the OpenSandbox server as a reverse proxy for all execd traffic?

Yes, but with performance considerations. The server exposes a proxy route at `/v1/sandboxes/{id}/proxy/{port}` implemented in `proxy_sandbox_endpoint_request` within [`server/src/api/lifecycle.py`](https://github.com/alibaba/OpenSandbox/blob/main/server/src/api/lifecycle.py). This handler forwards HTTP requests to the execd daemon, filters hop-by-hop headers, and streams responses back. While this simplifies network security by exposing only the server endpoint, it adds an extra network hop compared to direct SDK-to-execd communication.