Skip to content

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.

GROUP module-attribute

GROUP = 'hylo.commands'

commands

commands() -> dict[str, EntryPoint]

main

main(argv: list[str] | None = None) -> int

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).

ALLOWED_KINDS module-attribute

ALLOWED_KINDS = frozenset('biuf')

encode_array

encode_array(arr: ndarray) -> dict[str, Any]

decode_array

decode_array(obj: dict[str, Any]) -> np.ndarray

encode

encode(obj: Any) -> Any

decode

decode(obj: Any) -> Any

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

CompatReport(errors: list[str] = list(), warnings: list[str] = list())

errors class-attribute instance-attribute

errors: list[str] = field(default_factory=list)

warnings class-attribute instance-attribute

warnings: list[str] = field(default_factory=list)

ok property

ok: bool

check_compatibility

check_compatibility(agent: AgentSpec, env: EnvSpec) -> CompatReport

require_compatible

require_compatible(agent: AgentSpec, env: EnvSpec) -> CompatReport

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

LEGACY_MODULE_PREFIXES = {'worldcurrent.': 'hylo.', 'wc_examples': 'hylo_examples'}

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({})]

Contract

Bases: BaseModel

model_config class-attribute instance-attribute

model_config = ConfigDict(frozen=True, extra='forbid', arbitrary_types_allowed=True)

current_schema

current_schema(value: Any) -> Any

A schema id as it is named now: "wc.critic/v0.1" -> "hylo.critic/v0.1" (anything else unchanged).

current_module

current_module(ref: str) -> str

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:" or none) and an unlabeled episode is never treated as a success.

ExternalFrame

Bases: Contract

state class-attribute instance-attribute

state: dict[str, NDArray] = Field(default_factory=dict)

images class-attribute instance-attribute

images: dict[str, NDArray] = Field(default_factory=dict)

action class-attribute instance-attribute

action: NDArray | None = None

ExternalEpisode

Bases: Contract

episode_id instance-attribute

episode_id: str

task_id instance-attribute

task_id: str

instruction class-attribute instance-attribute

instruction: str = ''

frames instance-attribute

frames: list[ExternalFrame]

success class-attribute instance-attribute

success: bool | None = None

meta class-attribute instance-attribute

meta: dict[str, JsonAny] = Field(default_factory=dict)

external_split

external_split(name: str) -> str

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 error and 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.record so nothing collected so far is lost.

HyloError

HyloError(message: str, *, record: Any = None)

Bases: Exception

phase class-attribute instance-attribute

phase: str = 'unknown'

record instance-attribute

record = record

AgentError

AgentError(message: str, *, record: Any = None)

Bases: HyloError

phase class-attribute instance-attribute

phase = 'agent_act'

AgentTimeout

AgentTimeout(message: str, *, record: Any = None)

Bases: AgentError

phase class-attribute instance-attribute

phase = 'agent_timeout'

EnvironmentFault

EnvironmentFault(message: str, *, record: Any = None)

Bases: HyloError

phase class-attribute instance-attribute

phase = 'env_step'

SafetyAbort

SafetyAbort(message: str, *, record: Any = None)

Bases: HyloError

phase class-attribute instance-attribute

phase = 'safety'

IncompatibleComponents

IncompatibleComponents(message: str, *, record: Any = None)

Bases: HyloError

phase class-attribute instance-attribute

phase = 'bind'

ProtectedScopeViolation

ProtectedScopeViolation(message: str, *, record: Any = None)

Bases: HyloError

phase class-attribute instance-attribute

phase = 'evolution'

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.

PriorFn module-attribute

PriorFn = Callable[[np.ndarray], PriorDecision]

EpisodeRef

Bases: Contract

run_id instance-attribute

run_id: str

episode_id instance-attribute

episode_id: str

split instance-attribute

split: str

judge class-attribute instance-attribute

judge: str = 'sim'

ActionSegment

Bases: Contract

One verified decision point: the retrieval key of the observation and the chunk the policy then produced.

key instance-attribute

key: NDArray

actions instance-attribute

actions: NDArray

task_id instance-attribute

task_id: str

step class-attribute instance-attribute

step: int = Field(ge=0)

progress class-attribute instance-attribute

progress: float = Field(default=0.0, ge=0.0, le=1.0)

source instance-attribute

source: EpisodeRef

ActionMemory

Bases: Protocol

add

add(segments: Sequence[ActionSegment]) -> int

query

query(key: ndarray, *, task_id: str | None = None, k: int = 10) -> list[tuple[ActionSegment, float]]

snapshot

snapshot() -> str

save

save(path: str) -> str

PriorDecision

Bases: Contract

What the memory steerer hands the sampler: a chunk prior and the flow time to start integrating from.

prior instance-attribute

prior: NDArray | None

t0 class-attribute instance-attribute

t0: float = Field(default=1.0, ge=0.0, le=1.0)

info class-attribute instance-attribute

info: dict[str, JsonAny] = Field(default_factory=dict)

noise class-attribute instance-attribute

noise: NDArray | None = None

noise_weight class-attribute instance-attribute

noise_weight: float = Field(default=0.0, ge=0.0, le=1.0)

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.

sample

sample(observation: Observation, seeds: list[int] | None, noise_scale: float = 1.0, prior_fn: PriorFn | None = None) -> np.ndarray

retrieval_key

retrieval_key(observation: Observation) -> np.ndarray

Lesson

Bases: Contract

id instance-attribute

id: str

scope instance-attribute

scope: str

kind instance-attribute

kind: Literal['strategy', 'pitfall']

title instance-attribute

title: str

content instance-attribute

content: str

helpful class-attribute instance-attribute

helpful: int = 0

harmful class-attribute instance-attribute

harmful: int = 0

evidence class-attribute instance-attribute

evidence: list[EpisodeRef] = Field(default_factory=list)

status class-attribute instance-attribute

status: Literal['active', 'retired'] = 'active'

SkillTrigger

Bases: Contract

instruction_pattern class-attribute instance-attribute

instruction_pattern: str | None = None

task_tags class-attribute instance-attribute

task_tags: tuple[str, ...] = ()

env class-attribute instance-attribute

env: str | None = None

Skill

Bases: Contract

name instance-attribute

name: str

version instance-attribute

version: str

description instance-attribute

description: str

trigger instance-attribute

trigger: SkillTrigger

kind instance-attribute

kind: Literal['plan', 'steering', 'recovery', 'weights']

body instance-attribute

body: dict[str, JsonAny]

status class-attribute instance-attribute

status: Literal['proposed', 'verified', 'refuted', 'deprecated'] = 'proposed'

verdicts class-attribute instance-attribute

verdicts: dict[str, int] = Field(default_factory=dict)

evidence class-attribute instance-attribute

evidence: dict[str, Any] = Field(default_factory=dict)

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).

WriteOp module-attribute

WriteOp = Literal['ADD', 'INVALIDATE', 'SKIP_DUP']

MemoryKind

Bases: str, Enum

WORKING class-attribute instance-attribute

WORKING = 'working'

EPISODIC class-attribute instance-attribute

EPISODIC = 'episodic'

SEMANTIC class-attribute instance-attribute

SEMANTIC = 'semantic'

SPATIAL class-attribute instance-attribute

SPATIAL = 'spatial'

SKILL class-attribute instance-attribute

SKILL = 'skill'

Pose

Bases: Contract

frame_id instance-attribute

frame_id: str

position instance-attribute

position: tuple[float, float, float]

orientation class-attribute instance-attribute

orientation: tuple[float, float, float, float] | None = None

TimeSpan

Bases: Contract

start instance-attribute

start: float

end class-attribute instance-attribute

end: float | None = None

clock class-attribute instance-attribute

clock: Literal['sim', 'wall'] = 'sim'

MemoryItem

Bases: Contract

kind instance-attribute

kind: MemoryKind

content instance-attribute

content: str

key class-attribute instance-attribute

key: str | None = None

payload class-attribute instance-attribute

payload: dict[str, JsonAny] = Field(default_factory=dict)

entities class-attribute instance-attribute

entities: tuple[str, ...] = ()

scope class-attribute instance-attribute

scope: dict[str, str] = Field(default_factory=dict)

pose class-attribute instance-attribute

pose: Pose | None = None

event_time class-attribute instance-attribute

event_time: TimeSpan | None = None

valid_from class-attribute instance-attribute

valid_from: float | None = None

confidence class-attribute instance-attribute

confidence: float = Field(default=1.0, ge=0.0, le=1.0)

source class-attribute instance-attribute

source: str = ''

id class-attribute instance-attribute

id: str = Field(default_factory=lambda: uuid.uuid4().hex)

content_hash

content_hash() -> str

MemoryQuery

Bases: Contract

text class-attribute instance-attribute

text: str | None = None

kinds class-attribute instance-attribute

kinds: frozenset[MemoryKind] | None = None

key class-attribute instance-attribute

key: str | None = None

entities class-attribute instance-attribute

entities: tuple[str, ...] = ()

scope class-attribute instance-attribute

scope: dict[str, str] | None = None

time_range class-attribute instance-attribute

