Skip to main content
A plugin artifact contains a strict plugin.yaml plus its implementation or declarations. Python providers can use ordinary pure-Python wheels and capability-specific PyPA entry points. The platform registry stores immutable artifacts; it does not install dependencies into jobs.

Layout

plugin.yaml

plugin.yaml

Required fields

string
required
Always tuneplane/plugin/v1. Any other value is refused with the version this build speaks.
string
required
The leaf name. The platform stamps your account on it at publish time, so the published id is <owner>/<name> — you do not write the owner yourself.
string
required
Starts with a letter or digit; letters, digits, ., _, - after that. Immutable once published.
string
required
The one classification you declare: the protocol this package implements, one of algorithm, environment, data-prep, framework-integration, recipe, benchmark, playbook or prompt. Where its code runs and which shelf group it belongs to follow from it. Policy publication requires an administrator; code never loads into the control plane.
local | job
Only for data-prep, the one capability with two execution locations: your own machine (local) or a job (job). Every other capability has one location and refuses the field.
A manifest with any other schema is refused. The package type (runtime, asset or policy) is derived from the capability and is never declared.

Entrypoints for runtime extensions

module.path:callable
For source-directory providers, required for capabilities algorithm, environment, and data-prep with execution: job. A wheel provider instead declares wheel and provider. The module path is relative to the package root, and must exist at publish time.Forbidden for other capabilities and execution locations. A data-prep plugin with execution: local is discovered by the prepare_*.py convention; a declarative pack executes nothing, so it has no entry point at all.
eager | deferred
default:"eager"
When the launcher calls your entrypoint. See algorithm plugins.

Optional fields

PEP 440 specifier
Which tuneplane versions your plugin works with, for example ">=0.3,<1". Checked at launch; a mismatch stops the job with plugin x@1.2.0 requires SDK >=0.3,<1, this one is 0.2.9 rather than failing somewhere stranger later.
string
One line, shown in listings.
string
A preset icon name, an emoji (at most 8 characters), or a package-relative PNG path. PNG artwork is limited to 64 KiB and 512 × 512 pixels. Defaults to the capability’s icon.
string
Who wrote it. Distinct from owner, which is the platform account that published it.
string, url, string[]
Display and search only. homepage must be http(s). At most 12 keywords, lowercased and deduplicated.

README.md

A README.md at the package root becomes the long description on the detail page. Capped at 64 KB; anything beyond is truncated, because the detail page wants an introduction, not a manual. It is deliberately not a manifest field — long text in YAML forces the author to escape things and loses the Markdown toolchain. It is covered by the package digest, so changing it needs a new version.

Capabilities

You declare the capability; the execution location and the shelf group are derived from it. data-prep is the one capability with two execution locations, so it is the only manifest that also declares execution. The built-in framework integrations ship inside the SDK and are versioned with it. A new framework publishes an integration package and recipes against the existing compiler contract; it does not add a capability or require a core dispatch branch. New protocol behavior requires a versioned contract change; arbitrary execution locations are refused. Solutions are not published as plugins.
playbook and prompt are deployment-wide singletons: one is active and it changes what everyone sees on a diagnosis page. They are admin-only because the consequence lands on other people. There are no per-user versions — “whose diagnosis verdict is this” is a question that should not exist.

Publish

The client validates the manifest and the layout locally, computes the directory digest, and uploads. The server recomputes the digest and refuses a mismatch.

Install and reference

--exp writes plugins.lock.json into the experiment: the reference and its digest. At submission the platform reads that lockfile, injects exactly that version into the job package under tuneplane_plugins/<name>/, and records the triple in the JobSpec.
plugins.lock.json
Two plugins whose packages would unpack into the same leaf directory name cannot be combined in one job. Rename one.

Check it worked

Shows the version you just published and its digest. After submitting a job that references it, the job log carries one line per loaded plugin:
If the digest was tampered with after injection, the job refuses to start instead:

Next

Algorithm plugins for what your entrypoint receives · Recipe packs · Benchmark packs

Standard Python providers

Build with your usual Python build backend. Register one callable under the group for its capability:
wheel and provider replace entrypoint. Only portable pure-Python wheels without installation-time data relocation are supported. Native libraries and dependencies must already be in the job image. Wheel Requires-Python and Requires-Dist are checked in the job interpreter. Discovery inspects only the selected artifact’s metadata; it never globally auto-loads installed providers. Unknown manifest and requirement fields are errors. requires.frameworks maps framework names to version specifiers; an empty specifier constrains the name only. requires.methods lists method IDs. requires.backends lists allowed execution backends. Omitted constraints add no restriction, but do not bypass the capability’s own supported consumer or the platform’s resource requirements. Framework/method/backend conditions are checked before submission; Python and installed dependency conditions are checked in the actual job process. This is compatibility validation, not certification of arbitrary plugin code.
Local downloads live under tuneplane_plugins/<owner>/<name>/. Download verification completes before replacing an existing installation. An experiment must explicitly lock each job plugin with --exp. Job bundles currently reject duplicate leaf names as well as overlapping Python import namespaces. Give each provider a unique import root.

