Skip to content

New Skill: hyperloom-workload-optimizer - #114

Open
lishuoshuo-amd wants to merge 10 commits into
amd:mainfrom
lishuoshuo-amd:add-hyperloom-workload-optimizer-skill
Open

New Skill: hyperloom-workload-optimizer#114
lishuoshuo-amd wants to merge 10 commits into
amd:mainfrom
lishuoshuo-amd:add-hyperloom-workload-optimizer-skill

Conversation

@lishuoshuo-amd

@lishuoshuo-amd lishuoshuo-amd commented Aug 3, 2026

Copy link
Copy Markdown

Summary

Adds hyperloom-workload-optimizer, a skill that autonomously optimizes
end-to-end LLM inference throughput on AMD Instinct GPUs using the Hyperloom
multi-agent optimizer, and reports a validated gain.

Given a model, framework, workload shape (TP/EP, concurrency, ISL/OSL,
precision), an objective and a time budget, the skill explores which levers to
pull per workload — serving/config parameters and environment, framework
enablement and source patches, and hot GPU-kernel rewrites — benchmarks each
candidate, and returns the optimization stack that produced the gain.
Contribution Path A (skill authored in this repository).

Contents

  • skills/hyperloom-workload-optimizer/SKILL.md — skill body
  • skills/hyperloom-workload-optimizer/setup.md — environment setup (bare metal and Docker)
  • skills/hyperloom-workload-optimizer/reference.md — configuration and flag reference
  • skills/hyperloom-workload-optimizer/skill-card.md — governance card
  • skills/hyperloom-workload-optimizer/evals/evals.py — behavioral test
  • walkthroughs/hyperloom-workload-optimizer.md — walkthrough, linked from walkthroughs/README.md
  • Registered in .claude-plugin/marketplace.json; derived manifests regenerated
    via ./.github/scripts/publish.sh

Validation

./.github/scripts/check.sh passes locally: 0 errors across 7 skills, and the
Cursor and Codex manifests are reported up to date.

Add the Hyperloom workload optimizer catalog skill that bootstraps a
workspace, prepares the runtime, collects workload parameters, then
installs, launches, and monitors the optimizer on AMD Instinct GPUs.
Register it in the Claude/Codex/Cursor plugin manifests and walkthroughs.
Remove the primussafe container guard from the behavioral eval; it referenced
an internal platform name. Docker images will standardize on ROCm, so the
generic plain-serving guard is sufficient.
Stop restating custom-advanced docker commands and flags in Phase 1; the image
choice, docker run, and in-container setup are owned by custom-advanced Setup
Configuration. Keep only the catalog's orchestration guardrails.
Persist confirmed Phase 2 values to workload.env and source it in every Phase 3
block so launch no longer silently falls back to TP/CONC/model defaults; guard
empty MODEL_PATH. Add vllm.entrypoints to the IR-1 process scan, parse the
launch-info JSON with python3 instead of jq, align the max-hours default column,
fix the reference IR heading and table of contents, and add a trailing newline
to the walkthrough index.
Read the real optimizer .pid from the launch-info JSON (setsid wrapper $! exits
immediately) and rewrite the pid file. Rebuild the resume path to re-source
.env/workload.env, re-run IR-2/IR-1, resume the explicit session with
--resume-from, and use $PYTHON. Fail preflight when CUDA is unavailable, write
workload.env with a quoted heredoc, launch via $PYTHON, guard MODEL_PATH, and
resolve the monitor session dir from launch-info. Trim SKILL.md under the
500-line limit.

## Phase 1 — Environment prep

Load `hyperloom-custom-advanced` and follow its **Setup Configuration**

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The intro (line 28-30) says this skill "inlines the operator workflow so you can run end-to-end without bouncing across files," but Phase 1/2 delegate the actual setup (image choice, docker run, in-container setup, workload intake) to hyperloom-custom-advanced, which isn't in this PR (it only lands after the wheel installs) and is the demo skill rather than core inference_optimizer. That contradicts the self-contained claim and makes the Docker path non-reviewable if that skill isn't loaded. Can we inline the minimal self-contained setup into this skill's own setup.md, based on core inference_optimizer?

export PYTHON="${PYTHON:-$(command -v python3)}"
export IR1_VRAM_LIMIT_MIB="${IR1_VRAM_LIMIT_MIB:-500}"