time_range: tuple[float, float] | None = None

as_of class-attribute instance-attribute

as_of: float | None = None

near class-attribute instance-attribute

near: tuple[Pose, float] | None = None

include_invalidated class-attribute instance-attribute

include_invalidated: bool = False

k class-attribute instance-attribute

k: int = Field(default=10, ge=1)

Hit

Bases: Contract

item instance-attribute

item: MemoryItem

score instance-attribute

score: float

details class-attribute instance-attribute

details: dict[str, float] = Field(default_factory=dict)

valid_to class-attribute instance-attribute

valid_to: float | None = None

WriteResult

Bases: Contract

events instance-attribute

events: tuple[tuple[WriteOp, str], ...]

MemoryStore

Bases: Protocol

write

write(items: Sequence[MemoryItem]) -> WriteResult

query

query(q: MemoryQuery) -> list[Hit]

forget

forget(q: MemoryQuery) -> int

snapshot

snapshot() -> str

WorkingMemory

WorkingMemory(capacity: int = 256)

Per-episode key/value scratchpad with a hard capacity (ReMEmbR's working memory is unbounded).

capacity instance-attribute

capacity = capacity

put

put(key: str, value: Any) -> None

get

get(key: str, default: Any = None) -> Any

clear

clear() -> None

items

items() -> list[tuple[str, Any]]

now

now() -> float

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)

forward_steps instance-attribute

forward_steps = forward_steps

spec

spec() -> AgentSpec

reset

reset(ctx: EpisodeContext) -> None

act

act(observation: Observation) -> ActionChunk

on_step

on_step(result: StepResult) -> None

on_episode_end

on_episode_end(outcome: EpisodeOutcome) -> None

close

close() -> 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>'

PROTOCOL module-attribute

PROTOCOL = 'hylo.agentserver/v0.1'

main

main(argv: list[str]) -> int

hylo.core.remote.client

RemoteEnvironment: an Environment proxy for an EnvServer subprocess.

RemoteEnvironment

RemoteEnvironment(ref: str, params: dict[str, Any] | None = None, *, python: str | None = None, env: dict[str, str] | None = None, runtime: str | None = None)

spec

spec() -> EnvSpec

reset

reset(task: TaskInstance) -> Observation

step

step(action: Action) -> StepResult

privileged_state

privileged_state() -> dict[str, Any]

close

close() -> None

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.

EnvHandler

EnvHandler(env: Any)

protocol class-attribute instance-attribute

protocol = 'hylo.envserver/v0.1'

env instance-attribute

env = env

closed instance-attribute

closed = False

handle

handle(msg: dict[str, Any]) -> dict[str, Any]

close

close() -> None

AgentHandler

AgentHandler(agent: Any)

protocol class-attribute instance-attribute

protocol = 'hylo.agentserver/v0.1'

agent instance-attribute

agent = agent

closed instance-attribute

closed = False

handle

handle(msg: dict[str, Any]) -> dict[str, Any]

close

close() -> None

load_component

load_component(ref: str, params: dict[str, Any] | None, group: str) -> Any

Build from 'module:attr' or, failing that, from a registered plugin name in group.

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": "..."}

PROTOCOL module-attribute

PROTOCOL = 'hylo.envserver/v0.1'

METHODS module-attribute

METHODS = ('spec', 'reset', 'step', 'privileged_state', 'close')

child_env

child_env(extra: dict[str, str] | None) -> dict[str, str]

Environment for a component subprocess: the parent's, plus extra with ~ and $VARS expanded.

claim_stdout

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>'

main

main(argv: list[str]) -> int

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.

packb

packb(obj: Any) -> bytes

unpackb

unpackb(data: bytes) -> Any

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.

WORKCELL_API module-attribute

WORKCELL_API = 'hylo.workcell/v0.1'

PATHS module-attribute

PATHS = {'healthz': '/healthz', 'status': '/status', 'episodes': '/episodes', 'operator': '/operator', 'events': '/events'}

WORKCELL_STATES module-attribute

WORKCELL_STATES = ('idle', 'starting', 'running', 'awaiting_reset', 'awaiting_verdict', 'fault')

OperatorEventType module-attribute

OperatorEventType = Literal['estop', 'stop', 'clear_fault', 'reset_done', 'verdict']

PolicyEndpoint

Bases: Contract

url instance-attribute

url: str

protocol class-attribute instance-attribute

protocol: Literal['hylo', 'openpi'] = 'hylo'

token class-attribute instance-attribute

token: str | None = None

params class-attribute instance-attribute

params: dict[str, JsonAny] = Field(default_factory=dict)