Shipped runnable examples

The Plugins page includes tuneplane/jsonl-filter and tuneplane/text-records, with dedicated icons, requirements, version controls and a README. These are real independently packaged providers, not catalog entries standing in for plugins. Administrators can disable them; restart preserves that choice. Their namespace is reserved for shipped artifacts.
  • JSONL filter: structural validation, configurable text length, disk-backed exact deduplication, unchanged accepted records and rejection counts. Invalid records fail by default; an explicit skip policy is available. It does not claim semantic quality or PII detection.
  • Text records: UTF-8 text/Markdown to overlapping character chunks, with stable IDs, source paths and offsets. Deterministic output supports auditing. It does not generate SFT instructions or parse PDFs.
Both require Python >= 3.12, SDK >= 0.3.56, framework custom and method custom/custom. They need no GPU or training library. Single-machine CPU-only jobs support Local, Node, Kubernetes and Slurm Fleets. Declare one pool with nodes: 1, gpus_per_node: 0, positive cpus and memory_gb, and no GPU series. Local/Node require Docker or Podman and configured host capacity. Kubernetes uses a native Pod and object-storage Capsule delivery. Slurm uses a registered SIF/SQSH runtime and the shared storage root, without Ray. Downstream training still needs a dataset schema accepted by its framework and method. A transform callable accepts tuneplane.contract.transforms.TransformRequest and returns TransformResult(files=(...), records=N). Its inputs are named readable paths, its configuration is a JSON object, and its output directory is owned by the host. All output files must be listed in the result. Symlinks and escaping paths are refused.
Run from the custom job’s script, after locking the selected provider:
The destination must be new. The runner executes in a fresh subprocess, enforces a deadline, terminates its process group on cancellation, validates outputs and publishes the directory only after success. The report records the exact provider identity. This process boundary is lifecycle isolation, not a security sandbox; the job container supplies the execution boundary. Use the job’s existing output_dataset declaration to publish the dataset.

Deployment activation

Publishing a playbook or prompt stores an available version without changing deployment behavior. An administrator explicitly selects an exact version:
Activation stores the ID, version, digest and generation. Concurrent updates must present the current generation. Before disabling an actively selected plugin or version, restore platform defaults or explicitly apply another version. Disablement never silently changes the deployment policy. Replicas refresh eventually. A failed application preserves the prior process snapshot and is retried; the activation response reports whether the handling instance applied it. It is not a claim of simultaneous activation across every replica.

Plugin artwork

Set icon in plugin.yaml to a preset (filter or files), an emoji, or a relative PNG path such as icons/logo.png. Include the image in the published package. PNG artwork must be at most 64 KiB and 512 × 512 pixels. External URLs and paths outside the package are not accepted. The console serves the artwork from registry metadata and falls back to a type icon if an image cannot load.

Manage plugins in the console

The Plugins page lists packages registered on this platform. Use the card switch to enable or disable a whole plugin; the setting persists when another version is published. The Versions tab manages each release independently and selects the recommended default for new installations. Existing experiment locks remain unchanged. Without a recommendation, unpinned resolution retains the newest enabled release fallback; pin a version for reproducible use. Upload a tar.gz containing plugin.yaml at its root (maximum 32 MiB). Preview validates the package without executing its code and displays its identity, compatibility requirements and digest. Confirming resends the same bytes with a short-lived review receipt; the server verifies both again. Browser imports start disabled. Enable the family and the selected version before use. Existing CLI publishing remains available. Use & activity provides capability-specific instructions, policy Apply/Restore actions where applicable, and recorded job references. Non-administrators see only their own jobs. Unsubmitted local experiments are not counted. Policy application reports the responding process, not acknowledgement from every replica.

Inspect a version before choosing it

Open a plugin’s Files & changes tab to inspect the exact selected version, including disabled versions. It shows the recorded admission method and actor, the SHA-256 of the stored archive, and its unpacked content digest. Older packages without recorded provenance are labeled Not recorded; a hash does not establish publisher trust. Search package paths and preview UTF-8 text up to 128 KiB and 4,000 lines. Binary files show size and SHA-256 without being executed or unpacked as nested archives. The server verifies the package content digest before returning inspection results. Invalid archives and digest mismatches are errors, not empty file lists. Choose Compare versions and select a base version. The comparison runs from that base to the currently selected version, showing added, removed and modified files. Text differences are bounded to 2,000 lines and 256 KiB, with an explicit truncation notice. Comparing does not add, enable, recommend or activate a release. Add a new immutable version through Upload first, inspect it, then explicitly enable or recommend it as appropriate.