covalent-tenki-plugin
A Covalent executor plugin that runs each electron (task) inside a disposable Tenki Sandbox microVM (Firecracker).
Every task gets a fresh, fully isolated Linux VM with real root — created on demand, destroyed the moment the task finishes. Ideal for untrusted or dependency-conflicting workloads: one task's environment can never leak into another's.
Installation
pip install covalent-tenki-plugin
Prerequisites
- A Tenki Cloud account with sandbox access.
- A Tenki API key, exposed as
TENKI_API_KEY(orTENKI_AUTH_TOKEN) on the machine running the Covalent dispatcher. - Local Python minor version matching the sandbox Python (3.12 on the default
image) — tasks travel via
cloudpickle, which requires matching interpreters. The executor verifies this and fails fast with a clear message on mismatch.
Usage
import covalent as ct
from covalent_tenki_plugin import TenkiExecutor
executor = TenkiExecutor(
cpu_cores=2,
memory_mb=4096,
sandbox_requirements="numpy pandas", # installed in the VM at bootstrap
)
@ct.electron(executor=executor)
def process(x):
import numpy as np
return float(np.sqrt(x))
@ct.lattice
def workflow(x):
return process(x)
dispatch_id = ct.dispatch(workflow)(1764)
Configuration
| Argument | Default | Description |
|---|---|---|
project_id |
first project on the API key | Tenki project to create sandboxes in |
cpu_cores |
Tenki default (2) | Sandbox CPU cores |
memory_mb |
Tenki default (4096) | Sandbox memory |
disk_size_gb |
Tenki default (5) | Ephemeral root disk |
image |
unset (Ubuntu base) | Registry image ref; a prepared image skips the bootstrap |
sandbox_max_duration_seconds |
3600 | Hard VM lifetime (self-destruct safety net) |
bootstrap_timeout_seconds |
600 | Timeout for the apt + pip bootstrap |
task_timeout_seconds |
1800 | Timeout for the task execution |
sandbox_requirements |
"" |
Extra pip specs installed at bootstrap (cloudpickle and covalent always included) |
How it works
For each electron the executor:
- Creates a sandbox via the official
tenki-sandboxPython SDK, withmax_durationset so the VM self-destructs server-side even if the dispatcher crashes (no leaked billing). - Bootstraps a virtualenv and installs
cloudpickle,covalent(pinned to the dispatcher's version — server-dispatched tasks arrive as covalent wrapper callables, so unpickling them requires covalent in the sandbox, same as the official SSH plugin's remote hosts), and yoursandbox_requirements(~2–3 min on the default image; skipped whenimagepoints at a prepared registry image). - Ships the cloudpickled
(function, args, kwargs)into the VM over the SDK's exec data plane (no SSH, no object storage), executes it with the sandbox venv Python, and reads the pickled(result, exception)back. - Terminates the sandbox unconditionally; remote exceptions are re-raised locally with full fidelity.
Current limitations
- ~2–3 min cold start per task on the default image (apt + venv +
covalentinstall) — significant for many short electrons. Use a preparedimageto eliminate it, or batch small steps into fewer electrons. - Task payloads and results travel through the exec data plane; very large results (tens of MB) may hit message-size limits — write large artifacts to external storage from within the task instead.
- Mid-task cancellation is not yet wired to Covalent's cancel API; the
max_durationself-destruct bounds runaway tasks. - Sandbox volumes and snapshots are not used by this plugin.
Development
pip install -e ".[dev]"
pytest tests/ -q # unit tests, fully mocked, no credentials needed
A live end-to-end smoke test requires TENKI_API_KEY and creates (then
terminates) real sandboxes.
Known upstream issue (unrelated to this plugin)
With covalent==0.240.0 and requests>=2.34, any ct.dispatch() fails
with 422 Unprocessable Entity: the SDK posts the dispatch manifest as a raw
string without a Content-Type: application/json header, and the server's
FastAPI rejects it. Workaround until fixed upstream:
from covalent._dispatcher_plugins import local as ldisp
_orig_post = ldisp.APIClient.post
def _patched_post(self, endpoint, **kw):
if "data" in kw:
kw.setdefault("headers", {})["Content-Type"] = "application/json"
return _orig_post(self, endpoint, **kw)
ldisp.APIClient.post = _patched_post
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 covalent_tenki_plugin-0.1.0.tar.gz.
File metadata
- Download URL: covalent_tenki_plugin-0.1.0.tar.gz
- Upload date:
- Size: 13.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2d396034763896030039049808090c3c67e7aa0211644f0c9dd619deadfe7e45
|
|
| MD5 |
7bf5a68e8a81d768c3341202e9e755eb
|
|
| BLAKE2b-256 |
4402a8efecdb384f5a4a35d776445486bf434b3f85dae4d8747df6202ee2a61c
|
Provenance
The following attestation bundles were made for covalent_tenki_plugin-0.1.0.tar.gz:
Publisher:
pypi-publish.yml on TenkiCloud/covalent-tenki-plugin
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
covalent_tenki_plugin-0.1.0.tar.gz -
Subject digest:
2d396034763896030039049808090c3c67e7aa0211644f0c9dd619deadfe7e45 - Sigstore transparency entry: 2210073829
- Sigstore integration time:
-
Permalink:
TenkiCloud/covalent-tenki-plugin@acbb2b93a03771992b217466c6d03f846b2d757b -
Branch / Tag:
refs/heads/main - Owner: https://github.com/TenkiCloud
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
self-hosted -
Publication workflow:
pypi-publish.yml@acbb2b93a03771992b217466c6d03f846b2d757b -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file covalent_tenki_plugin-0.1.0-py3-none-any.whl.
File metadata
- Download URL: covalent_tenki_plugin-0.1.0-py3-none-any.whl
- Upload date:
- Size: 12.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
db862530890fa5ede29e34adec38896176a30a61d406be7b68229ec0f91841fd
|
|
| MD5 |
09fbf810bfa48684ea62582b7eb7b62d
|
|
| BLAKE2b-256 |
7bf185ddbdd1bf0d23ae32771b8885b7e6ed4027fdb36df07e871b41e1d6bc59
|
Provenance
The following attestation bundles were made for covalent_tenki_plugin-0.1.0-py3-none-any.whl:
Publisher:
pypi-publish.yml on TenkiCloud/covalent-tenki-plugin
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
covalent_tenki_plugin-0.1.0-py3-none-any.whl -
Subject digest:
db862530890fa5ede29e34adec38896176a30a61d406be7b68229ec0f91841fd - Sigstore transparency entry: 2210073856
- Sigstore integration time:
-
Permalink:
TenkiCloud/covalent-tenki-plugin@acbb2b93a03771992b217466c6d03f846b2d757b -
Branch / Tag:
refs/heads/main - Owner: https://github.com/TenkiCloud
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
self-hosted -
Publication workflow:
pypi-publish.yml@acbb2b93a03771992b217466c6d03f846b2d757b -
Trigger Event:
workflow_dispatch
-
Statement type: