Cooperative pause, stop, and resume control for detached Hugging Face Jobs
Project description
HF Job Control
HF Job Control is a Python library and CLI for cooperative control of detached
Hugging Face Jobs. A running job saves its work at a safe boundary before it
responds to run, pause, stop, or abort.
The control history stays in a versioned Hugging Face dataset. Checkpoints use content-addressed keys in a Hugging Face Bucket, while a separate dataset stores observed status and immutable receipts.
Installation
HF Job Control requires Python 3.11 or newer. Install the CLI from PyPI:
uv tool install hf-job-control
A submitted job should pin an exact package version and verify the built wheel's SHA-256. A Git commit remains available before the first release or when testing an unreleased change:
uv tool install "hf-job-control @ git+https://github.com/osolmaz/hf-job-control@<commit>"
Agent skill
The Python package includes the comprehensive Agent Skills package under
skills/hf-job-control. The CLI exposes it
through the Skillflag interface:
hf-job-control --skill list
hf-job-control --skill show hf-job-control
hf-job-control --skill export hf-job-control | skill-install --agent codex --scope user
The skill covers operator workflows, worker integration, protocol records, incident recovery, and launch or completion audits. The export contains its references, schemas, agent metadata, and launch-specification example.
Pi can also load the public HF Job Control skill from a pinned Git revision:
pi install git:github.com/osolmaz/hf-job-control@<tag-or-commit>
The package.json manifest and the Python CLI expose only the public skill.
The repository's internal documentation helper is excluded.
Operator workflow
Set the private Hub resources used by the run:
export HF_JOB_CONTROL_REPO=owner/jobs-control
export HF_JOB_STATUS_REPO=owner/job-status
export HF_JOB_ARTIFACT_BUCKET=owner/job-artifacts
Create a logical run. The default ID comes from @osolmaz/petname:
RUN_ID="$(hf-job-control create --reason "Start training" | jq -r '.control.run_id')"
Launch one physical attempt from a checked-in launch specification:
hf-job-control launch "$RUN_ID" launch.json
The first launch stores this specification under the logical run. Later attempts must match it byte for byte after canonical JSON serialization.
A pause takes effect after the next safe checkpoint:
hf-job-control pause "$RUN_ID" --reason "Release the worker"
hf-job-control watch "$RUN_ID"
Resume verifies the paused checkpoint and publishes the next run generation.
Exact and boundary adapters carry the checkpoint reference forward. Restart
adapters begin again from their immutable inputs. Launching creates a new
physical job under the same logical run ID:
hf-job-control resume "$RUN_ID" --reason "Continue from the checkpoint"
hf-job-control launch "$RUN_ID" launch.json
Stop completes the logical run at its next safe boundary:
hf-job-control stop "$RUN_ID" --reason "The registered metric has converged"
hf-job-control watch "$RUN_ID"
Pass --expected-generation to a mutating command when another operator or
process could write concurrently.
Remote canary
The built-in canary runs a small counter on cpu-basic. It exercises the same
Hub reads, checkpoint uploads, status writes, and receipts as a real worker:
hf-job-control canary "$RUN_ID" \
--status-repo "$HF_JOB_STATUS_REPO" \
--artifact-bucket "$HF_JOB_ARTIFACT_BUCKET" \
--package-ref "git+https://github.com/osolmaz/hf-job-control.git@<tag>"
Use the normal pause, resume, launch, and stop commands against the
canary run.
Worker integration
A worker supplies a checkpoint adapter and calls the controller at each safe boundary:
from hf_job_control import (
Boundary,
Controller,
ControllerConfig,
HubBucketArtifactStore,
HubControlStore,
HubStatusStore,
)
controller = Controller(
ControllerConfig.from_environment(),
control_store=HubControlStore("owner/jobs-control"),
status_store=HubStatusStore("owner/job-status"),
artifact_store=HubBucketArtifactStore("owner/job-artifacts"),
)
controller.start(checkpoint_adapter)
for step in training_steps:
train(step)
if is_safe_boundary(step):
decision = controller.boundary(
boundary=Boundary(name="half-epoch", sequence=step),
adapter=checkpoint_adapter,
metrics={"exact": evaluate()},
)
if decision.should_exit:
finalize_outputs()
controller.finish(decision)
raise SystemExit(decision.exit_code)
The adapter writes and restores the application's checkpoint payload. The
controller verifies the bundle and Hub revisions, tracks command generations,
and writes both receipts and observed state. On Hugging Face Jobs, it also
copies the built-in JOB_ID into those records.
Resume guarantees
Adapters declare one resume mode. exact restores every state item needed to
match uninterrupted execution. boundary restarts from the last committed
unit. restart repeats the job from immutable inputs. unsupported rejects a
pause at the safe boundary and exits failed because it cannot promise a usable
checkpoint.
For PyTorch training, an exact adapter normally includes model parameters, optimizer and scheduler state, mixed-precision state, random-number generator state, data order, global step, and model-selection counters.
Monitoring
hf-job-control watch reads durable project status. W&B can receive the same
metrics through WandbMetricSink, but W&B is optional and never controls
checkpoint or resume state.
Safety
Hugging Face Jobs defaults to a 30-minute timeout. Every launch specification must set an explicit timeout long enough for the workload.
The controller writes a checkpoint before reading control. It writes an applied-control receipt before changing lifecycle state. If control remains unavailable after retries, the worker pauses instead of continuing forever.
See the protocol for file layouts and action semantics. The implementation plan records the design and test requirements.
License
Project details
Release history Release notifications | RSS feed
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 hf_job_control-0.2.0.tar.gz.
File metadata
- Download URL: hf_job_control-0.2.0.tar.gz
- Upload date:
- Size: 166.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f66d3e9069d56dd061a1a26d3e242e618408588196095ea2826bdcf287a31f6d
|
|
| MD5 |
bd00a957deaf70ecb4140eb40136a76e
|
|
| BLAKE2b-256 |
e6f28e1589746d52d1ebe1b680b117a8a40253411cc849f1270fc09830ee4519
|
File details
Details for the file hf_job_control-0.2.0-py3-none-any.whl.
File metadata
- Download URL: hf_job_control-0.2.0-py3-none-any.whl
- Upload date:
- Size: 74.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1a87a0dc56239384bf51e3a8c6ce051506805f0d9d59434c9f490f53723ec8ac
|
|
| MD5 |
d56268021fd2c502d2bf2f19ecb61621
|
|
| BLAKE2b-256 |
facd9105aff0323b68c1ca86677a47c09c90b75371a634070be202cb5ce8ffaa
|