StartEpisode

Bases: Contract

task_id class-attribute instance-attribute

task_id: str | None = None

instruction class-attribute instance-attribute

instruction: str | None = None

seed class-attribute instance-attribute

seed: int = 0

max_steps class-attribute instance-attribute

max_steps: int | None = None

policy class-attribute instance-attribute

policy: PolicyEndpoint | None = None

EpisodeStarted

Bases: Contract

task_id instance-attribute

task_id: str

policy instance-attribute

policy: str

OperatorEvent

Bases: Contract

type instance-attribute

type: OperatorEventType

by class-attribute instance-attribute

by: str | None = None

verdict class-attribute instance-attribute

verdict: Literal['success', 'failure', 'partial'] | None = None

note class-attribute instance-attribute

note: str | None = None

OperatorAck

Bases: Contract

fault instance-attribute

fault: str | None

state instance-attribute

state: str | None

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

ComponentServer(factory: Callable[[], EnvHandler | AgentHandler], *, host: str = '127.0.0.1', port: int = 8765, token: str | None = None, max_connections: int = 64, log: Callable[[str], None] = lambda m: print(m, file=sys.stderr, flush=True))

Serves one component type; factory() builds a fresh handler per connection.

url property

url: str

start

start() -> 'ComponentServer'

Start serving on a background thread (tests, embedding). port=0 picks a free port.

serve_forever

serve_forever() -> None

shutdown

shutdown() -> None

WSEnvironment

WSEnvironment(url: str, **kw: Any)

Bases: _Client

Environment proxy for a remote ws.py env server.

protocol class-attribute instance-attribute

protocol = EnvHandler.protocol

fault class-attribute instance-attribute

fault = EnvironmentFault

spec

spec() -> EnvSpec

reset

reset(task: TaskInstance) -> Observation

step

step(action) -> StepResult

privileged_state

privileged_state() -> dict[str, Any]

close

close() -> None

WSAgent

WSAgent(url: str, forward_steps: bool = True, **kw: Any)

Bases: _Client

Agent proxy for a remote ws.py agent server; relays the agent's trace events like RemoteAgent.

protocol class-attribute instance-attribute

protocol = AgentHandler.protocol

fault class-attribute instance-attribute

fault = AgentError

forward_steps instance-attribute

forward_steps = forward_steps

spec

spec() -> AgentSpec

reset

reset(ctx: EpisodeContext) -> None

act

act(observation: Observation) -> ActionChunk

on_step

on_step(result: StepResult) -> None

on_episode_end

on_episode_end(outcome: EpisodeOutcome) -> None

close

close() -> None

make_server

make_server(kind: str, ref: str, params: dict[str, Any] | None = None, **kw: Any) -> ComponentServer

main

main(argv: list[str] | None = None) -> int

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

Bases: Contract

name instance-attribute

name: str

passed instance-attribute

passed: bool

detail class-attribute instance-attribute

detail: str = ''

skipped class-attribute instance-attribute

skipped: bool = False

ConformanceReport

Bases: Contract

subject instance-attribute

subject: str

checks class-attribute instance-attribute

checks: list[CheckResult] = Field(default_factory=list)

ok property

ok: bool

summary

summary() -> str

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_memory_store

check_memory_store(store_factory: Callable[[], Any]) -> ConformanceReport

check_scorer

check_scorer(scorer: Any, trace: Any, task: TaskInstance) -> ConformanceReport

describe

describe(report: ConformanceReport) -> str

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

check_policy(policy: Any, env: Environment, task: TaskInstance | TaskSpec) -> ConformanceReport

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

A dependency-free learner for tests and conformance: summarises development runs into a sealed artifact.

SummaryLearner

name class-attribute instance-attribute

name = 'hylo.testing.summary@0.1'

fit

fit(job) -> ArtifactManifest

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)

ARENA module-attribute

ARENA = 1.0

SUCCESS_RADIUS module-attribute

SUCCESS_RADIUS = 0.05

PointReachEnv

PointReachEnv(dt: float = 0.05, max_speed: float = 0.5, lag: float = 0.5)

spec

spec() -> EnvSpec

reset

reset(task: TaskInstance) -> Observation

step

step(action: Action) -> StepResult

privileged_state

privileged_state() -> dict

snapshot

snapshot() -> bytes

restore

restore(blob: bytes) -> None

close

close() -> None

reach_tasks

reach_tasks() -> tuple[TaskSpec, ...]

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

env_and_task(cfg: ExperimentConfig) -> tuple[Any, TaskInstance]

A fresh environment of the experiment and its first task instance (validation split, else the first split).