"$PYTHON" - <<'PY'

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The preflight (:275-335), launch (:349-382), monitor (:424-437), and resume (:450-474) blocks are many many lines of inline bash/Python. Per the authoring standard, fragile order-dependent code should live in scripts/ and be invoked, not pasted into the body for the agent to reconstruct each run. Can we move these into scripts/ (e.g. preflight.sh, launch.sh, monitor.sh) and have the body call them? That also shrinks the body well under the 500-line cap and makes the steps testable.

export IR1_VRAM_LIMIT_MIB="${IR1_VRAM_LIMIT_MIB:-500}"

"$PYTHON" - <<'PY'
import os, shutil, subprocess, sys

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IR-1 is meant to block launch when a GPU is busy, but the VRAM check can miss that. If amd-smi/rocm-smi returns JSON in a shape the parser doesn't expect, the reading at line 313 comes back empty and gets skipped, so a GPU that's actually occupied looks free and the launch proceeds. Since this is a safety gate, could we make it stop and warn the user when it can't read VRAM, instead of continuing? Right now an unexpected amd-smi output is enough to let a run start on a busy GPU.

Confirm `hyperloom/inference_optimizer/assets/install.sh` exists. Restart the
agent if wheel skills are not visible.

### Credentials and run mode

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two credential gaps:

  1. The skill doesn't help the user choose between Hyperloom's two credential shapes: single gateway (SAFE_API_KEY + OPENAI_BASE_URL) vs the Anthropic split (ANTHROPIC_API_KEY + ANTHROPIC_BASE_URL + CLAUDE_MODEL). Can it ask which one they have and recommend a known-good model, claude-opus-4-8 (preferred) or claude-opus-4-7, since both pass Hyperloom's model gate?
  2. We only check the secret isn't <PLEASE_FILL_IN> (setup.md:91), but Hyperloom does no live key validation, so a wrong/expired key fails late as a 401 mid-run. Can we add a cheap preflight (one small call against the configured base URL) that confirms the key works before the long optimize run? Turns a wasted multi-hour run into a 5-second early failure.


```bash
cd "$INSTALL_DIR" # the directory confirmed above
wheel_url="$(curl -fsSL "https://api.github.com/repos/AMD-AGI/Hyperloom/releases?per_page=20" \

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This resolver takes the newest matching asset across all releases with no prerelease filter, so it currently resolves to 1.0.0a2 (an alpha) and drifts as new releases publish, non-reproducible and can pull a prerelease onto a user's box. Can we skip prereleases (rel.get("prerelease")) and/or pin a known-good version (e.g. latest stable 0.9.0, or an env-overridable HYPERLOOM_WHEEL_VERSION) so bootstraps are deterministic?


## Prerequisites

- AMD Instinct GPU host (MI300X / MI325X / MI350X / MI355X) with ROCm

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make the execution-location assumption explicit? Prerequisites and Phase 1 assume the agent already has a shell on the GPU host with local /dev/kfd+/dev/dri. The common case is a remote Instinct server the user SSHes into, which isn't addressed. Suggest one line in Prerequisites ("this skill assumes it runs on the GPU host; for a remote host, SSH in first") plus a pointer to Hyperloom's remote/multi-node support (docs/how-to/multi-node/, remote sandbox via SAFE_API_URL).


- **IR-1 — GPU unoccupied.** Before every `optimize` (fresh or `--resume`), every
visible GPU must have zero foreign serving PIDs (`sglang.launch_server` /
`vllm.entrypoints` / `Magpie`) and ≲ 500 MiB VRAM in use.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fallback .env hardcodes HYPERLOOM_RUN_MODE=docker with no prompt. On the /hyperloom-setup path the mode is chosen for the user (fine), but this fallback silently forces docker even on a baremetal host with ROCm already set up. Can the fallback ask docker vs baremetal (one line on the tradeoff: docker = isolated/reproducible but needs an image + /dev/kfd,/dev/drimapping; baremetal = simpler when ROCm is present but touches the host env), and do a quick feasibility check (docker: daemon reachable + devices mappable; baremetal: ROCm + serving framework importable) before writing.env`?

