Skip to content

Export and serving

The problem. A trained policy that cannot leave the process it was trained in is not a deliverable. Weights alone are not enough to run one: acting needs the shapes it was trained against, judging needs the reward it was trained under, and none of that is in a checkpoint — while nothing stops a checkpoint being loaded against the wrong task and producing numbers that look fine. What is missing is a record: this policy, these schemas, this reward, this environment.

The shape here. A bundle — a directory holding a manifest beside the weights — and a runner that drives an environment with one, inference only, writing the same trace a training run writes, so skyfall-crl eval scores a served policy with no special case. A bundle is self-contained by default (weights copied inside, referenced relatively — movable, archivable, handable as one object), and everything the environment supplies is optional: an environment that declares no spaces and reports no reward specification still produces a useful record, because absence is written down rather than invented.

What you implement: nothing, usually. An array policy that wants to be servable implements load_weights(path); everything else is recorded automatically.

Exporting

Export happens during a run — the only moment the environment and the trained algorithm are both in hand:

skyfall-crl run --config experiment.yaml --export bundles/my-policy

A matrix gives every cell its own subdirectory; --export-external DIR records an absolute weights path instead of copying (smaller, machine-bound, and the manifest says so). From Python, export_bundle takes the environment and algorithm directly, and run_experiment(..., export_dir=...) is the hook the CLI uses. Name the policy in the document — the bundle records how to rebuild it, and a backend's internal default policy cannot be recorded.

The complete manifest field specification, with a real produced example, is in the file-formats reference. Two details matter most in practice: the reward specification is stored by value, because a world can declare one inline and a name would not survive the trip; and the spaces are encoded losslessly — infinite bounds, dtypes, Discrete.start, Text alphabets and zero minimum lengths all round-trip, none of which a naive encoding preserves.

Serving

skyfall-crl serve --bundle bundles/my-policy --steps 200 --seed 7 --traces served/traces.jsonl
skyfall-crl eval --traces served

The bundle names the environment and the configuration schedule, so serving needs nothing else — and the recorded schedule is replayed by default, so a served trace segments exactly as the training trace did and the two are comparable; --stationary declines it deliberately. --env and --env-kwargs override the environment, because serving a policy against a world it was not trained on is legitimate and should be something you asked for. Name --seed on any serve you intend to score, and --auto-reset for an environment with genuine terminal states — the same rule training follows. Serving means inference against a live environment, not a web server; nothing starts a process or opens a port.

Two ways a policy is put back

The manifest's format selects one, because there genuinely are two: a language model is rebuilt from its checkpoint, while an array policy is built and then filled.

format The recorded factory receives Who this is
checkpoint the checkpoint directory, as its first argument a language policy
weights nothing; the rebuilt policy's own load_weights(path) is handed the file an array policy
absent no weights were recorded a backend that cannot checkpoint

A policy whose bundle records weights but which has no way to take them is refused, not built fresh and left empty — a partially restored policy still acts, like something that was never trained, while every log line reports success.

Limits

No server, as above. A backend's auxiliary state is not saved: checkpointing writes the policy, so a reloaded EWC policy has no consolidation memory and a reloaded LCM policy has no context encoder — the policy without the algorithm's memory (Fidelity records what each loses). And nothing validates that a bundle's environment is the one you serve it against beyond what you pass — overriding is deliberate, and whether the schemas still fit is your call.


API: every public symbol, with signatures — Export and serving — API reference.