reactor.yaml is the model spec. One file declares what the model is called, how the runtime loads
it, how its image is built, and where it runs. reactor init writes it, and every other reactor
command reads it.
The file sits at the root of your workspace. A workspace is the directory tree rooted at a
reactor.yaml, so you can run commands from a subdirectory. The CLI searches upward for the file
and stops at the first directory that holds a .git entry, so the search never leaves your
repository.
The name is exactly reactor.yaml. There is no .yml spelling. reactor model register and
reactor model update take --model-file <path>, which points at a different path rather than a
different name, and reads a .json file as JSON.
Check a file without contacting the server:
$schema
reactor.yaml
$schema declares which generation of the format you wrote. It is a marker, not a URL. Nothing is
published at that address, so do not open it and do not point an editor at it for completion.
Write
$schema: reactor/v2 at the top of every new file. Older formats covers
what happens to a file that predates it.
model:
What the model is called on the platform, and the hardware it asks for.
model.resources:
cpu and memory each take a request and a limit, both Kubernetes quantity strings such as
500m or 4Gi. The limit must be greater than or equal to the request. reactor.yaml is the only
place to set them, because there are no equivalent CLI flags. Leave either key out and the Reactor
API fills in a value. See Gotchas.
model.resources.gpu:
The scaffold requests one
NVIDIA_B200.
Accelerator type codes
These are the codesmodel.resources.gpu.type accepts. The older model.gpu.type takes the same
set. Write a code exactly as it appears here, because the Reactor API rejects any other string.
The family is the only part of a code the CLI reads, and it comes from the prefix. A code that
starts with
AWS_TRAINIUM_ or AWS_INF_ is AWS Neuron hardware. Every other code is a GPU.
This table copies a list the platform owns, so a platform release can add to it. Print the set your
platform accepts today:
reactor model register, reactor model update, and
reactor model deploy send it to the Reactor API, which schedules the model on that hardware.
A Neuron code is the one code that changes a local run, and it takes a flag away rather than adding
one. Docker’s --gpus does not reach Neuron devices, so an AWS_TRAINIUM_ or AWS_INF_ code makes
reactor run drop that flag and print a note. It drops the flag even when you passed --gpus all.
Expose the device files your host has instead:
runtime:
How the runtime inside the container finds and loads your model code.
The Go parser does not require
import, so a file without it passes reactor validate and then
fails when the container starts. Treat it as required.
weights_path is read by three callers, each with its own precedence:
reactor runtakes the bind mount from--weights, then$REACTOR_WEIGHTS_PATH, thenruntime.weights_path. With none of the three set, nothing is mounted.reactor model publishandreactor weights uploadtake the upload source from--weights, thenruntime.weights_path, then./weights.- Inside the container, the runtime reads
$REACTOR_WEIGHTS_PATH, thenruntime.weights_path, then falls back to its own cache directory.
build:
The image. reactor build renders a Dockerfile from this block in memory, so a scaffolded workspace
ships no Dockerfile to maintain. Build the image walks through the
workflow and the build secrets. The table below is the full field list.
Both environment blocks reject six names the generated image sets for itself:
HOST,
LD_LIBRARY_PATH, PATH, PORT, PYTHONUNBUFFERED, and VIRTUAL_ENV.
build.run[]
Each step is either a plain string, which is the command, or a mapping:
A mount takes three keys.
type must be secret. id is required, and it matches the id you pass
to reactor build --build-secret. target is the optional mount path.
deployment:
Where the model runs.
Each entry takes two keys, and both are required:
count: 0 on a named region is a deliberate scale to zero, and it is applied. An empty instances:
list is different: it declares no plan, so the deploy warns and leaves per-region capacity
unchanged. The scaffold requests one instance in us-west. The Reactor API checks quota and
availability, and a deploy either applies the whole plan or changes nothing.
Key casing
The casing is not uniform across blocks, and the CLI accepts only one spelling. Copy the exact key:model:uses hyphens for its multi-word keys:display-name,extra-args.runtime:,build:, anddeployment:use underscores:weights_path,runtime_version,base_image,cuda_version,python_version,system_packages,python_requirements,python_indexes,build_env,runtime_env.
build.runtime_version and model.display-name are the pair that catches people. Both are
multi-word keys in the same file, spelled two different ways.
Which commands read which blocks
model.description, model.public, model.resources.cpu, model.resources.memory, and
model.resources.gpu.count reach the Reactor API through register and update. They have no
effect on a local run.
reactor run is the one command that does not search upward. It reads the reactor.yaml in the
current directory only, so run it from the workspace root.
How it relates to the other files
reactor init scaffolds four files that work together, plus a weights directory:
config.yaml
config.yaml holds nothing Reactor reads. The runtime loads the file that runtime.config names
and hands the parsed mapping to the model’s load() method. The contents and the format are yours.
A relative path resolves against the workspace root. With no runtime.config, the model receives an
empty mapping.
reactor run -- --model.<key>=<value> merges overrides on top of the loaded file. Those overrides
need runtime.config to be set, and fail with an error when it is not.
deployment.yaml
deployment.yaml is a standalone deployment plan, and it is not deprecated. One thing changed:
reactor init no longer writes it. A fresh workspace’s plan is the deployment: block inside
reactor.yaml, and reactor deploy init still writes a deployment.yaml for the CI path.
When both exist, deployment.yaml wins:
The scaffolded
deployment.yaml ships an empty instances: list, which declares no plan. Add the
file to a workspace that already carries a plan, and that plan stops being applied. Fill in the list
to restore it.
A minimal file
The smallest file that both parsers accept, and that supportsreactor build and reactor run:
reactor.yaml
<runtime-version> with the release reactor init pinned in your workspace, or pick one
from the runtime changelog.
reactor model publish and reactor model deploy also need model.version. With no deployment:
block, reactor model deploy warns and provisions nothing.
A fully populated file
Every key the format models, at its correct nesting.reactor.yaml
base_image is left out on purpose. Setting it replaces the base that cuda_version picks, which
makes cuda_version cosmetic.
Gotchas
A Dockerfile on disk switches most of build: off
When the workspace has a Dockerfile, reactor build builds that file verbatim. Nine fields then
stop applying: base_image, cuda_version, python_version, system_packages,
python_requirements, python_indexes, build_env, runtime_env, and run. The build prints a
note naming the fields it dropped, so read it. platform and runtime_version still apply. Use
reactor build --no-dockerfile to build from reactor.yaml instead.
base_image is not checked, but it is still constrained
The CLI uses the ref verbatim and validates nothing. But the generated image installs system
packages with apt-get. A base that is not Debian- or Ubuntu-derived fails the build instead of
the spec check.
model.display-name does nothing
The key parses, and then register and update both print that it is ignored and safe to remove.
Set model.description instead.
An absent model.public is not public: false
The key has three states. On register, leaving it out registers the model private. On
reactor model update, leaving it out keeps whatever the platform already holds, while an explicit
true or false overwrites it. Write the value you mean.
build.runtime_version has no default
The scaffold pins a version, which makes the field look defaulted, but the parser has no fallback. A
generated build with the key missing fails with an error naming it. Every workspace must carry it.
The CPU and memory defaults come from the Reactor API
They are not in this file. Leavecpu or memory out and the Reactor API fills in the request and
the limit at deploy time. Those values can change, so treat them as a platform behavior rather than
as a schema default. Set the keys yourself when a model needs a specific size.
Older formats
The format is versioned, and older files still load. Three shapes qualify:$schema: reactor/v1,
the older apiVersion and kind header, and no header at all. Each is upgraded as it loads, and
each earns a deprecation warning. The first generation also accepted a flat shape. There model was
a string rather than a mapping, beside the scalar keys name, config, and weights_path.
Two keys moved when the second generation landed. A deployment plan’s instances: now sits under
deployment:, and the recorder’s recording: block sits under runtime:. Under
$schema: reactor/v2 either key at the top level is a hard error rather than a silent drop, which
is what catches a half-finished migration. Move the block down one level, or drop $schema and let
the upgrade handle it.
Write new files as reactor/v2.