Rewrite the IR-1 VRAM gate as scripts/preflight.py and make it fail closed: an
unreadable probe now blocks the launch instead of being skipped, since an empty
reading was indistinguishable from idle GPUs. Normalize MB/MiB so the ceiling
comparison no longer mixes units, tolerate the amd-smi/rocm-smi output shapes
that vary across ROCm releases, and cover the shapes that used to pass silently
in scripts/tests/test_preflight.py.

Drop the inline .env fallback, which hardcoded docker mode and duplicated
hyperloom-setup's decisions. Replace it with the key contract, a diagnosis path
when the setup skill is missing, and a rule against sourcing .env, whose values
are unquoted and may contain spaces. Point at the optimize preflight catalog
probe rather than adding a second live key check, and require its warning-only
outcomes to be surfaced.

Document the docker delegation contract, stop and report when
hyperloom-custom-advanced is absent, state that every command runs on the GPU
host, and resolve the wheel by reporting the newest release and asking the user
instead of taking it silently.
…eader

The launch, health-check and resume blocks were order-dependent shell pasted into
the body for the agent to reassemble on every run: .env, then workload.env, then
the kernel-agent env, then a PATH derived from $PYTHON, and only then setsid
nohup. They now live in scripts/launch.sh, scripts/launch_health.sh and
scripts/resume.sh over a shared scripts/_env.sh, which also removes the preamble
that launch and resume duplicated line for line.

The run handles are recorded in optimizer_runs/last_launch.env. The health check,
monitor and resume steps run in fresh shells, so LAUNCH_INFO_FILE and SESSION_DIR
were previously only reachable when the agent happened to keep one shell alive.
The health check now fails loudly when the launch-info JSON never appeared or no
optimizer process can be found, instead of reporting an empty pid.

Drop the inline state.json parser in the monitor step and call the
read_optimizer_state.py that the wheel ships, which prints the same fields plus
the recent lifecycle events. Resolve it for both the wheel and source layouts,
matching how install.sh is resolved.

Correct the .env guidance in setup.md: values are sourced by the Phase 3 shell,
and hyperloom-setup double-quotes any value containing a space precisely so that
source cannot fail. The previous text claimed the opposite.
Exercises launch.sh, launch_health.sh and resume.sh against a stub optimizer, so
no GPU, wheel or network is needed. Covers the happy path (workload.env values
reaching the CLI, OPT_FLAGS word-splitting, run handles persisted to
last_launch.env, session_dir recorded) and four refusal paths: a launch-info JSON
that never appeared, a missing workload.env, a missing kernel-agent env from
IR-2, and resume without --model.

The stub reports a forked child as the optimizer pid, because setsid execs
directly when it need not fork -- with a single-process stub the wrapper pid and
the optimizer pid coincide and the check cannot tell whether launch_health.sh
rewrote the pid file at all. The fixture now asserts the two differ before
comparing, so removing the rewrite fails the test.

Each fixture is generated rather than copied: .env and workload.env hold absolute
paths, so a copied root would still point at the original directories and the
refusal paths would silently pass.
The confirmation gate showed an aligned plan block but never said where it goes,
so an agent using a structured question tool put the whole plan into the prompt
field. That field renders as one wrapped paragraph: the column alignment
collapses and the user has to hunt for MAX_HOURS inside a blob.

Require the plan in the reply body and keep the prompt to a single short
question. Also name the field to change instead of offering a free-text "change
something" option, which makes the user retype parameter names.
@lishuoshuo-amd
lishuoshuo-amd force-pushed the add-hyperloom-workload-optimizer-skill branch from 94c3d70 to 8de0f02 Compare August 5, 2026 08:46
@lishuoshuo-amd

Copy link
Copy Markdown
Author

@Mahdi-CV Thanks for the review — all seven are addressed across 8de0f02, d644585, 7218f06, 644052e.

  1. The "self-contained" claim

Removed the "inlines the operator workflow without bouncing across files" line. The skill is now described as what it is: it orchestrates, and hands environment prep to hyperloom-setup and workload intake to hyperloom-custom-advanced. Both ship inside the wheel and are version-locked to the runtime, so this repo keeps no copy of them. Missing delegates now fail explicitly instead of degrading — if hyperloom-custom-advanced isn't present, Phase 1 stops and reports it.

  1. Moving the inline blocks into scripts/

