#Sandbox Functions
Sandbox functions are one-shot handlers stored in the sandbox filesystem. The first Python runtime maps a function name such as main to /workspace/functions/main.py and invokes the handler function by default.
Function invocation does not add another daemon. Procd stays as the sandbox entry process and starts the injected /procd/runtimes/python-runner binary for each invocation.
Runtime Requirements#
The sandbox image must provide python3 on PATH. The default Sandbox0 template includes Python. Custom images should install Python when they need this function runtime.
The platform injects both binaries into the sandbox pod:
| Path | Purpose |
|---|---|
/procd/bin/procd | Sandbox entry process |
/procd/runtimes/python-runner | Python function runner |
Handler Contract#
Create a function module under /workspace/functions. For main, write /workspace/functions/main.py:
pythonimport base64 import json def handler(request): raw = base64.b64decode(request.get("body_base64") or "e30=") payload = json.loads(raw.decode("utf-8")) name = payload.get("name", "world") return { "status": 200, "headers": {"content-type": "application/json"}, "body": {"message": f"hello {name}"}, }
The request object contains method, path, query, headers, and body_base64. The response object contains status, headers, and body_base64. Returning a Python dict, str, bytes, or None is supported; non-response dictionaries can be returned as {"body": ...}.
Invoke#
/api/v1/sandboxes/{id}/functions/{name}/invoke
gosource := []byte(`import base64 import json def handler(request): raw = base64.b64decode(request.get("body_base64") or "e30=") payload = json.loads(raw.decode("utf-8")) return { "status": 200, "headers": {"content-type": "application/json"}, "body": {"message": "hello " + payload.get("name", "world")}, } `) _, err := sandbox.Mkdir(ctx, "/workspace/functions", true) if err != nil { log.Fatal(err) } _, err = sandbox.WriteFile(ctx, "/workspace/functions/main.py", source) if err != nil { log.Fatal(err) } body := base64.StdEncoding.EncodeToString([]byte(`{"name":"Ada"}`)) resp, err := sandbox.InvokeFunction(ctx, "main", apispec.FunctionInvokeRequest{ Method: apispec.NewOptString("POST"), Path: apispec.NewOptString("/hello"), BodyBase64: apispec.NewOptString(body), }) if err != nil { log.Fatal(err) } decoded, err := base64.StdEncoding.DecodeString(resp.BodyBase64.Or("")) if err != nil { log.Fatal(err) } fmt.Println(string(decoded))
By default, the CLI prints the decoded function body. Use -o json to inspect the full function response, including status, headers, and body_base64.