<owner>/<name>@<version>. The manifest declares how to
connect or run the environment; the bundle itself is not a running sandbox.
Layout
deployment: local
requires tasks.jsonl; remote services and hosted images own their task data.
tasks.jsonl
One JSON object per line:train | eval
default:"train"
Which half of the taskset this row belongs to. Declared per row.The platform sets which half a job sees from the operation itself, so a training job cannot be
handed the held-out tasks and an evaluation cannot ask for the training ones. An evaluation against
a split the environment never declared is refused rather than quietly served the training tasks —
that is the one failure this field exists to prevent, and it is the one that looks like a good
score.
manifest.json
string
required
Always
tuneplane/environment/v1.nemo-gym | openenv
required
The interaction contract. OpenEnv uses reset / step / state; NeMo Gym uses trajectory sessions.
local | remote | container
required
Who starts the environment implementation.
local runs inside the job, remote connects to
an existing service, and container asks the executor to host an image. NeMo Gym currently
supports only local. Schema v1 and the former compound protocol names are rejected.object
required
{"kind": "rubric|plugin|endpoint", "ref": "..."} — what decides whether a task was completed.
See verifiers.array
What the agent may call: a name, an endpoint, and a JSON Schema for the arguments.
object
{"plugin": "<owner>/<name>", "version": "...", "entrypoint": "module:ClassName", "digest": "..."}.
Required for nemo-gym. The code belongs to a capability: environment plugin; the platform writes at
most a two-line shim that imports it.bool
default:"false"
True when the harness runs model-generated code. A job that needs one, on a deployment with no
sandbox provider configured, is refused — it does not fall back to running the code in the
training container.
string
default:"other"
NeMo Gym’s metrics-grouping category. Required and validated for
nemo-gym, meaningless elsewhere.
One of math, coding, agent, knowledge, instruction_following, long_context, safety,
games, translation, e2e, rlhf, other.string
The OCI image for an
openenv environment. Resolved as a pinned runtime artifact like every other
image; never pulled ad hoc.url
Only valid with
deployment: remote. Use either a fixed endpoint, a Fleet, or registered runners.
Do not specify both endpoint and Fleet.Protocol and deployment
Two interaction contracts and three deployment choices describe four supported combinations. A sandbox provider such as Docker or E2B is a separate choice; it is not a protocol value.- OpenEnv + local
- NeMo Gym + local
- OpenEnv + remote
- OpenEnv + container
Turn-level. The platform runs the environment server from the taskset it holds, and the trainer
drives the episode itself through openenv-core’s client:
reset, step, state.Used by TRL, SkyRL, Unsloth and Axolotl. No harness needed — the trainer already owns the loop.Reaching a remote environment
Anopenenv (deployment: remote) environment only works if the training job can open a connection to it.
The control plane resolves where it answers and hands that address over; it never carries the
episode itself (ADR-0025).
An episode is a session of turns, one per generation round, and routing it through the process
that decides admission would put a hop nowhere near the data on every one of them.
So when the environment sits on a network the cluster cannot reach, one of these has to be true:
What none of them is: proxying through the console. If you find yourself wanting that, the answer
is usually the first row.
Or remove the question. An
openenv (deployment: container) environment runs in a container beside the job, so
there is no distance to cross and none of the three rows applies. Where the environment can be
containerised, that is the route to reach for — and it is where the wider OpenEnv ecosystem is
heading. It needs a kubernetes fleet today.The harness
The code that drives a model through an environment, supplied as acapability: environment plugin.
Needed for the materialised route, where the framework imports and runs it. Not needed for the
served turn-level route, where the trainer drives the episode itself.
plugin.yaml
harness.digest in the manifest pins the harness package the environment was authored against.
Leave it empty when a team ships the harness alongside the environment; set it when the two are
versioned apart and a mismatched harness would score differently. It is verified at submission,
never at rollout.
Push and reference
<owner>/<name> or bare name
required
A bare name goes into your own namespace.
string
required
Immutable once pushed.
flag
Only applies when the environment is first created.
Check it worked
Next
Verifiers for the three ways completion is decided · Writing rubrics · Using an environmentQuality evidence
The user-owned runnercommon/envkit/quality.py in tuneplane-examples executes your callbacks,
then reports through Reporter.environment_quality(). It belongs in your project, not in the
control plane. There is no universal model/scorer implementation: connect the same verifier and
harness used by your environment, pin a checkpoint, and disable policy updates during measurement.
Create an adapter factory such as my_quality:adapter returning keyword arguments for measure():
Use
verifier_fixtures(verify, fixture_task, correct=..., incorrect=...) to execute positive,
negative and verifier-execution fixtures against your real verifier. The negative fixture should
report fail when the known bad answer is rejected. For sandbox-required environments, add
egress_allowed, egress_denied and reference_isolation callbacks that actually probe your
runtime. Absence is never treated as success. Callbacks must set their own network/process timeouts.
A generation callback can return a string or Prediction(text=..., tokens=...); missing token
usage stays unknown. Callback exceptions become infra_error, not model failures. The runner
records all planned task trials, saves a complete JSON report and a separate local fixture-evidence
file, then uploads metadata. Raw fixture evidence stays local; protect that file because it may
contain sensitive diagnostics. An upload failure leaves the report available locally and fails
explicitly. No model response or reference is included in the ingest report.
Inside the owner’s job, with the environment version pinned:
TUNEPLANE_JOB_ENVIRONMENT_SPLIT. Locally, omit --upload and point --directory at your original
authoring directory. This is a callable/CLI integration for an existing project job, not a new
one-click model execution service. GPU generation and sandbox enforcement remain the adapter’s
runtime responsibilities.