hylo-core¶
Hylo core: contracts, kernel, safety shield, events, trace, registry, config, remote env protocol
Repository hylo-harness, packages/hylo-core. Licence: Apache-2.0. Depends on: numpy>=1.24, pydantic>=2.7, pyyaml>=6, websockets>=13, msgpack>=1.0.
Registered entry points
| Group | Name | Object |
|---|---|---|
| agents | remote |
hylo.core.remote.agent_client:RemoteAgent |
| agents | remote.ws |
hylo.core.remote.ws:WSAgent |
| commands | profile |
hylo.core.profile:main |
| commands | store |
hylo.core.store:main |
| envs | remote.ws |
hylo.core.remote.ws:WSEnvironment |
| envs | testing.point_reach |
hylo.testing.point_reach:PointReachEnv |
| guards | delta_limit |
hylo.core.safety:DeltaLimitGuard |
| guards | keep_out |
hylo.core.safety:KeepOutGuard |
| guards | norm_limit |
hylo.core.safety:NormLimitGuard |
| guards | workspace |
hylo.core.safety:workspace_guard |
| learners | testing.summary |
hylo.testing.learners:SummaryLearner |
| Module | Summary |
|---|---|
hylo.core |
Hylo core: contracts, execution kernel, safety shield, events, trace, registry, config |
hylo.core.agent |
Agent contract. The kernel only knows Agent; reasoners, planners, policies, world models and |
hylo.core.artifact |
Derived artifacts (RFC-0004): everything the system learns is a versioned, digest-pinned directory with provenance |
hylo.core.benchmark |
Benchmark = versioned set of TaskSpecs + evaluation protocol (splits, seeds, episodes); the benchmarks plugin |
hylo.core.cli |
hylo: the command dispatcher. Each package registers its own subcommands |
hylo.core.codec |
JSON-safe encoding for numpy arrays and arbitrary payloads. No pickle anywhere (RPent's socket RPC |
hylo.core.compat |
Bind-time compatibility check between an Agent and an Environment |
hylo.core.config |
Versioned experiment configuration and run manifest (design/experiment-schema.md) |
hylo.core.contract |
Base class and field types for data contracts |
hylo.core.datasource |
External data contracts (RFC-0004): demonstrations, videos and other robots' logs |
hylo.core.deployment |
The active version of an improvement campaign, as a file (hylo.active/v0.1) |
hylo.core.env |
Environment contract. An Environment = Simulator + Task logic behind reset/step |
hylo.core.errors |
Error taxonomy (semantics follow inspect-robots errors.py and vla-eval EpisodeError.phase) |
hylo.core.events |
Typed events and a synchronous event bus |
hylo.core.experience |
Experience contracts (RFC-0003): action memory, lessons and skills. Contracts and protocols only; stores live in |
hylo.core.improvement |
The generators plugin contract (hylo.generator) and the records of an improvement campaign |
hylo.core.instrument |
Instruments (RFC-0004): learned components that measure or label instead of act |
hylo.core.kernel |
Execution kernel: the one episode loop, used for evaluation, learning rollouts and deployment |
hylo.core.learning |
Learning pipeline contracts (RFC-0004): data source -> labeler -> learner -> sealed artifact -> candidate -> gate |
hylo.core.memory |
Memory contracts (schema from our research notes) |
hylo.core.plugins |
Contract versions and plugin metadata (RFC-0005 part 4) |
hylo.core.policy |
Policies (plugin group "policies"): action-chunk generators that agents run, steer and compose |
hylo.core.profile |
Execution profiles (hylo.profile/v0.1): where components run on this machine, kept out of experiment configs |
hylo.core.reasoning |
Reasoning plugin contracts, one per role (each its own plugin group and version): |
hylo.core.registry |
Plugin registry: explicit registration, module:attr references (vla-eval style) and |
hylo.core.remote |
|
hylo.core.remote.agent_client |
RemoteAgent: an Agent proxy for an AgentServer subprocess (e.g. a VLA in its own torch venv) |
hylo.core.remote.agent_server |
AgentServer: hosts one Agent in its own process (and venv), mirroring the EnvServer |
hylo.core.remote.client |
RemoteEnvironment: an Environment proxy for an EnvServer subprocess |
hylo.core.remote.handlers |
Transport-agnostic request dispatch for the EnvServer and AgentServer protocols |
hylo.core.remote.protocol |
EnvServer protocol hylo.envserver/v0.1: newline-delimited JSON over a subprocess's stdio |
hylo.core.remote.server |
EnvServer: hosts one Environment in its own process (in practice its own venv/container), so |
hylo.core.remote.wire |
msgpack-numpy wire format (the one openpi uses), shared by the policy server (hylo-serve) and the openpi client |
hylo.core.remote.workcell |
Workcell API (hylo.workcell/v0.1): what a workcell serves and a control plane calls |
hylo.core.remote.ws |
WebSocket transport for the EnvServer / AgentServer protocols: run a simulator or a policy on another |
hylo.core.safety |
SafetyShield: the single, non-bypassable checkpoint between any Agent and any Environment |
hylo.core.scorecard |
Scorecards (hylo.scorecard/v0.1): the result of running one policy under one benchmark protocol |
hylo.core.scoring |
The scorers and gate_tests plugin contracts (hylo.scorer, hylo.gate_test) and the data they exchange |
hylo.core.store |
Run and artifact store (hylo.store/v0.1): global ids, references instead of paths, deletion protection, sync |
hylo.core.task |
Task contracts. A TaskSpec covers both LIBERO-style declarative tasks with fixed init states and |
hylo.core.trace |
Event-sourced, replayable episode trace |
hylo.core.types |
Core data contracts shared by every layer (design/interfaces/environment.md, agent.md) |
hylo.testing |
Test fixtures shipped with core: the test double environment (testing.point_reach) and the conformance kit |
hylo.testing.conformance |
Conformance kit: contract checks every plugin must pass (design/plugin-system.md §6) |
hylo.testing.learners |
A dependency-free learner for tests and conformance: summarises development runs into a sealed artifact |
hylo.testing.point_reach |
Test double: a deterministic 2-D point-mass environment ("testing.point_reach") for unit and conformance tests |
hylo.testing.setup |
Where plugin checks run: a real simulator when one is installed, the test double otherwise |
hylo.core¶
Hylo core: contracts, execution kernel, safety shield, events, trace, registry, config.
META
module-attribute
¶
META = {'contracts': {'envs': 'hylo.env/v0.1', 'agents': 'hylo.agent/v0.1', 'guards': 'hylo.guard/v0.1', 'learners': 'hylo.learner/v0.1'}, 'maturity': 'implemented'}
hylo.core.agent¶
A core contract: documented in contracts.
hylo.core.artifact¶
A core contract: documented in artifacts and store.
hylo.core.benchmark¶
A core contract: documented in contracts.
hylo.core.cli¶
hylo: the command dispatcher. Each package registers its own subcommands.
A subcommand is an entry point in the group "hylo.commands": a name and a callable taking the remaining arguments and returning an exit code. The first line of the callable's docstring is its help line.
[project.entry-points."hylo.commands"]
bench = "hylo.bench.cli:main" # hylo bench ... (hylo-bench)
So hylo only has the commands of what is installed: on a robot computer with hylo-core and hylo-serve, hylo serve; on
a workstation with the harness, hylo run, hylo evolve, hylo learn, ...; with hylo-bench also hylo bench.
hylo.core.codec¶
JSON-safe encoding for numpy arrays and arbitrary payloads. No pickle anywhere (RPent's socket RPC unpickles arbitrary frames; DSPy's .pkl programs execute code on load).
hylo.core.compat¶
Bind-time compatibility check between an Agent and an Environment.
Unlike vla-eval (mismatch -> logger.warning), errors here stop the run. Severity split follows inspect-robots compat.py: control mode / rotation / dimensionality are errors; frame and gripper conventions are warnings.
CompatReport
dataclass
¶
hylo.core.config¶
A core contract: documented in config.
hylo.core.contract¶
Base class and field types for data contracts.
Rules:
- Data that crosses a boundary (process, file, version, plugin) is a frozen pydantic model with
extra="forbid", so typos fail loudly and every contract has a JSON Schema.
- Runtime objects that hold callables or live handles (EpisodeContext, SafetyContext) stay plain
dataclasses; they are never serialized.
- numpy arrays use NDArray; free-form payloads that may contain arrays use JsonAny. Both
round-trip through JSON via core.codec, so model_dump(mode="json") / model_validate is the
whole wire format.
- Formats written before the rename to Hylo (2026-11-01) carry wc.<name>/v<x> schema ids and refer to
worldcurrent.* modules. They are read as hylo.<name>/v<x> and hylo.* (current_schema,
current_module), so recorded runs, artifacts, configs and profiles stay readable; nothing is rewritten on disk.
LEGACY_MODULE_PREFIXES
module-attribute
¶
NDArray
module-attribute
¶
NDArray = Annotated[np.ndarray, PlainValidator(_to_array), PlainSerializer(codec.encode_array, when_used='json'), WithJsonSchema({'type': 'object', 'description': 'numpy array {__nd__, dtype, shape, b64}', 'required': ['__nd__', 'dtype', 'shape', 'b64']})]
JsonAny
module-attribute
¶
JsonAny = Annotated[Any, PlainValidator(codec.decode), PlainSerializer(codec.encode, when_used='json'), WithJsonSchema({})]
current_schema ¶
A schema id as it is named now: "wc.critic/v0.1" -> "hylo.critic/v0.1" (anything else unchanged).
current_module ¶
A module or module:attr reference as it is named now: "worldcurrent.agents.x:Y" -> "hylo.agents.x:Y".
hylo.core.datasource¶
External data contracts (RFC-0004): demonstrations, videos and other robots' logs.
A DataSource yields ExternalEpisodes. hylo.learn.data.ingest writes them as a run under split
external:<name> (sealed, with origin and licence); every label says who produced it ("source", "judge:
hylo.core.deployment¶
A core contract: documented in artifacts and store.
hylo.core.env¶
A core contract: documented in contracts.
hylo.core.errors¶
Error taxonomy (semantics follow inspect-robots errors.py and vla-eval EpisodeError.phase).
- AgentError: the agent failed; the episode is marked
errorand not scored. - EnvironmentFault: the env/sim failed; infra problem, counted as infra_invalid.
- SafetyAbort: a guard, the operator (stop, e-stop) or the realtime watchdog halted the episode. Guard and operator stops are scored as safety_abort; a watchdog abort (no new actions for max_hold_steps) is the agent's failure: error.
- IncompatibleComponents: bind-time contract mismatch; the run never starts.
The partial episode record travels on
exc.recordso nothing collected so far is lost.
hylo.core.events¶
A core contract: documented in kernel.
hylo.core.experience¶
Experience contracts (RFC-0003): action memory, lessons and skills. Contracts and protocols only; stores live in hylo-memory, consumers in hylo-agents, writers in hylo-evolve / hylo-reasoner-llm.
Every memory used in an evaluation is a frozen artifact with a content digest (recorded in the agent spec), and is built from verified development-split experience only.
EpisodeRef ¶
ActionSegment ¶
Bases: Contract
One verified decision point: the retrieval key of the observation and the chunk the policy then produced.
ActionMemory ¶
PriorDecision ¶
PriorSampler ¶
Bases: Protocol
A ChunkSampler that can start flow sampling from x_t0 = (1 - t0) * prior + t0 * noise. prior_fn receives the
retrieval key computed inside the policy's own forward pass, so retrieval costs no extra encoder call.
SkillTrigger ¶
hylo.core.improvement¶
A core contract: documented in contracts.
hylo.core.instrument¶
A core contract: documented in contracts.
hylo.core.kernel¶
A core contract: documented in kernel.
hylo.core.learning¶
A core contract: documented in contracts.
hylo.core.memory¶
Memory contracts (schema from our research notes).
They live in core so that agents (consumers) and memory backends (providers) depend only on core, never on each other. Time and pose are first-class fields with real range semantics, not values packed into an embedding; facts about the world are invalidated, never deleted (bi-temporal).
hylo.core.plugins¶
A core contract: documented in config.
hylo.core.policy¶
A core contract: documented in contracts.
hylo.core.profile¶
A core contract: documented in config.
hylo.core.reasoning¶
A core contract: documented in contracts.
hylo.core.registry¶
A core contract: documented in config.
hylo.core.remote¶
hylo.core.remote.agent_client¶
RemoteAgent: an Agent proxy for an AgentServer subprocess (e.g. a VLA in its own torch venv).
RemoteAgent ¶
RemoteAgent(ref: str, params: dict[str, Any] | None = None, python: str | None = None, env: dict[str, str] | None = None, forward_steps: bool = True, runtime: str | None = None)
hylo.core.remote.agent_server¶
AgentServer: hosts one Agent in its own process (and venv), mirroring the EnvServer.
Protocol hylo.agentserver/v0.1, newline-delimited JSON on stdio:
-> {"hello": "hylo.agentserver/v0.1"}
<- {"id", "method": "spec" | "reset" | "act" | "on_step" | "on_episode_end" | "close", "args"}
-> {"id", "ok": true, "result": ..., "events": [[type, payload], ...]} | {"id", "ok": false, "error", "traceback"}
Events the agent emits through EpisodeContext.emit are buffered and returned with each reply, so the kernel in the parent process writes them to the trace as if the agent were local.
python -m hylo.core.remote.agent_server <module:attr> '<json params>'
hylo.core.remote.client¶
RemoteEnvironment: an Environment proxy for an EnvServer subprocess.
RemoteEnvironment ¶
hylo.core.remote.handlers¶
Transport-agnostic request dispatch for the EnvServer and AgentServer protocols.
A handler turns one decoded request {"id", "method", "args"} into one JSON-safe reply. The stdio servers and the WebSocket server (ws.py) share these, so both transports speak exactly the same messages.
hylo.core.remote.protocol¶
EnvServer protocol hylo.envserver/v0.1: newline-delimited JSON over a subprocess's stdio.
Contracts are pydantic models, so the wire format is just model_dump(mode="json") and
model_validate; arrays travel through core.codec. No pickle.
-> {"hello": "hylo.envserver/v0.1"} (server, once)
<- {"id": 1, "method": "spec" | "reset" | "step" | "privileged_state" | "close", "args": {...}}
-> {"id": 1, "ok": true, "result": ...} | {"id": 1, "ok": false, "error": "...", "traceback": "..."}
child_env ¶
Environment for a component subprocess: the parent's, plus extra with ~ and $VARS expanded.
claim_stdout ¶
Reserve the real stdout for the protocol and send everything else written to fd 1 (Python prints, C extensions, library banners) to stderr, so third-party output can never corrupt the stream.
hylo.core.remote.server¶
EnvServer: hosts one Environment in its own process (in practice its own venv/container), so dependency-incompatible benchmarks (LIBERO: py3.8 + robosuite 1.4; RoboCasa: py3.11 + robosuite>=1.5.2) run side by side.
python -m hylo.core.remote.server <module:Class> '<json params>'
hylo.core.remote.wire¶
msgpack-numpy wire format (the one openpi uses), shared by the policy server (hylo-serve) and the openpi client.
msgpack frames in which numpy arrays are maps {b"ndarray": True, b"data": raw bytes, b"dtype": dtype.str, b"shape": shape} (and numpy scalars {b"npgeneric": True, b"data": item, b"dtype": dtype.str}). Written from the format, not copied; like openpi and core.codec it never falls back to pickle, so object / void dtypes are refused.
hylo.core.remote.workcell¶
Workcell API (hylo.workcell/v0.1): what a workcell serves and a control plane calls.
A workcell (hylo-serve) runs next to a robot or simulator and executes episodes with a remote policy. A control plane (the playground in hylo-studio) starts episodes and relays operator input. Both sides use the models here, so neither imports the other.
GET /healthz liveness, no auth
GET /status the workcell's state (dict; see WORKCELL_STATES)
POST /episodes StartEpisode -> EpisodeStarted 409 while an episode runs or a fault is latched
POST /operator OperatorEvent -> OperatorAck 400 for an unknown or malformed event
WS /events the live event stream: one JSON event per message
Auth, when the workcell has a token: Authorization: Bearer <token> on HTTP, ?token=<token> on the WebSocket.
PATHS
module-attribute
¶
PATHS = {'healthz': '/healthz', 'status': '/status', 'episodes': '/episodes', 'operator': '/operator', 'events': '/events'}
WORKCELL_STATES
module-attribute
¶
OperatorEventType
module-attribute
¶
EpisodeStarted ¶
hylo.core.remote.ws¶
WebSocket transport for the EnvServer / AgentServer protocols: run a simulator or a policy on another machine, container or GPU box, with the same JSON messages as the stdio transport (handlers.py).
# serve (in the component's own venv; binds localhost unless --host is given)
python -m hylo.core.remote.ws env libero --params '{"image_size": 256}' --port 8765
python -m hylo.core.remote.ws agent lerobot --params '{...}' --port 8766 --token-env HYLO_TOKEN
# use from any experiment config
env: {type: remote.ws, params: {url: "ws://gpu-box:8765"}}
agent: {type: remote.ws, params: {url: "ws://gpu-box:8766", token_env: HYLO_TOKEN}}
Each connection gets its own component instance (parallel workers = parallel connections, as with stdio subprocesses). One text frame per request and per reply; the server sends {"hello": PROTOCOL} first. GET /healthz answers 200 for load balancers. Auth is an optional shared bearer token; use TLS (wss://) or an SSH tunnel across untrusted networks.
ComponentServer ¶
WSEnvironment ¶
Bases: _Client
Environment proxy for a remote ws.py env server.
WSAgent ¶
Bases: _Client
Agent proxy for a remote ws.py agent server; relays the agent's trace events like RemoteAgent.
make_server ¶
make_server(kind: str, ref: str, params: dict[str, Any] | None = None, **kw: Any) -> ComponentServer
hylo.core.safety¶
A core contract: documented in contracts.
hylo.core.scorecard¶
A core contract: documented in artifacts and store.
hylo.core.scoring¶
A core contract: documented in contracts.
hylo.core.store¶
A core contract: documented in artifacts and store.
hylo.core.task¶
A core contract: documented in contracts.
hylo.core.trace¶
A core contract: documented in kernel.
hylo.core.types¶
A core contract: documented in contracts.
hylo.testing¶
Test fixtures shipped with core: the test double environment (testing.point_reach) and the conformance kit.
hylo.testing.conformance¶
Conformance kit: contract checks every plugin must pass (design/plugin-system.md §6).
from hylo.testing.conformance import check_environment, check_agent, check_memory_store, check_scorer
report = check_environment(lambda: MyEnv(), task) # -> ConformanceReport
assert report.ok, report.summary()
Also available as hylo conformance env|agent|memory <plugin> [--params JSON].
CheckResult ¶
ConformanceReport ¶
check_environment ¶
check_environment(env_factory: Callable[[], Environment], task: TaskInstance | TaskSpec, *, n_steps: int = 5, spec_budget_s: float = 2.0) -> ConformanceReport
check_agent ¶
check_agent(agent: Agent, env: Environment, task: TaskInstance | TaskSpec, *, deterministic: bool = True) -> ConformanceReport
check_guard ¶
check_guard(guard: Any, *, action_dim: int = 2, trials: int = 50, seed: int = 0) -> ConformanceReport
A guard plugin: named, returns a finite action of the same shape, never enlarges what it was given beyond the action box, works without state, and is deterministic for the same input.
check_policy ¶
A policy plugin (core.policy.ChunkPolicy): its spec fits the environment, sample returns finite (N, T, A)
chunks of the action shape, the same seeds give the same chunks (randomness comes from the seeds only), and
default_execution_steps is within the chunk.
hylo.testing.learners¶
hylo.testing.point_reach¶
Test double: a deterministic 2-D point-mass environment ("testing.point_reach") for unit and conformance tests.
Not an evaluation environment: examples, protocols and campaigns use the real simulators of hylo-bench
(MuJoCo, LIBERO). hylo plugins lists testing.* plugins only with --all.
Task params (TaskSpec.params): goal: [x, y] or "random" (seeded) goal_visible_steps: int | None goal shown only for the first N steps (working memory) sense_radius: float | None goal shown only when within this radius (exploration / memory) push: {"step": k, "velocity": [vx, vy]} external perturbation (recovery)
PointReachEnv ¶
hylo.testing.setup¶
Where plugin checks run: a real simulator when one is installed, the test double otherwise.
hylo plugin check and the learning / generator conformance checks make their sample runs and environments from
check_experiment(): MuJoCo planar reach (hylo-bench's hylo-env-mujoco, with the analytic IK controller)
when it is registered, else the harness's test double, so a harness-only install can still check a plugin. Any
experiment config can be given instead (hylo plugin check ... --experiment CONFIG.yaml), e.g. your robot's.
MUJOCO
module-attribute
¶
MUJOCO = ExperimentConfig(name='conformance', benchmark={'type': 'mujoco/reach-v0', 'params': {'protocol': 'rsi'}}, env={'type': 'mujoco.planar_reach'}, agent={'type': 'baseline.planar_ik', 'params': {'kp': 0.3}}, workers=8)
DOUBLE
module-attribute
¶
DOUBLE = ExperimentConfig(name='conformance', benchmark={'type': 'testing/reach-v0', 'params': {'tags': ['reach'], 'protocol': 'rsi'}}, env={'type': 'testing.point_reach'}, agent={'type': 'testing.p_controller', 'params': {'kp': 1.0}})
check_experiment ¶
check_experiment(experiment: str | Path | ExperimentConfig | None = None, prefer: Literal['auto', 'mujoco', 'double'] = 'auto') -> ExperimentConfig
The experiment checks run on: the given one, else MuJoCo planar reach if installed, else the test double.
env_and_task ¶
A fresh environment of the experiment and its first task instance (validation split, else the first split).