Examples
Every example config in hylo-bench and hylo-plugins, with the comment at its top. Paths are relative to the development workspace; commands run from any directory (simulator runtimes come from the machine profile, artifacts from the store).
Experiments
| Example |
What it shows |
libero10_critic |
SmolVLA on LIBERO-10: sample 4 chunks per decision, execute the one a learned chunk critic values most (hylo.agents.critic). Train the critic first: uv run python -m hylo.learn.critic --runs runs/... --task-prefix libero/libero_10/ \ --image-camera agentview --out runs/critics/ and reference it by id (hylo store ref runs/critics/<name>). l10-v1 predates manifests and was adopted without a record of its training runs: it runs here, but the RSI gate refuses it in a candidate (unknown provenance). |
libero10_memory |
SmolVLA on LIBERO-10 steered by an action memory of its own verified successes (RFC-0003 M1): flow sampling starts from a retrieved prior at t0 in [t0_min, t0_max] instead of pure noise. Build the memory first (development splits only): envs/libero/.venv/bin/python -m hylo.policies.lerobot.memory_build --runs runs/ \ --splits search --out runs/memory/ then reference it by id: hylo store ref runs/memory/<name> |
libero10_noise |
SmolVLA on LIBERO-10 with noise-space steering (RFC-0004 W3): the initial flow noise is biased towards the noise that produced similar successful chunks; the policy is unchanged. Build the bank first (search split only): envs/libero/.venv/bin/python -m hylo.policies.lerobot.memory_build --store noise --splits search \ --runs runs/ --out runs/memory/ then reference it by id: hylo store ref runs/memory/<name> |
libero10_planner |
LIBERO-10 with an LLM/VLM subgoal planner (qwen3.5) in front of the steered SmolVLA. CPU only. |
libero10_steered |
SmolVLA on LIBERO-10 behind SteeredAgent (seeded noise, sample-and-select, runtime rules). CPU only. Simulator and policy each run out of process in this machine's libero-sim / lerobot runtimes (hylo profile show; bench's envs/libero/setup.sh builds the venv and registers both). |
libero_smolvla |
SmolVLA (lerobot/smolvla_libero, 450M) on LIBERO, CPU only. Simulator and policy each run out of process in this machine's libero-sim / lerobot runtimes (hylo profile show; bench's envs/libero/setup.sh builds the venv and registers both). |
mujoco_policy_flow_steered |
A flow-matching policy (trained by examples/policies: compare.py, or hylo learn examples/policies/jobs/flow.json) steered: 4 seeded samples per decision, the medoid executed. Any registered policy can be the sampler: policy.bc, policy.tokens, lerobot, your own. The sampler is referenced by store id; without a digest, the one artifact of that name (retraining replaces it), pinned in the run's manifest. |
mujoco_reach |
- |
mujoco_reach_remote |
The MuJoCo reach experiment with the simulator in a separate process (EnvServer protocol). Set runtime: to a runtime from this machine's profile to run an environment whose dependencies conflict with yours (LIBERO does this). |
mujoco_table_memory |
Language-conditioned reaching with spatial memory on the MuJoCo table: the pads are visible only for the first 5 control steps, so the agent must remember where the named pad was (see external_demo/ for the full study). |
libero10_critic
uv run hylo run bench/examples/configs/libero10_critic.yaml
bench/examples/configs/libero10_critic.yaml
# SmolVLA on LIBERO-10: sample 4 chunks per decision, execute the one a learned chunk critic values most
# (hylo.agents.critic). Train the critic first:
# uv run python -m hylo.learn.critic --runs runs/... --task-prefix libero/libero_10/ \
# --image-camera agentview --out runs/critics/<name>
# and reference it by id (`hylo store ref runs/critics/<name>`). l10-v1 predates manifests and was adopted without
# a record of its training runs: it runs here, but the RSI gate refuses it in a candidate (unknown provenance).
schema_version: hylo.experiment/v0.1
name: libero10-critic
benchmark: {type: libero, split: search_val, params: {suite: libero_10, protocol: rsi, replicates: 1, gate_looks: 3}}
env:
type: libero
remote: {runtime: libero-sim}
agent:
type: remote
params:
ref: lerobot.critic_steered
runtime: lerobot
params:
repo_id: lerobot/smolvla_libero
num_threads: 3
steering: {n_samples: 4, selector: gripper_vote_medoid, execution_steps: 25, seed_noise: true}
critic: {path: "artifact:l10-v1@7934d463d67ad242", beta: 0.5, within_vote: true}
trace: {record_privileged: true, image_every: 5}
workers: 12
output_dir: runs
libero10_memory
uv run hylo run bench/examples/configs/libero10_memory.yaml
bench/examples/configs/libero10_memory.yaml
# SmolVLA on LIBERO-10 steered by an action memory of its own verified successes (RFC-0003 M1):
# flow sampling starts from a retrieved prior at t0 in [t0_min, t0_max] instead of pure noise.
# Build the memory first (development splits only):
# envs/libero/.venv/bin/python -m hylo.policies.lerobot.memory_build --runs runs/<search runs> \
# --splits search --out runs/memory/<name>
# then reference it by id: `hylo store ref runs/memory/<name>`
schema_version: hylo.experiment/v0.1
name: libero10-memory
benchmark: {type: libero, split: search_val, params: {suite: libero_10, protocol: rsi, replicates: 1, gate_looks: 3}}
env:
type: libero
remote: {runtime: libero-sim}
agent:
type: remote
params:
ref: lerobot.memory_steered
runtime: lerobot
params:
repo_id: lerobot/smolvla_libero
num_threads: 4
steering: {n_samples: 1, seed_noise: true}
memory: {type: action_bank, params: {path: "artifact:l10-search-v1@40a84dd1afab4a5c"}}
memory_steer: {k: 10, same_task: true, sim_floor: 0.95, t0_min: 0.1, t0_max: 0.7}
env: {TORCHDYNAMO_DISABLE: "1"}
trace: {record_privileged: true, image_every: 10}
workers: 24
output_dir: runs
libero10_noise
uv run hylo run bench/examples/configs/libero10_noise.yaml
bench/examples/configs/libero10_noise.yaml
# SmolVLA on LIBERO-10 with noise-space steering (RFC-0004 W3): the initial flow noise is biased towards the
# noise that produced similar successful chunks; the policy is unchanged. Build the bank first (search split only):
# envs/libero/.venv/bin/python -m hylo.policies.lerobot.memory_build --store noise --splits search \
# --runs runs/<search runs> --out runs/memory/<name>
# then reference it by id: `hylo store ref runs/memory/<name>`
schema_version: hylo.experiment/v0.1
name: libero10-noise
benchmark: {type: libero, split: search_val, params: {suite: libero_10, protocol: rsi, replicates: 1, gate_looks: 3}}
env:
type: libero
remote: {runtime: libero-sim}
agent:
type: remote
params:
ref: lerobot.noise_steered
runtime: lerobot
params:
repo_id: lerobot/smolvla_libero
num_threads: 4
steering: {n_samples: 1, seed_noise: true}
memory: {type: action_bank, params: {path: "artifact:l10-noise-search-v1@2687768fc5102b06", frozen: true}}
noise_steer: {weight: 0.5, k: 5, same_task: true, sim_floor: 0.95}
env: {TORCHDYNAMO_DISABLE: "1"}
trace: {record_privileged: true, image_every: 10}
workers: 24
output_dir: runs
libero10_planner
uv run hylo run bench/examples/configs/libero10_planner.yaml
bench/examples/configs/libero10_planner.yaml
# LIBERO-10 with an LLM/VLM subgoal planner (qwen3.5) in front of the steered SmolVLA. CPU only.
schema_version: hylo.experiment/v0.1
name: libero10-planner
benchmark:
type: libero
split: validation
params:
suite: libero_10
n_validation: 10
n_heldout: 0
env:
type: libero
remote: {runtime: libero-sim}
agent:
type: planner.subgoal
params:
inner:
type: remote
params:
ref: lerobot.steered
runtime: lerobot
params:
repo_id: lerobot/smolvla_libero
num_threads: 4
steering:
n_samples: 1
seed_noise: true
planner:
type: planner.llm
params:
model: qwen3.5:35b-a3b
cache_dir: runs/llm-cache
subgoal_max_steps: 260
check_every: 1
trace:
record_privileged: true
image_every: 10
workers: 24
output_dir: runs
libero10_steered
uv run hylo run bench/examples/configs/libero10_steered.yaml
bench/examples/configs/libero10_steered.yaml
# SmolVLA on LIBERO-10 behind SteeredAgent (seeded noise, sample-and-select, runtime rules). CPU only.
# Simulator and policy each run out of process in this machine's libero-sim / lerobot runtimes (hylo profile show;
# bench's envs/libero/setup.sh builds the venv and registers both).
schema_version: hylo.experiment/v0.1
name: libero10-steered
benchmark: {type: libero, split: validation, params: {suite: libero_10, n_validation: 10, n_heldout: 0}}
env:
type: libero
remote: {runtime: libero-sim}
agent:
type: remote
params:
ref: lerobot.steered
runtime: lerobot
params: {repo_id: lerobot/smolvla_libero, num_threads: 4, steering: {n_samples: 1, seed_noise: true}}
trace: {record_privileged: true, image_every: 10} # keep every 10th camera frame (a frame pair is ~400 KB)
workers: 24 # thread budget: 24 x (4 policy + 2 render) ~ 144 threads on 128 cores
output_dir: runs
libero_smolvla
uv run hylo run bench/examples/configs/libero_smolvla.yaml
bench/examples/configs/libero_smolvla.yaml
# SmolVLA (lerobot/smolvla_libero, 450M) on LIBERO, CPU only.
# Simulator and policy each run out of process in this machine's libero-sim / lerobot runtimes (hylo profile show;
# bench's envs/libero/setup.sh builds the venv and registers both).
schema_version: hylo.experiment/v0.1
name: libero-smolvla
benchmark: {type: libero, split: validation, params: {suite: libero_spatial, n_validation: 5, n_heldout: 0}}
env:
type: libero
remote: {runtime: libero-sim, env: {OMP_NUM_THREADS: "2", LP_NUM_THREADS: "4"}}
agent:
type: remote
params:
ref: hylo.policies.lerobot.agent:LeRobotAgent
runtime: lerobot
params: {repo_id: lerobot/smolvla_libero, num_threads: 6}
trace: {record_privileged: true, image_every: 10} # keep every 10th camera frame (a frame pair is ~400 KB)
workers: 10
output_dir: runs
mujoco_policy_flow_steered
uv run hylo run bench/examples/configs/mujoco_policy_flow_steered.yaml
bench/examples/configs/mujoco_policy_flow_steered.yaml
# A flow-matching policy (trained by examples/policies: compare.py, or hylo learn examples/policies/jobs/flow.json)
# steered: 4 seeded samples per decision, the medoid executed. Any registered policy can be the sampler:
# policy.bc, policy.tokens, lerobot, your own. The sampler is referenced by store id; without a digest, the one
# artifact of that name (retraining replaces it), pinned in the run's manifest.
schema_version: hylo.experiment/v0.1
name: mujoco-policy-flow-steered
benchmark: {type: mujoco/reach-v0, split: heldout, params: {protocol: rsi}}
env: {type: mujoco.planar_reach}
agent:
type: steered
params:
sampler: {type: policy.flow, params: {path: "artifact:policy.flow"}}
steering: {n_samples: 4, selector: medoid}
workers: 8
output_dir: runs
mujoco_reach
uv run hylo run bench/examples/configs/mujoco_reach.yaml
bench/examples/configs/mujoco_reach.yaml
schema_version: hylo.experiment/v0.1
name: mujoco-reach
benchmark: {type: mujoco/reach-v0, split: validation}
env: {type: mujoco.planar_reach}
agent: {type: baseline.planar_ik, params: {kp: 0.3}}
output_dir: runs
mujoco_reach_remote
uv run hylo run bench/examples/configs/mujoco_reach_remote.yaml
bench/examples/configs/mujoco_reach_remote.yaml
# The MuJoCo reach experiment with the simulator in a separate process (EnvServer protocol). Set `runtime:` to a
# runtime from this machine's profile to run an environment whose dependencies conflict with yours (LIBERO does this).
schema_version: hylo.experiment/v0.1
name: mujoco-reach-remote
benchmark: {type: mujoco/reach-v0, split: validation}
env: {type: mujoco.planar_reach, remote: {}}
agent: {type: baseline.planar_ik, params: {kp: 0.3}}
output_dir: runs
mujoco_table_memory
uv run hylo run bench/examples/configs/mujoco_table_memory.yaml
bench/examples/configs/mujoco_table_memory.yaml
# Language-conditioned reaching with spatial memory on the MuJoCo table: the pads are visible only for the first
# 5 control steps, so the agent must remember where the named pad was (see external_demo/ for the full study).
schema_version: hylo.experiment/v0.1
name: mujoco-table-memory
benchmark: {type: mujoco/table-v0, split: validation}
env: {type: mujoco.table_reach}
agent:
type: composable.object_reach
params: {kp: 0.3, chooser: {type: chooser.rule_color}, memory: {type: sqlite, params: {path: ":memory:"}}}
safety: {max_delta: 0.5}
output_dir: runs
Improvement campaigns
| Example |
What it shows |
libero10_llm |
Frozen SmolVLA on LIBERO-10, steering candidates proposed by a local LLM (qwen3.5) from failure traces. CPU only. uv run hylo evolve run examples/evolve/libero10_llm.yaml uv run hylo evolve status runs/evolve/libero10-llm |
libero10_selftrain |
Expert iteration on LIBERO-10 (RFC-0002 L4): each cycle fine-tunes SmolVLA's action expert on its own successful search-split episodes (CPU), then gates the new weights on unseen init states. uv run hylo evolve run examples/evolve/libero10_selftrain.yaml |
libero10_steering |
Frozen SmolVLA on LIBERO-10: evolve steering (L0/L1) with the RFC-0002 protocol, CPU only. uv run hylo evolve run examples/evolve/libero10_steering.yaml uv run hylo evolve status runs/evolve/libero10-steering |
mujoco_reach_gain |
A campaign on MuJoCo planar reach (about a minute): the IK controller starts with a weak gain, a rule generator proposes larger and smaller gains, and the RFC-0002 gate (search_val selection, group-sequential gate, held-out report) decides. uv run hylo evolve run examples/evolve/mujoco_reach_gain.yaml |
libero10_llm
uv run hylo evolve run bench/examples/evolve/libero10_llm.yaml
bench/examples/evolve/libero10_llm.yaml
# Frozen SmolVLA on LIBERO-10, steering candidates proposed by a local LLM (qwen3.5) from failure traces. CPU only.
# uv run hylo evolve run examples/evolve/libero10_llm.yaml
# uv run hylo evolve status runs/evolve/libero10-llm
schema_version: hylo.evolve/v0.1
name: libero10-llm
experiment: ../configs/libero10_steered.yaml
experiment_overrides:
benchmark.params: {suite: libero_10, protocol: rsi, replicates: 1, gate_looks: 3}
workers: 24
proposer: {type: llm.steering, params: {model: "qwen3.5:35b-a3b", n_candidates: 4, cache_dir: runs/llm-cache}}
diagnosis: {stall_steps: 30, regrasp: 3}
protocol: {alpha: 0.05, gate_looks: 3, spending_rho: 3.0, stage1_pairs: 30, stage1_max_deficit: 4, gate_top_k: 1}
cycles: 3
stop_after_no_progress: 2
budget_s: 28800
approval: auto # use manual for anything that runs on hardware
out_dir: runs/evolve/libero10-llm
libero10_selftrain
uv run hylo evolve run bench/examples/evolve/libero10_selftrain.yaml
bench/examples/evolve/libero10_selftrain.yaml
# Expert iteration on LIBERO-10 (RFC-0002 L4): each cycle fine-tunes SmolVLA's action expert on its own
# successful search-split episodes (CPU), then gates the new weights on unseen init states.
# uv run hylo evolve run examples/evolve/libero10_selftrain.yaml
schema_version: hylo.evolve/v0.1
name: libero10-selftrain
experiment: ../configs/libero10_steered.yaml
experiment_overrides:
benchmark.params: {suite: libero_10, protocol: rsi, replicates: 1, gate_looks: 3}
agent.params.params.steering: {n_samples: 1, seed_noise: true, execution_steps: 25}
workers: 24
proposer: {type: selftrain.expert_iteration, params: {out_root: runs/selftrain/libero10, steps: 300, batch_size: 8, lr: 1.0e-5}}
diagnosis: {stall_steps: 30, regrasp: 3}
protocol: {alpha: 0.05, gate_looks: 3, spending_rho: 3.0, stage1_pairs: 30, stage1_max_deficit: 4, gate_top_k: 1}
cycles: 2
stop_after_no_progress: 1
budget_s: 43200
approval: manual # new weights: a person signs off before promotion
out_dir: runs/evolve/libero10-selftrain
libero10_steering
uv run hylo evolve run bench/examples/evolve/libero10_steering.yaml
bench/examples/evolve/libero10_steering.yaml
# Frozen SmolVLA on LIBERO-10: evolve steering (L0/L1) with the RFC-0002 protocol, CPU only.
# uv run hylo evolve run examples/evolve/libero10_steering.yaml
# uv run hylo evolve status runs/evolve/libero10-steering
schema_version: hylo.evolve/v0.1
name: libero10-steering
experiment: ../configs/libero10_steered.yaml
experiment_overrides:
benchmark.params: {suite: libero_10, protocol: rsi, replicates: 1, gate_looks: 3}
workers: 24
proposer: {type: rule.steering, params: {}}
diagnosis: {stall_steps: 30, regrasp: 3}
protocol: {alpha: 0.05, gate_looks: 3, spending_rho: 3.0, stage1_pairs: 30, stage1_max_deficit: 4, gate_top_k: 1}
cycles: 3
stop_after_no_progress: 2
budget_s: 28800
approval: auto # use manual for anything that runs on hardware
out_dir: runs/evolve/libero10-steering
mujoco_reach_gain
uv run hylo evolve run bench/examples/evolve/mujoco_reach_gain.yaml
bench/examples/evolve/mujoco_reach_gain.yaml
# A campaign on MuJoCo planar reach (about a minute): the IK controller starts with a weak gain, a rule generator
# proposes larger and smaller gains, and the RFC-0002 gate (search_val selection, group-sequential gate,
# held-out report) decides. uv run hylo evolve run examples/evolve/mujoco_reach_gain.yaml
schema_version: hylo.evolve/v0.1
name: mujoco-reach-gain
experiment: ../configs/mujoco_reach.yaml
experiment_overrides: {agent.params.kp: 0.02, workers: 16, benchmark.params: {protocol: rsi, gate_looks: 2}}
proposer: {type: rule.gain, params: {path: agent.params.kp, factors: [2.0, 4.0]}}
protocol: {alpha: 0.05, gate_looks: 2, stage1_pairs: 20}
cycles: 3
stop_after_no_progress: 1
approval: auto
out_dir: runs/evolve/mujoco-reach-gain
Plugin examples: experiments
| Example |
What it shows |
mujoco_guarded |
Guard plugins from the safety config (they run between the shield's mandatory finite and bounds checks). examples.slow_zone comes from packages/hylo-plugin-examples: a third-party package, no Hylo change. Here the fingertip slows to a quarter of its speed within 10 cm of the fixed target. |
mujoco_mixture |
A mixture of two policies, steered: each of 4 seeded samples comes from one member (examples.mixture), and the medoid proposal is executed. Members can be any registered policies (reference policies, LeRobot, your own). |
mujoco_reach |
MuJoCo planar reach with the analytic IK controller: the experiment the plugin examples build on. |
mujoco_guarded
uv run hylo run plugins/examples/configs/mujoco_guarded.yaml
plugins/examples/configs/mujoco_guarded.yaml
# Guard plugins from the safety config (they run between the shield's mandatory finite and bounds checks).
# examples.slow_zone comes from packages/hylo-plugin-examples: a third-party package, no Hylo change.
# Here the fingertip slows to a quarter of its speed within 10 cm of the fixed target.
schema_version: hylo.experiment/v0.1
name: mujoco-guarded
benchmark: {type: mujoco/reach-v0, split: validation}
env: {type: mujoco.planar_reach}
agent: {type: baseline.planar_ik, params: {kp: 0.3}}
safety:
max_delta: 0.5
guards:
- {type: norm_limit, params: {max_norm: 1.2}}
- {type: examples.slow_zone, params: {state_key: tip_pos, center: [0.35, 0.2], radius: 0.1, factor: 0.25}}
workers: 8
output_dir: runs
mujoco_mixture
uv run hylo run plugins/examples/configs/mujoco_mixture.yaml
plugins/examples/configs/mujoco_mixture.yaml
# A mixture of two policies, steered: each of 4 seeded samples comes from one member (examples.mixture), and the
# medoid proposal is executed. Members can be any registered policies (reference policies, LeRobot, your own).
schema_version: hylo.experiment/v0.1
name: mujoco-mixture
benchmark: {type: mujoco/reach-v0, split: validation}
env: {type: mujoco.planar_reach}
agent:
type: steered
params:
sampler:
type: examples.mixture
params:
members:
- {type: examples.ik_reacher, params: {gain: 0.3, noise: 0.05}}
- {type: examples.ik_reacher, params: {gain: 0.1, noise: 0.3}}
weights: [0.5, 0.5]
steering: {n_samples: 4, selector: medoid}
workers: 8
output_dir: runs
mujoco_reach
uv run hylo run plugins/examples/configs/mujoco_reach.yaml
plugins/examples/configs/mujoco_reach.yaml
# MuJoCo planar reach with the analytic IK controller: the experiment the plugin examples build on.
schema_version: hylo.experiment/v0.1
name: mujoco-reach
benchmark: {type: mujoco/reach-v0, split: validation}
env: {type: mujoco.planar_reach}
agent: {type: baseline.planar_ik, params: {kp: 0.3}}
workers: 8
output_dir: runs
Plugin examples: campaigns
| Example |
What it shows |
mujoco_online_cem |
Online learning as a candidate generator: the CEM learner (packages/hylo-plugin-examples) searches the controller gain by rolling out on the search split, seals its result with every rollout run in the provenance, and the proposer turns the best gain into a candidate that the gate judges on unseen init states. |
mujoco_steps_gate |
The gate's statistic is a plugin. Both gains always reach the target, so a success-based gate (McNemar) has no discordant pairs; a sign test on steps (lower is better) promotes the faster one. Vetoes stay on success and safety. Try {type: examples.min_effect, params: {min_effect: 0.1}} from packages/hylo-plugin-examples as well. |
mujoco_online_cem
uv run hylo evolve run plugins/examples/evolve/mujoco_online_cem.yaml
plugins/examples/evolve/mujoco_online_cem.yaml
# Online learning as a candidate generator: the CEM learner (packages/hylo-plugin-examples) searches the controller
# gain by rolling out on the search split, seals its result with every rollout run in the provenance, and the
# proposer turns the best gain into a candidate that the gate judges on unseen init states.
schema_version: hylo.evolve/v0.1
name: mujoco-online-cem
experiment: ../configs/mujoco_reach.yaml
experiment_overrides: {benchmark.params: {protocol: rsi}, agent.params.kp: 0.02}
proposer:
type: learn
params:
learner: examples.cem
online: true
out_root: runs/evolve/mujoco-online-cem/learned
params: {space: {kp: {path: params.kp, low: 0.01, high: 1.0, init: 0.05}}, population: 5, iterations: 3}
patch: {agent.params.kp: "{metrics.best.kp}"}
hypothesis: "a gain of {metrics.best.kp} found by CEM on the search split reaches more targets in time"
cycles: 1
out_dir: runs/evolve/mujoco-online-cem
mujoco_steps_gate
uv run hylo evolve run plugins/examples/evolve/mujoco_steps_gate.yaml
plugins/examples/evolve/mujoco_steps_gate.yaml
# The gate's statistic is a plugin. Both gains always reach the target, so a success-based gate (McNemar) has no
# discordant pairs; a sign test on steps (lower is better) promotes the faster one. Vetoes stay on success and
# safety. Try {type: examples.min_effect, params: {min_effect: 0.1}} from packages/hylo-plugin-examples as well.
schema_version: hylo.evolve/v0.1
name: mujoco-steps-gate
experiment: ../configs/mujoco_reach.yaml
experiment_overrides: {benchmark.params: {protocol: rsi}, agent.params.kp: 0.1}
proposer: {type: rule.gain, params: {path: agent.params.kp, factors: [2.0]}}
protocol: {gate_test: {type: sign, params: {metric: steps, direction: lower}}}
cycles: 1
out_dir: runs/evolve/mujoco-steps-gate
Scripts
| Script |
What it does |
bench/examples/policies/compare.py |
Every reference policy family on MuJoCo planar reach: demonstrations -> learners -> scorecards -> leaderboard. |
bench/examples/rsi_demo.py |
End-to-end offline improvement loop on MuJoCo planar reach. |