Environment variables#
User-configurable environment variables for Hyperloom, grouped by purpose. Runtime parameters such as framework, tensor parallelism, prompt lengths, and phase toggles are configured with CLI flags; internal subprocess handoff envs are intentionally not listed as user configuration.
Variables marked Required must be set (using shell or $REPO_ROOT/.env)
or the CLI will exit fast at startup. Variables marked Optional have
sensible defaults; the default is shown in the Default column.
Precedence rule (applies everywhere): shell-exported env wins over .env.
See Hyperloom authentication and credentials.
Credentials#
These variables configure LLM gateway access and optional backend credentials.
Variable |
Required |
Default |
Description |
|---|---|---|---|
|
Conditional |
— |
AMD primus-safe large language model (LLM) gateway key. Format |
|
Conditional |
— |
LLM gateway URL. Required for the single-gateway setup; split-gateway deployments can provide provider-specific base URLs instead. Example: |
|
No |
Derived from |
Claude-side base URL for split-gateway deployments. |
|
No |
Inherits |
Claude CLI auth token alias; set explicitly only for split-gateway deployments. |
|
No |
Inherits |
Only set explicitly to override the default inheritance. |
|
No |
Inherits |
Only set explicitly to override the default inheritance. |
|
No |
Inherits |
GEAKv4 Claude Code workflow model id. |
|
No |
Inherits |
Only set explicitly to override. |
|
No |
Inherits |
Only set explicitly to override. |
|
No (required |
Unset |
Base URL of your Langfuse deployment (for example, |
|
No (required |
Unset |
Langfuse project public key ( |
|
No (required |
Unset |
Langfuse project secret key ( |
Path environment#
The following variables configure filesystem paths for Hyperloom’s runtime dependencies and session data.
Variable |
Required |
Default |
Description |
|---|---|---|---|
|
No (recommended) |
|
This Hyperloom checkout. Used to locate |
|
Conditional |
Auto-cloned by |
Path to the SemiAnalysisAI/InferenceX repo, used by baseline / target analysis. |
|
No (installer auto-clones) |
|
|
|
No (installer auto-resolves) |
First of |
Pins the Claude Code binary the GEAK SDK path uses, so |
|
No |
|
Session directory root (logs, runs, mirrors, breakdown). Replaces the retired |
|
No (set by CLI) |
Set at session boot |
Absolute path to the active session directory. Written by the CLI when a session starts and inherited by every benchmark subprocess; session-path resolution prefers it over scanning |
|
No |
|
Legacy source-mirror root kept for compatibility. Current open-source dependency checkouts default to the repo-local cache root ( |
|
No |
|
Writable, repo-local base for auto-cloned open-source deps (TraceLens, Magpie, etc.), cloned per revision as |
|
No |
Resolved from installed |
Magpie package root for benchmark wrappers and patch inspection. |
|
No |
Built-in model roots such as |
|
|
No (robustness-agent) |
Scan known paths |
Path containing |
|
No (robustness-agent) |
Scan known DNS |
M1 primary data source; empty disables the primary path and forces local-only probes. |
|
No |
Unset |
Legacy path variable. Still consumed in two narrow spots: the CLI |
|
No |
Unset |
Retired — replaced by |
Workload configuration#
Set with CLI flags, not env vars. Pre-set ISL / OSL / CONC / PRECISION /
TP / EP env vars are ignored and overwritten (GPU_TYPE is a fallback when
--gpu-type is omitted).
Model / workload shape:
--model,--model-class,--framework,--framework-version,--precision,--tp,--ep,--isl,--osl,--conc,--max-model-len,--profile-osl.Goal / budget:
--target-gain,--max-hours,--target-summary,--target-tput,--compare-against-gpu.Cluster topology & multi-node backend:
--nodes,--gpus-per-node,--cpus-per-node,--mem-per-node,--gpu-type,--mn-backend(rayjob/infera),--mn-image,--server-args(rayjob),--rayjob-extra-env(repeatable; the supported way to inject server-side env such asSGLANG_USE_AITER=0into RayJob pods — the sandbox’s ownSGLANG_*env is not forwarded).PD disaggregation (infera):
--pd-mode disaggregated,--pd-prefill-nodes/--pd-prefill-tp/--pd-prefill-ep/--pd-prefill-extra-args,--pd-decode-nodes/--pd-decode-tp/--pd-decode-ep/--pd-decode-extra-args,--pd-transfer-backend,--pd-ib-device.Phase toggles:
--enable-roofline/--no-enable-roofline,--enable-conc-sweep/--no-enable-conc-sweep,--conc-sweep-concs,--no-framework-agent,--no-framework-local-explore,--no-kernel,--no-explore.Agent models:
--claude-model,--codex-model.Session / resume:
--resume,--resume-from,--session-dir,--reset-state.Quantization:
--quantize,--quantize-scheme.
Run inference_optimizer optimize --help for the exhaustive flag list.
Kernel-opt backend selection#
The following variables control the kernel optimization backend ladder.
Variable |
Default |
Description |
|---|---|---|
|
Unset |
Comma-separated override for the kernel-opt backend. Bare-metal defaults to |
|
|
Max parallel kernel-opt attempts per request (per-kernel race fan-out). The runtime caps this by visible GPUs and per-attempt GPU reservation when it can detect them. |
|
Unset |
Cap on how many |
Single-node Ray execution#
Variable |
Default |
Description |
|---|---|---|
|
Unset ( |
Opt-in switch for routing single-node serving benchmarks and |
Codex (OpenAI) backend web search#
The following variables enable OpenAI’s built-in server-side web search for the
Codex (GPT-style) backend. When enabled, every Codex turn is issued through the
OpenAI Responses API with the built-in web_search tool instead of
chat.completions; the search resolves server-side in one call and the model’s
reply still carries the intent envelope. Only affects deployments whose Codex
endpoint is OpenAI-compatible and supports the Responses API web_search tool.
Variable |
Default |
Description |
|---|---|---|
|
Unset (off) |
Set to |
|
|
Passed through as the |
Multi-node / prefill-decode (PD)#
Use CLI flags for multi-node topology and prefill-decode configuration:
--nodes, --mn-backend, --mn-image, --gpus-per-node,
--cpus-per-node, --mem-per-node, --tp, --ep,
--pd-mode, --pd-prefill-nodes, --pd-decode-nodes, --pd-prefill-tp,
--pd-decode-tp, --pd-transfer-backend, and --pd-ib-device.
When the optimizer provisions the cluster itself (Primus-SaFE flow), those flags are all you need — no environment variables are required.
External-mode variables (SaFE-less cluster)#
When SaFE is unavailable (SAFE_API_URL / SAFE_API_KEY not both set) and
HYPERLOOM_MN_EXT_SERVICE_URL is set, the optimizer skips all
provisioning and benchmarks an already-running cluster described by these
variables. When both SAFE_API_* are present these are ignored.
Variable |
Backend |
Required |
Description |
|---|---|---|---|
|
both |
yes |
Benchmark frontend URL ( |
|
infera |
yes |
Private SSH key already authorized on the pods (SaFE injects one otherwise). |
|
infera |
PD |
Prefill / decode pod IPs (comma-separated) for PD-disaggregated runs. |
|
infera |
aggregated |
Worker pod IPs (comma-separated) for aggregated (non-PD) runs. At least one of |
|
infera |
No (default |
SSH base port; decode role is offset |
|
infera |
No |
|
|
rayjob |
No (recommended) |
Ray head IP (Dashboard |
|
rayjob |
No |
Ray Dashboard auth token, only if the dashboard is authenticated. |
Infera external mode requires HYPERLOOM_MN_EXT_SSH_KEY plus at least one
*_IPS list, or the run fails fast at startup. RayJob external mode ignores
the SSH / IP vars and uses HYPERLOOM_MN_EXT_HEAD_IP for restarts.
Multi-node SSH fanout creates session-scoped keys under the active session
directory. Treat mn_id_ed25519 and mn_id_ed25519.pub as sensitive session
artifacts: keep the session directory on an access-controlled filesystem and
do not publish it unchanged in support bundles.
Quantization prelude#
Variable |
Default |
Description |
|---|---|---|
|
Unset |
Primary switch ( |
|
Unset |
AMD Quark checkout used by the quantization-agent. Set this explicitly when quantization is enabled. |
Framework / source-tree discovery#
The following variables configure framework source discovery and path overrides.
Variable |
Default |
Description |
|---|---|---|
|
Union with |
Colon-separated list of source roots used by PolicyGate and flag discovery. Populated automatically by |
|
Unset |
Colon-separated list of extra directories the harvest step scans for stray |
|
Aiter default |
Override the aiter just-in-time (JIT) cache root for cold-cap sizing. |
|
|
When |
|
Unset |
Pin the sglang server-patch step to specific upstream versions; advanced compatibility option. |
|
|
Set to |
|
Unset |
Optional bare-metal AITER install pin. When unset, the installer selects the newest tag compatible with the installed torch/triton stack. |
|
|
Controls the FRAMEWORK phase semantic-audit LLM deep-read. |
Security compatibility switches#
These switches keep production-compatible behavior by default while still allowing operators to turn off credential/env persistence in hardened deployments.
Variable |
Default |
Description |
|---|---|---|
|
Unset ( |
Bash-enabled specialist subprocesses inherit the limited provider credential set by default: |
|
Unset ( |
Allows the specialist MCP config file to include auth headers such as |
|
Unset ( |
Slurm carrier only. Set to |
Critic / Robustness / knowledge base (KB)#
The following variables configure the Critic, Robustness, and knowledge base components.
Variable |
Default |
Description |
|---|---|---|
|
|
Filesystem root for the local recipe-snapshot KB store (always the write target). Overridden by |
|
Unset |
Base URL of the remote recipe-snapshot page store — the read side of the recipe KB. When unset, recipe reads are local-only. |
|
Unset |
Bearer token for |
|
|
|
|
Unset |
Optional Cortex KB URL used only by the Critic agent’s per-proposal assess enrichment ( |
|
Derived from |
Override location of the critic-agent runtime. |
|
Derived from |
Override location of the robustness-agent runtime. |
|
Unset |
Set to |
Session / observability hand-off#
These are read by src/hyperloom/inference_optimizer/session/manifest.py and the src/hyperloom/inference_optimizer/breakdown/collectors/
package to populate session_breakdown.json for downstream consumers.
Variable |
Description |
|---|---|
|
Hosted SaFE / Claw session id, written to |
|
Hosted SaFE / Claw user id, written to |
|
Primary switch (default off) for live Langfuse trace push. See details below. |
HYPERLOOM_LANGFUSE_ENABLE details:
Primary switch (default off) for live Langfuse trace push.
SDK install: when this flag is on,
src/hyperloom/inference_optimizer/assets/install.shauto-installs the optionallangfuseSDK on demand and skips it entirely when off — no separatepip install '...[trace]'is required.Live push: when set to
1/true/yes/onand the threeLANGFUSE_*credentials are present, every in-process LLM call is mirrored into Langfuse while the run is live. A session-end flush backfills out-of-process children (geak, forge, robustness, specialist) and KEEP/REVERT decision Scores.Local ledger:
reports/trace/*.jsonlis always written regardless of this flag. If the SDK is unavailable, live push degrades to a no-op.Correlation: the Langfuse trace ID and
session_idgrouping are derived fromclaw_session_id(envCLAW_SESSION_ID), falling back to the internal session ID for standalone runs. Live push and the offlinebackfill_langfuseCLI collapse onto one trace per Primus-Claw session.Span layout:
trace → phase span (PRELUDE/FRAMEWORK_AGENT/EXPLORE/KERNEL_AGENT/SWEEP/…) → agent span (component: orchestration/kernel/specialist/critic/geak/forge/…) → Generation. Each KEEP/REVERT/gain_pctScore attaches to the agent span that produced the decision, with a trace-level fallback when no matching span exists.Receipt: every session records a
langfusesection insession_breakdown.json(andreports/trace/langfuse_receipt.json) noting:Whether push was enabled (or the
disabled_reason)The redacted connection config (host and key-presence booleans — never the keys themselves)
The derived
trace_idandsession_idHow many generations, scores, and spans were sent
This lets an operator confirm post-hoc whether a run reached Langfuse.
Langfuse and artifact-package — security and known limitations#
Sensitive data surface: When live push is on,
conversations.jsonl(and Langfuse Generations) carry full prompt/response text.redact_secretsscrubs common token shapes (Bearer,sk-/pk-, GitHub tokens, someKEY=value) but is not a complete data loss prevention (DLP) filter — bare keys without a recognizable prefix (for example, raw AWSAKIA…) can slip through. The artifact packager also copiesreports/trace/*.jsonland, with the loose mode on by default (HYPERLOOM_SESSION_PACKAGE_LOOSE), drops them under/workspacefor the Claw sync. If a session might contain customer code or secrets, define an explicit retention + access-control policy for both the Langfuse project and the/workspacepackage destination, and consider disabling live push or loose packaging for those runs.live push+backfill_langfuseoverlap: Both derive the sametrace_idfromclaw_session_id, so running the offline backfill after a live run re-emits the out-of-process children onto the same trace and can duplicate observations. Use one path per session, or treat backfill as a recovery tool only when live push did not run.flush_sessionis idempotent: A second flush only re-writes the receipt (no re-emit), so a duplicated CLOSE step won’t double-push.Package truncation: The bundle caps at 5000 files / 256 MB. On a very long session the cap can stop the bundle short; the
PACKAGE_MANIFESTthen setstruncated: trueand listsdropped_files, so consumers must not treat a truncated package as complete.Generation duration is ~0: Both live and backfill stamp a single timestamp (
end == start), so Langfuse shows no meaningful per-Generation duration — counts/usage are accurate, latency is not captured.
token_usage section (in session_breakdown.json)#
Every breakdown carries a top-level token_usage section: a promoted,
discoverable rollup of LLM token spend derived from the per-call ledger
(reports/trace/llm_calls.jsonl + ext/*.jsonl). It is purely derived from
decision_trace.token_rollup, so it always reconciles with that section. No
env var controls it; it is always present (zeroed on pre-trace sessions).
session_total: whole-session total across every call, with two convenience figures:total_in_out(prompt + completion only) andgrand_total(in + out + all cache-creation + cache-read tokens).by_component: per-agent breakdown (orchestration / kernel / critic / specialist / proposal_scorer / geak / forge / …), each with the same convenience totals.by_phase: per-phase breakdown (PRELUDE / FRAMEWORK_AGENT / EXPLORE / KERNEL_AGENT / SWEEP / CLOSE).attribution:attributed_to_decisionsvsunattributedsplit plusattributed_calls_pct. Only calls that carry atask_id/dyn_idjoining to a KEEP/REVERT or dynamic_action decision (for example, specialist subprocess turns) are attributed; orchestration / kernel / critic / proposal_scorer turns are LLM-internal and land inunattributed(this is expected, not a gap in the data).timeline: eachaction_timelinerow annotated with the tokens that join to it ontask_id. Rows whose action has no LLM spend showtokens: null(rather than a zero bucket) to make the sparsity explicit.
To get the single “total tokens for this run” number, read
token_usage.session_total.grand_total (all-in) or .total_in_out
(prompt+completion only).
Variables intentionally not exposed#
These are read by os.environ somewhere in the codebase but are
internal-only — do not set them by hand:
HYPERLOOM_KERNEL_AGENT_ROOT: internal CLI-only handoff to the kernel subprocess (Python constant_KERNEL_AGENT_ROOT_ENV).Any
_INFERENCE_OPTIMIZER_*_INTERNAL_*symbol: internal toggles for the test suite.
If you find one of these in a log message, treat it as diagnostic detail rather than something you should tune.
More info#
Use these resources for related configuration and reference information:
Hyperloom authentication and credentials: Credential precedence and direct upstream gateway wiring.
Troubleshooting Hyperloom: Symptom → variable reverse-lookup for common failures.