This release is a pre-release and may not be stable for production use.
FissionPlane Python SDK
Use FissionPlane to create and control isolated sandboxes on your own infrastructure. This package connects Python applications to an FissionPlane installation.
The SDK can:
- create, list, pause, resume, and delete sandboxes;
- run commands, stream process output, and use PTYs;
- read, write, and watch sandbox files;
- make a sandbox port private or public;
- build templates from OCI images; and
- use synchronous or asynchronous Python.
FissionPlane requires an existing on-premises installation. See the FissionPlane repository for the platform source and deployment information.
Requirements
- Python 3.10 or later
- An FissionPlane control plane URL
- An API key or OIDC bearer token
- A template alias or template artifact ID
Install
Install the package with pip:
pip install fissionplane
You can also use uv:
uv add fissionplane
Configure the client
Set the control plane URL and API key:
export FISSIONPLANE_API_URL="https://api.sandbox.example.com"
export FISSIONPLANE_API_KEY="your-api-key"
FissionPlane() reads both variables. You can also pass the values directly:
from fissionplane import FissionPlane
client = FissionPlane(
base_url="https://api.sandbox.example.com",
api_key="your-api-key",
)
Use access_token instead of api_key for an OIDC bearer token. An explicit
API key takes precedence over an access token. The client rejects an empty
credential, or one containing whitespace, when you construct it.
Timeouts, retries, and logging
The client applies a 60 second timeout to every request. Change the default
with request_timeout. Pass 0 or None to disable the timeout.
client = FissionPlane(request_timeout=30)
Every operation also accepts request_timeout for one call:
sandbox = client.sandboxes.get("sbx-123", request_timeout=5)
result = sandbox.commands.run("make", args=["build"], request_timeout=0)
The client retries a failed request twice by default, with exponential
backoff and jitter. Set max_retries=0 to disable retries. The SDK only
retries a request that is safe to send again:
- reads, such as
get(),list(), andfiles.read(); sandboxes.create()when you pass anidempotency_key; and- responses the server marks
retryable, or status 429 and 5xx responses that the server does not markretryable: false.
client = FissionPlane(max_retries=4)
sandbox = client.sandboxes.create("base", idempotency_key="example-job-1")
Pass headers to add or replace headers on one call:
client.sandboxes.list(headers={"X-Request-Source": "nightly-job"})
The SDK reports retries, capability token re-mints, and page fetches at debug
level on the fissionplane logger. Pass your own logger to redirect them:
import logging
logging.basicConfig(level=logging.DEBUG)
client = FissionPlane(logger=logging.getLogger("my-app.sandboxes"))
Anything you pass in httpx_args wins over the SDK defaults, including
timeout and headers.
Create a sandbox and run a command
Sandbox creation is synchronous. The call returns after a node acknowledges the sandbox.
from fissionplane import FissionPlane
client = FissionPlane()
sandbox = client.sandboxes.create(
"base",
name="example-job",
deadline_seconds=600,
idempotency_key="example-job-1",
)
try:
result = sandbox.commands.run(
"python",
args=["-c", "print('hello from FissionPlane')"],
timeout_seconds=30,
)
print(result.stdout)
print(result.exit_code)
finally:
sandbox.delete()
commands.run() waits for the command to exit. It returns the exit code,
standard output, standard error, and an optional truncation flag.
Use sandbox.commands.list_processes() to list supervised processes. Use
sandbox.commands.kill(pid, "SIGTERM") to signal one process.
Start a background process when output must be followed or stdin stays open:
from fissionplane import PtySize
process = sandbox.commands.start("bash", pty=PtySize(cols=120, rows=40))
attachment = process.attach()
attachment.send_input("pwd\n")
for event in attachment:
if event.type == "stdout":
print(event.data, end="")
elif event.type == "exit":
break
Filesystem operations use the sandbox data plane directly:
sandbox.files.make_dir("/workspace")
sandbox.files.write("/workspace/input.txt", b"hello")
entries = sandbox.files.list("/workspace")
watch = sandbox.files.watch("/workspace", recursive=True)
Manage the sandbox lifecycle
A sandbox has one of four visible states: running, paused, terminated,
or failed.
sandbox.pause()
sandbox.resume(deadline_seconds=600)
sandbox.extend_deadline(900)
sandbox.delete()
pause() saves a snapshot and releases node capacity. resume() restores the
snapshot on a node. A resumed sandbox has a new epoch.
Capability tokens belong to one sandbox epoch. The SDK replaces the token on
the handle after resume(). A handle returned by sandboxes.get() or
sandboxes.iterate() has no token. Call sandbox.mint_token() before you use
commands on such a handle.
A capability token also expires on its own schedule. When the sandbox data plane rejects one, the handle mints a replacement and sends the request again. This applies to command, file, and streaming calls alike, so long-lived handles keep working without your code refreshing anything.
Use an idempotency key when your application can retry sandbox creation. The same key returns the sandbox from the first successful request.
Expose a port
Every port is private by default. Private access requires a capability token. Make one port public only when anonymous access is required.
exposure = sandbox.ports.expose(3000, "public")
print(exposure.url)
records = sandbox.ports.list()
sandbox.ports.unexpose(3000)
unexpose() removes the exposure record. The port then returns to private
access.
Build and use a template
Template builds run asynchronously on the FissionPlane installation.
from fissionplane import BuildStep
build = client.templates.build(
"python:3.12",
alias="python-tools",
steps=[BuildStep(command="pip install httpx")],
)
template = build.wait(timeout=600)
sandbox = client.sandboxes.create("python-tools")
Use build.logs(offset) to read build output. Pass the returned offset to the
next call. Use client.templates.get_build(build_id) to reconnect to an
existing build.
Use the asynchronous client
AsyncFissionPlane has the same operations as the synchronous client. Await
each network operation.
import asyncio
from fissionplane import AsyncFissionPlane
async def main() -> None:
client = AsyncFissionPlane()
sandbox = await client.sandboxes.create("base")
try:
result = await sandbox.commands.run("python", args=["-V"])
print(result.stdout)
finally:
await sandbox.delete()
asyncio.run(main())
Use async for with client.sandboxes.iterate() to read all matching pages.
Read every page
sandboxes.list() returns one page and its next_cursor. Use iterate()
when you want every match instead. It fetches one page at a time and follows
the cursor until the collection ends.
for sandbox in client.sandboxes.iterate(state=SandboxState.RUNNING, limit=50):
print(sandbox.sandbox_id)
The asynchronous client returns an async generator:
async for sandbox in client.sandboxes.iterate(metadata={"run": "42"}):
print(sandbox.sandbox_id)
Handle errors
All SDK errors inherit from FissionPlaneError. HTTP errors include status,
code, retryable, and request_id when the server returns those fields.
from fissionplane import FissionPlaneError, RateLimitError
try:
sandbox = client.sandboxes.create("base")
except RateLimitError as error:
if error.retryable:
print(f"retry later; request ID: {error.request_id}")
except FissionPlaneError as error:
print(error.code, error)
The package also exports errors for authentication, authorization, missing resources, lifecycle conflicts, expired snapshots, command timeouts, and failed template builds.
Control plane and data plane
The control plane manages sandboxes, ports, tokens, and templates. The sandbox data plane runs commands, streams process I/O, and accesses files.
The SDK sends your API key or OIDC token to the control plane. It sends a short-lived capability token to the sandbox data plane. The SDK stores that token on the sandbox handle.
The data-plane agent uses port 50000 by default. Pass agent_port to the
client only when your installation uses a different port.
Build the API reference
The package documents its public surface with pdoc. Run it from
src/sdks/python:
uv run pdoc fissionplane -o docs
The command writes browsable HTML to docs/, which is not committed. Add
module names to document them on their own pages, for example
uv run pdoc fissionplane fissionplane.sandboxes -o docs. Do not point pdoc
at fissionplane._api or fissionplane._dataplane: those are generated cores,
and the OpenAPI files below are their reference.
Use uv run pdoc fissionplane without -o to preview the reference on a local
web server.
API status
This package is version 0.0.1. Treat its public API as unstable until the
project publishes a stable release.
The control-plane and data-plane OpenAPI files define the HTTP contracts:
License
FissionPlane uses the Apache License 2.0.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fissionplane-0.0.1b0.tar.gz.
File metadata
- Download URL: fissionplane-0.0.1b0.tar.gz
- Upload date:
- Size: 102.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.9.24 {"installer":{"name":"uv","version":"0.9.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6b0e5bc150bb802b3c9f8aeb50fb79630748ce26d5f9bb7c8d8d91df5b91e79d
|
|
| MD5 |
e1894bd7d0b25bc6f9361eb567b87ce8
|
|
| BLAKE2b-256 |
692adea481f4bf67a1385ca6c66ddc41c55c7a545168c1eb33f21a522babc63b
|
File details
Details for the file fissionplane-0.0.1b0-py3-none-any.whl.
File metadata
- Download URL: fissionplane-0.0.1b0-py3-none-any.whl
- Upload date:
- Size: 129.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.9.24 {"installer":{"name":"uv","version":"0.9.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
53fdab5f0aeb7cef0c7aedbd93611a7a3b936e1e5bde79a1fb333ceda883451b
|
|
| MD5 |
6d21de61bc1908699a6ef2e0657055d6
|
|
| BLAKE2b-256 |
45ee49b2e31b34b5856dadc87d3c931aa54c2ea99435c072cf66cbe7ad0d082b
|