All four are out: scripts/preflight.py, launch.sh, launch_health.sh, resume.sh, with the shared env preamble in _env.sh. The monitor step no longer parses state.json itself; it calls tools/read_optimizer_state.py, which ships in the wheel, so it can't drift from the format the optimizer actually writes. Each step in SKILL.md is now a 3–5 line call, and the body went from 509 to 401 lines.

Added scripts/tests/test_launch_flow.sh: it runs the real scripts against a stub optimizer over 8 scenarios, covering the happy path plus four refusals — missing workload.env, missing install output, launch-info.json never appearing, and the optimizer process not being present. For the PID-rewrite scenario the stub forks, and the test asserts the setsid wrapper PID differs from the optimizer PID before comparing against what landed in PID_FILE.

  1. The IR-1 VRAM gate was fail-open

It's fail-closed now: the launch proceeds only if every check passed, and an unreadable VRAM probe blocks. The single escape hatch is IR1_ALLOW_UNVERIFIED_VRAM=1, which has to be set explicitly. Three concrete defects that caused silent passes are fixed as well: amd-smi / rocm-smi JSON shape differences across versions (list vs dict, different field spellings) made the parse come back empty; some fields report MB while the threshold compared MiB, so 96432 MB read as idle; and parse exceptions were swallowed.

scripts/tests/test_preflight.py covers 18 cases built around those shapes, and I verified the assertions by removing them one at a time. The foreign-process check now prints only the PID and the matched pattern name rather than the full cmdline, so a token on the command line doesn't reach the log.

  1. Credential shape and validation

On the choice of shape: not adding one. hyperloom-setup already prompts for CLAUDE_MODEL and defaults it to claude-opus-4-8 (SKILL.md:102), and what it writes is "the Anthropic keys plus the common keys" (:195-197). Credential collection is its job and this skill follows the shape it produces; offering a different shape here would conflict with it rather than merely duplicate it. The runtime-side allowlist and the preferred/fallback hint are in cli/init.py:718-725.

On validation: Hyperloom's optimize preflight already runs a live probe with the bearer header and the custom headers, and exits 2 on an auth failure, so there's no second probe here. The gap is that two of its outcomes only warn instead of blocking, so setup.md points at that probe and requires the agent to report those two warning-only results explicitly.

  1. Wheel resolution isn't reproducible

The alpha line is expected for now — v1.0.0a1/a2/a3 is the current release line, and this will be adjusted once we publish a formal 1.0.0. Filtering on GitHub's prerelease field wouldn't work in any case: all 11 releases have it set to false, alphas included, since it's set by hand.

What changed is that it no longer installs silently. It reports the resolved version to the user and waits for confirmation, and the user can name a specific version instead.

  1. Execution-location assumptions

Added to Prerequisites: this skill runs on the target GPU host. setup.md now carries a docker-mode contract listing what must hold before Phase 3 — container running, GPU devices mapped, workspace mounted at the same absolute path, MODEL_PATH resolvable inside, and setup already run inside the container.

  1. The inline .env template hardcoded docker mode

The template is gone. hyperloom-setup is the single source for LLM providers and variable names; if the setup skill is missing, setup.md gives a diagnostic path (restart the agent, confirm the wheel installed completely) rather than a local fallback template.

How to inspect .env is now spelled out: read it line by line, don't source it, don't echo the key. ANTHROPIC_CUSTOM_HEADERS and similar values contain spaces and a colon, and hyperloom-setup writes values double-quoted for that reason, so sourcing breaks them.

amd-smi 26.x on ROCm 7.x returns {"gpu_data": [...]} instead of a bare
list, so _iter_gpu_entries found no GPU entries and the fail-closed gate
blocked every launch with "no recognizable GPU list" even on an idle GPU
holding 270 MiB. The known container keys are tried before the
dict-of-dicts scan so a sibling metadata object is not read as a GPU.
@lishuoshuo-amd
lishuoshuo-amd force-pushed the add-hyperloom-workload-optimizer-skill branch from e01a7b3 to 6abcf72 Compare August 5, 2026 10:17
@danielholanda danielholanda changed the title Add hyperloom-workload-optimizer skill New Skill: hyperloom-workload-optimizer Aug 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants