Contracts¶
Every plugin group's contract lives in hylo-core, so a plugin depends on hylo-core alone. What a plugin must provide, and the data that passes between the kernel, environments and agents. The plugin system explains how plugins are registered; the interfaces explain the design behind each contract; the plugin catalogue lists what implements them.
Environments¶
env ¶
Environment contract. An Environment = Simulator + Task logic behind reset/step.
Optional capabilities are declared in EnvSpec.capabilities and exposed through separate protocols, never by duck-typing, so the kernel can refuse a run that needs a missing capability.
Agents¶
agent ¶
Agent contract. The kernel only knows Agent; reasoners, planners, policies, world models and
memory are an Agent's internal composition (hylo-agents).
EpisodeStatus
module-attribute
¶
EpisodeStatus = Literal['success', 'failure', 'error', 'safety_abort', 'infra_invalid', 'unlabeled']
AgentSpec ¶
EpisodeContext
dataclass
¶
EpisodeContext(episode_id: str, task: TaskInstance, env_spec: EnvSpec, emit: Callable[[str, Mapping[str, Any]], None], seed: int = 0)
Runtime handle given to the Agent at reset. Not serialized.
Agent ¶
Policies¶
policy ¶
Policies (plugin group "policies"): action-chunk generators that agents run, steer and compose.
An Agent is what the kernel talks to (core.agent). A ChunkPolicy is the model inside: given an observation it
draws action chunks, one per noise seed. Separating the two lets one policy be run, steered (seeded noise,
sample-and-select, recovery rules), temporally ensembled (ACT), shadowed or memory-steered by agents in hylo-agents
without the policy knowing, and lets one agent wrap any policy by configuration:
agent: {type: policy, params: {policy: {type: policy.flow, params: {path: artifacts/flow}}}}
agent: {type: steered, params: {sampler: {type: lerobot, params: {repo_id: lerobot/smolvla_libero}},
steering: {n_samples: 4, selector: medoid}}}
Deterministic policies (regression, retrieval, scripted) ignore the seeds and return identical samples. Stochastic ones (diffusion, flow matching, sampled tokens) must derive their randomness from the seeds only, so a candidate and its parent face the same noise on the same init state and an episode can be replayed.
Reasoners, choosers, planners, reflectors¶
reasoning ¶
Reasoning plugin contracts, one per role (each its own plugin group and version):
reasoners(hylo.reasoner): the slow, event-triggered part of an agent; turns observations and memory into a Decision (a subgoal, a skill, an abort), with begin / deliberate / end around an episode.choosers(hylo.chooser): which object an instruction refers to, among perceived or remembered objects.planners(hylo.planner): decomposes an instruction into short sequential subgoals and judges when one is done.reflectors(hylo.reflector): distils lessons from a campaign's diagnosis into operations on a lesson book.
Rule-based, LLM and VLM implementations satisfy the same protocols; the kernel never sees the difference. The agents that use them (composable object reach, SubgoalAgent, the experience generator) live in hylo-agents and hylo-evolve; the LLM ones in hylo-reasoner-llm and hylo-proposer-llm.
ReasonerContext
dataclass
¶
Reasoner ¶
Bases: Protocol
SceneObject ¶
Choice ¶
Chooser ¶
Subgoal ¶
Plan ¶
Planner ¶
Reflector ¶
Bases: Protocol
Reads only what a generator may read (search-split diagnostics and timelines) and returns operations (ADD / UPVOTE / DOWNVOTE / EDIT / RETIRE) that the lesson book applies deterministically.
Shared data types¶
types ¶
Core data contracts shared by every layer (design/interfaces/environment.md, agent.md).
- Observations and actions are typed, not free-form dicts (vla-eval's Dict[str, Any] ends up with inconsistent keys across benchmarks).
- Action semantics live on the action space (inspect-robots ActionSemantics); compatibility is checked at bind time and a mismatch is an error.
successis reported separately fromterminated/truncated.
ControlMode
module-attribute
¶
ControlMode = Literal['joint_pos', 'joint_delta', 'joint_vel', 'eef_delta_pos', 'eef_delta_pose', 'eef_abs_pose', 'planar_vel']
WorkspaceLimit ¶
Bases: Contract
Box the controlled point must stay in. action_dims[i] is the action dimension that moves along axis i
of state_key (delta-position control); a move that pushes further outside the box is zeroed.
Action ¶
ActionChunk ¶
Tasks¶
task ¶
Task contracts. A TaskSpec covers both LIBERO-style declarative tasks with fixed init states and RoboCasa-style code tasks with seeded/snapshot init and dynamic instructions.
InitSpec
module-attribute
¶
InitStateRef ¶
SnapshotInit ¶
Predicate ¶
Bases: Contract
Success predicate: builtin name, declarative expr (e.g. BDDL goal) or callable ref.
TaskSpec ¶
Instruments¶
instrument ¶
Instruments (RFC-0004): learned components that measure or label instead of act.
A success judge or progress model labels episodes (so memory and training data can be written without simulator
ground truth); a world model pre-screens candidates. Instruments are trusted through calibration, not the gate:
hylo.learn.calibrate scores a judge against simulator outcomes on runs the judge was not built from and
stores the CalibrationReport in the judge's artifact manifest. An instrument never decides a gate verdict: in simulation the gate always
scores with ground truth, and a world model may only choose which candidates are worth real evaluation budget.
Learners¶
learning ¶
Learning pipeline contracts (RFC-0004): data source -> labeler -> learner -> sealed artifact -> candidate -> gate.
Contracts only. A learner turns development data into one artifact directory and seals it
(artifact.write_manifest). Running jobs (in-process or with another venv's interpreter), calibration and data
ingestion live in hylo-learn (hylo.learn).
Learner ¶
OnlineLearner ¶
Bases: Protocol
Learns by acting (policy search, on-policy RL, iterative self-training): each iteration it proposes agent
specs to roll out, the runner evaluates them on a development split (recorded as ordinary runs) and hands back
the results, the learner updates. seal writes the artifact; its provenance lists every rollout run.
Run by hylo.learn.online.run_online; a TrainJob whose learner has policies / update is online and
carries the experiment config in params["experiment"].
DataSource ¶
Bases: Protocol
Episodes from outside the campaign's own runs (demonstrations, videos, other robots).
core.datasource.ingest turns them into a run under split external:
Benchmarks¶
benchmark ¶
Benchmark = versioned set of TaskSpecs + evaluation protocol (splits, seeds, episodes); the benchmarks plugin
contract (hylo.benchmark): a plugin is a factory that returns a Benchmark.
standard_splits ¶
Disjoint seed ranges: train 0.., validation 10000.., heldout 20000..
rsi_splits ¶
rsi_splits(n_states: int = 50, bounds: tuple[int, int, int] = (20, 30, 40), replicates: int = 1, gate_looks: int = 1) -> dict[str, tuple[int, ...]]
RFC-0002 split of init-state indices: search (diagnosis), search_val (selection), gate (confirmation), heldout (report only). Replicate r reuses init state (seed % n_states) with new policy noise (seed + r * n_states). gate_looks > 1 adds gate_r1 .. gate_r{looks-1}: further noise replicates of the gate init states, evaluated only when an earlier look is inconclusive (group-sequential gate).
Scorers and gate tests¶
scoring ¶
The scorers and gate_tests plugin contracts (hylo.scorer, hylo.gate_test) and the data they exchange.
A scorer reads one episode's trace (never the agent or the environment) and returns a Score; a Score of None is an abstention (infra failure, agent error) and is excluded from metrics. A gate test compares per-episode values of one metric between a candidate and its parent, paired on (task, seed), and returns a PairedComparison. Implementations (success, steps, McNemar, sign, permutation) live in hylo-eval.
Generators and campaign records¶
improvement ¶
The generators plugin contract (hylo.generator) and the records of an improvement campaign.
A generator (Proposer) reads a parent's diagnosis and the campaign's archive and proposes candidates: declarative patches of dotted config paths, each with a hypothesis. The cascade, the gate and the registry that decide what happens to a candidate live in hylo-evolve; these are the shapes a generator plugin sees and returns.
CandidateKind
module-attribute
¶
CandidateKind = Literal['config_patch', 'critic_rule', 'recovery_rule', 'prompt', 'skill', 'policy_ref', 'code']
Candidate ¶
Safety¶
safety ¶
SafetyShield: the single, non-bypassable checkpoint between any Agent and any Environment.
- Built by the kernel from the EnvSpec plus config; Agents never see or construct it.
- Mandatory guards (finite check, bounds clamp) are always installed; config can only add guards
or tighten limits. RSI candidates cannot target the
safety.*config scope (evolve/candidate.py). - Extra guards are plugins ("guards" group):
safety: {guards: [{type: keep_out, params: {...}}]}. They run between the mandatory finite check (first) and bounds clamp (last), so no plugin can let a non-finite or out-of-bounds action through. Built in: delta_limit, workspace, norm_limit, keep_out. - Rotation-aware: per-dimension clamping is refused for quaternion / rot6d dims (inspect-robots approver.py makes the same choice).
SafetyContext
dataclass
¶
SafetyContext(space: BoxSpace, clip_tolerance: float = 0.0, state: Any = None, last_action: ndarray | None = None, step: int = 0)
GuardVerdict
dataclass
¶
Guard ¶
FiniteGuard ¶
BoundsGuard ¶
WorkspaceGuard ¶
DeltaLimitGuard ¶
SafetyReview
dataclass
¶
SafetyReview(proposed: ndarray, approved: ndarray, modified: bool, reasons: list[str] = list(), clipped: bool = False)
SafetyShield ¶
SafetyShield(env_spec: EnvSpec, extra_guards: list[Guard] | None = None, *, abort_on_modification: bool = False, clip_tolerance: float = 0.05)
NormLimitGuard ¶
KeepOutGuard ¶
KeepOutGuard(state_key: str, low: list[float], high: list[float], action_dims: list[int], margin: float = 0.0)
A box the controlled point must not enter (a fixture, a person's side of the table). Delta-position components that move the point into the box, or deeper into it, are zeroed.
workspace_guard ¶
workspace_guard(state_key: str, low: list[float], high: list[float], action_dims: list[int]) -> WorkspaceGuard
build_guards ¶
Extra guards from the safety config: max_delta (shorthand) and guards: [{type, params}] plugins.