HPC orchestrator for Claude Code and external agent harnesses
Project description
hpc-agent
HPC orchestrator for array-batch experiments on SGE/SLURM clusters. Two surfaces over one core:
- Slash commands for humans in Claude Code (
/submit-hpc,/monitor-hpc,/aggregate-hpc,/campaign-hpc) — interactive markdown templates inslash_commands/commands/*.mdthat walk you through choosing a cluster and authoring.hpc/tasks.py. The four workflow triggers cover every end-user moment; entry-point onboarding, axis classification, and axes-init are folded into/submit-hpc's escalation playbook (the worker escalates when it can't proceed; the playbook walks the user through the dialog and the agent invokes the relevant skill with a resolved spec). Environment preflight (SSH agent, cluster reachability) is a one-time-per-machine CLI step:hpc-agent setup --cluster <name>probes the cluster and writes a 24h cache marker/submit-hpc's Step 6b gate reads — runtime workflows assume setup succeeded. - CLI for agents and automation (
hpc-agent <subcommand>) — JSON-in, JSON-out, exit codes. Designed to be invoked via aBash-style tool by external orchestrators. This is a POSIX-native agent surface: any tool that can shell out and parse JSON can drive a cluster — seedocs/reference/agent-surface.md. For integrators:docs/integrations/CONTRACT.md.
Both surfaces invoke hpc-agent <subcommand>. The slash commands are pure markdown that orchestrate the binary; the binary's atomic-ops layer (the per-subject runners under hpc_agent/ops/) ensures cross-surface state — in-flight runs, journal records under ~/.claude/hpc/<repo_hash>/ — is shared automatically.
Quick Start
For humans (Claude Code)
pip install hpc-agent # or `pip install -e .` from a checkout
hpc-agent setup # copy commands + skills
hpc-agent setup --cluster hoffman2 # probe cluster + populate 24h preflight cache (run once per cluster)
hpc-agent setup (no flags) copies the bundled slash commands into
~/.claude/commands/ and the skills into ~/.claude/skills/ —
idempotent. Re-run with --cluster <name> once per machine + cluster
to probe SSH agent reachability, ssh/transport on PATH,
clusters.yaml parseability, and TCP :22; on a green probe it writes
a 24h cache marker that /submit-hpc's Step 6b gate consults, so the
first submit doesn't re-run the check. Pass --dry-run to preview.
Each preflight check's detail field carries actionable remediation
prose, so a red probe tells you exactly what to fix. Every command
(/submit-hpc, /monitor-hpc, /aggregate-hpc, /campaign-hpc)
and skill ships inside the package.
Once installed:
hpc-agent setup --cluster <name>(once per machine + cluster) — install assets and probe each cluster you'll submit to. Runtime workflows assume setup succeeded; re-run if SSH credentials or a cluster's reachability change./submit-hpc— answer prompts about cluster, executor, grid params. The worker escalates with structured intent prompts (entry-point onboarding, axis classification) when it can't proceed; the in-chat agent walks the user through the escalation playbook and invokes the relevant skill with the resolved spec./monitor-hpcto monitor,/aggregate-hpcto collect results.
For agents and automation
pip install hpc-agent
hpc-agent setup --cluster hoffman2 # one-time: install assets + probe cluster + write 24h cache marker
hpc-agent interview --spec intent.json --campaign-dir <d> # persist campaign intent next to tasks.py
hpc-agent recall --root ~/experiments --task-kind <kind> # query past interviews for next-interview grounding
hpc-agent submit --spec spec.json # JSON envelope on stdout
hpc-agent status --run-id <id> # one-shot snapshot; poll as needed
hpc-agent aggregate --run-id <id> --wave 1 # combiner + result pull
Stdout is a single-line JSON envelope: {"ok": true, "idempotent": ..., "data": {...}} or {"ok": false, "error_code": ..., "retry_safe": ..., "remediation": ...}. Exit codes: 0 ok, 1 user error, 2 cluster/network, 3 internal. Full schema in docs/reference/cli-spec.md; JSON Schema files for runtime validation under hpc_agent/schemas/.
For integrators
hpc-agent is Bash-invokable from any agent harness with a JSON
parser. See docs/integrations/CONTRACT.md
for the full contract: the spawn env block,
error_code → retry policy table, the find-prior-run → submit →
monitor-summary → verify-aggregation-complete workflow, the
.hpc/tasks.py boundary, and the executor import allowlist.
The canonical reference for .hpc/tasks.py is shipped inside the
package at
src/hpc_agent/models/mapreduce/templates/scaffolds/tasks_example.py.
It demonstrates three patterns (Cartesian product, chunking by row
count, date-window backtests) inline. Integrators locate it at runtime
via from hpc_agent import _PACKAGE_ROOT or rglob("tasks_example.py").
The most common first-time failure is the harness's default-empty
spawn env dropping SSH_AUTH_SOCK. hpc-agent
status/aggregate/reconcile fail fast with error_code:
"ssh_unreachable" (exit 2) instead of hanging on auth — run
hpc-agent setup --cluster <name> once on each machine to verify the
spawn env and populate the 24h cache marker that /submit-hpc's
Step 6b gate reads. hpc-agent does not kill cluster jobs by design
(settings.json denies scancel/qdel); if the integrator decides
a run is bad, stop polling and let it expire.
Standalone usage
Organize your experiment repo
Keep standalone executor scripts in a dedicated directory, separate from shared utilities:
my_experiment/
├── executors/ # or src/ — each file is a runnable experiment
│ ├── ml_ridge.py # python3 executors/ml_ridge.py --help
│ ├── ml_xgboost.py
│ └── dl_patchts.py
├── lib/ # shared utilities (not executors)
│ ├── loading.py
│ └── transforms.py
└── data/
Each executor accepts experiment-specific arguments (--horizon, --start, --end, --features, etc.). No HPC awareness is needed — all parameters arrive as CLI flags.
Run
hpc-agent setup --cluster <name> → one-time per machine: install assets + probe cluster
/submit-hpc → discovers executors, walks you through .hpc/tasks.py, syncs code, submits
/monitor-hpc → tracks completion per grid point, diagnoses failures, auto-resubmits
/aggregate-hpc → validates completeness, runs aggregation, downloads summaries
Example conversation:
You: /submit run ridge and xgboost with horizon=[1, 5, 25]
Claude: I found these executors in src/:
ml_ridge.py — --horizon, --start, --end, --output-file
ml_xgboost.py — --horizon, --start, --end, --output-file
Proposed plan:
Cluster: hoffman2 (SGE)
Grid: executor=[ml_ridge, ml_xgboost] × horizon=[1, 5, 25] → 6 grid points
Total: 6 tasks
Resources: 1 CPU, 16G, 4:00:00
Confirm?
You: yes
Claude: Submitted job 12345678 (6 tasks). Run /monitor-hpc to track progress.
No config files required. Claude discovers your executors by reading their source and --help, then suggests resources conversationally based on the executor and your input.
How It Works
The framework's contract with your experiment is a @register_run-decorated Python function with typed kwargs — that function can live in a notebook, a .py script, or a package module; discover_runs AST-walks all three indifferently. See docs/internals/experiment-contract.md for the canonical description.
The boundary between hpc-agent and your experiment repo is documented in docs/reference/boundary-contract.md and enforced by tests/test_boundary_contract.py.
- Claude reads your executor scripts and their
--helpoutput. - You describe what to run in natural language — Claude walks you through writing
.hpc/tasks.pyonce: a small Python module exposingtotal()andresolve(task_id)that returns the per-task kwargs. The file is committed to git and reused on every subsequent submit. - A per-run sidecar
.hpc/runs/<run_id>.jsonrecords the executor command, result-dir template,cmd_sha, and wave map for this particular submission. - The framework executor
_hpc_dispatch.py(zero deps, stdlib-only) is deployed to the cluster's.hpc/bydeploy_runtime. - The job template runs the dispatcher, which imports your
.hpc/tasks.py, callsresolve(task_id), formats the result_dir, and execs your executor command with kwargs as env vars. - Your executor reads kwargs as ordinary env vars (uppercased +
HPC_KW_*) — no HPC awareness needed.
Parallelism Model
The parallelization axis lives entirely in user code (.hpc/tasks.py). The framework is agnostic to whether you're doing a Cartesian grid, chunking by row count, date-window backtests, or something else — it just calls total() and resolve(i). The canonical reference at hpc_agent/models/mapreduce/templates/scaffolds/tasks_example.py shows three patterns inline; the agent helps you keep whichever applies and delete the rest.
Memory across campaigns
Two primitives — interview and recall — close the loop between consecutive campaigns. The interview agent (Claude Code or any external orchestrator) persists structured intent (goal, task_count, budget, abort_if, task_generator, cluster_target, transcript, provenance) into <campaign_dir>/interview.json next to the materialized tasks.py. The next interview calls recall --root <experiments-dir> to query past intents, returning recency-sorted summaries plus a 3-tier rollup (counts/histograms/quantiles, optional walltime aggregation, optional per-generator parameter envelopes). Observed ranges only — reasoning over them stays in the calling agent.
See docs/workflows/memory-across-campaigns.md for the full flow, including the task_generator typed materializer (5 shapes: enumerated, cartesian_product, items_x_seeds, numeric_logspace, numeric_linspace) and the ~/.hpc-agent/config.json:experiment_roots default-root config.
Throughput Optimization
hpc-agent automatically optimizes job submissions for cluster constraints. When constraints are configured (max array size, walltime, concurrent job limits), the optimizer packs tasks into batched waves:
- Tasks are split into arrays of ≤max_array_size
- Arrays are grouped into waves of ≤max_concurrent_jobs
- Waves are staggered via scheduler dependencies (SLURM
--dependency, SGE-hold_jid) - Total wall-clock time is estimated when per-task duration is known
Configure constraints in clusters.yaml (cluster-level); per-experiment overrides resolved at /submit time are persisted to the run sidecar at .hpc/runs/<run_id>.json.
Commands
| Command | What it does |
|---|---|
/submit-hpc |
Discover executors (scaffolds inline if none found), build grid conversationally, write .hpc/tasks.py with FLAGS dict + .hpc/cli.py dispatcher, sync code, submit array jobs. Carries an escalation playbook covering entry-point onboarding, axis classification, and axes-init dialogs. |
/monitor-hpc |
Poll status, diagnose failures, auto-resubmit, self-schedule next check |
/aggregate-hpc |
Validate completeness, run aggregation on cluster, download summaries |
/campaign-hpc |
Closed-loop iteration: tag submits, read prior history, repeat /submit-hpc campaign_id=<slug> until the strategy stops. Carries the validate-campaign findings interpretation guide. See docs/workflows/campaign.md. |
Setup is a CLI step, not a slash: run hpc-agent setup --cluster <name> once per machine + cluster (see Quick Start above). Each preflight check's detail field carries actionable remediation prose.
Primitives
The slash commands above compose ~50 primitives exposed as hpc-agent <name>. Full machine-readable catalog at docs/generated/operations.md (auto-regenerated). High-traffic ones for agent orchestration:
| Primitive | Replaces |
|---|---|
submit-flow / submit-flow-batch |
rsync + deploy + qsub + record (single or N-spec batch with shared rsync). Auto-dispatches when the spec is {specs: [...]}. |
monitor-flow |
Poll-and-combine loop the slash command's tick body wraps. |
aggregate-flow |
rsync_pull _combiner/ + reduce_partials + optional summary pull + ingest runtime samples. |
build-submit-spec |
Resolved-interview-values → validated submit_flow.input.json spec. |
build-tasks-py |
Cartesian-product axes → .hpc/tasks.py from the canonical Pattern 1 template. |
discover-executors / discover-reducers |
Scan repo for executor scripts / aggregator scripts (find existing reducer instead of writing a fresh one). |
decide-monitor-arm |
Pick cron/loop/none + cadence + cron schedule for scheduling the next monitor tick. |
monitor-summary |
Canonical user-facing tick summary (byte-stable framing). |
summarize-submit-plan |
Canonical pre-submit confirmation summary. |
verify-canary |
Wait + grep + output-check protocol for 1-task canary submissions. |
verify-aggregation-complete |
All-waves-combined / all-tasks-present / no-cross-run-contamination invariant report. |
suggest-setup-action / find-prior-run |
/submit-hpc Setup priority cascade + cmd_sha resume detection. |
prune-orphan-sidecars |
Clean half-baked sidecars from failed batches. |
hpc-agent <name> --help shows the per-primitive args; many take --spec <path> for a JSON input. See docs/primitives/<name>.md for the per-primitive contract (idempotency, side effects, error codes, schemas).
Configuration
clusters.yaml (required)
Cluster infrastructure definitions. Ships inside the package at hpc_agent/config/clusters.yaml. Override the active path with HPC_CLUSTERS_CONFIG=/your/clusters.yaml (useful for integrators who want to keep their cluster definitions outside the package):
hoffman2:
host: hoffman2.idre.ucla.edu
user: <your_user>
scheduler: sge
scratch: <your_scratch>
modules: [python/3.11.9]
conda_source: /u/local/apps/anaconda3/2024.06/etc/profile.d/conda.sh
conda_envs: [<your_env>] # optional — Claude presents these as options
gpu_types: [a100, h200, a6000]
~/.hpc-agent/config.json (optional)
Per-user config for the recall primitive's default --root. List one or more directories under experiment_roots and recall walks them all when --root is omitted:
{
"experiment_roots": [
"/home/user/experiments",
"/scratch/user/campaigns"
]
}
The --root CLI flag still wins when set. If neither flag nor config is present, recall errors with spec_invalid rather than silently falling back to cwd.
Caching
Claude remembers your preferences (cluster, executor directory, environment, resources) across conversations via Claude Code memory. The .hpc/runs/<run_id>.json sidecars (paired with .hpc/tasks.py) serve as the submission record for monitoring and resubmission.
Job Templates
| Template | SGE | SLURM |
|---|---|---|
| CPU array | hpc_agent/models/mapreduce/templates/runtime/sge/cpu_array.sh |
hpc_agent/models/mapreduce/templates/runtime/slurm/cpu_array.slurm |
| GPU array | hpc_agent/models/mapreduce/templates/runtime/sge/gpu_array.sh |
hpc_agent/models/mapreduce/templates/runtime/slurm/gpu_array.slurm |
Templates are parameterized via environment variables injected at submission time. Resolve paths via hpc_agent.get_template_path(scheduler, template). The GPU template is used when the configured resources include gpus; otherwise the CPU template is used.
Supported Clusters
| Cluster | Institution | Scheduler |
|---|---|---|
| Hoffman2 | UCLA IDRE | SGE |
| Discovery | USC CARC | SLURM |
Cluster connection details are in hpc_agent/config/clusters.yaml (or whatever HPC_CLUSTERS_CONFIG points at).
Python API
# Framework subdirectory layout
from hpc_agent import RUNS_SUBDIR, RepoLayout, TASKS_FILENAME, load_tasks_module
# Per-run sidecars (canonical home)
from hpc_agent.state.runs import (
compute_cmd_sha,
find_existing_runs,
find_run_by_cmd_sha,
read_run_sidecar,
write_run_sidecar,
)
# Cluster config + templates
from hpc_agent import _PACKAGE_ROOT, get_template_path, load_clusters_config
# Submission planning
from hpc_agent.infra.constraints import ClusterConstraints, parse_constraints
from hpc_agent.infra.throughput import (
WorkloadSpec,
build_wave_map,
compute_submission_plan,
)
# Remote execution + backends
from hpc_agent.infra.backends import get_backend
from hpc_agent.infra.remote import deploy_runtime
Development
pip install -e '.[dev]'
pre-commit install # auto-runs ruff, frontmatter regen, index regen
pytest -q # 1400+ tests
The pre-commit hook regenerates docs/primitives/*.md frontmatter,
docs/primitives/README.md catalog, and docs/generated/operations.md
from the @primitive registry, then auto-stages the result. Without it
you'll see CI fail on the corresponding --check gates and have to
push a follow-up chore: regenerate ... commit.
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 hpc_agent-0.7.1.tar.gz.
File metadata
- Download URL: hpc_agent-0.7.1.tar.gz
- Upload date:
- Size: 602.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.12 {"installer":{"name":"uv","version":"0.10.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c3b6dd3c113bc963e49ddff5f829d54dc3c58e4f47aaf7fc2f54813763965dc9
|
|
| MD5 |
385c481dc53ccdae698f72ee621b85ae
|
|
| BLAKE2b-256 |
e4c4e44ae4639d51cb3bfa2611d526d26e5e3297c63dd1382cfcbccd6ef50771
|
File details
Details for the file hpc_agent-0.7.1-py3-none-any.whl.
File metadata
- Download URL: hpc_agent-0.7.1-py3-none-any.whl
- Upload date:
- Size: 779.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.12 {"installer":{"name":"uv","version":"0.10.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c1c9aee669dcc6e615c91c841d47748d107fceee7fe420f3d84bee3c27fba999
|
|
| MD5 |
19937d13283e25c8c27995427382fa5a
|
|
| BLAKE2b-256 |
a3aa24f7a40004242bc583f934f0ebea86ad03fed51b0ed61bbc64518f822e9e
|