The channel contains two related contracts:
The run loop on the wire
hello creates or resumes a session and returns the environment identity plus
its capability bindings. tasks.start advances one task generator to its first
yield and returns the prompt. The agent drives the advertised capabilities while
that generator remains suspended. tasks.grade sends the agent’s answer into
the generator and returns its second yield as an evaluation.
The environment defines what can be acted on and how the resulting state is
graded. The agent harness defines the action loop. Their only shared contract is
the channel and the capability protocols named by its bindings.
Session methods
A control session speaks JSON-RPC 2.0 for the connection’s lifetime:
Each request and response is one newline-delimited JSON frame. Calls on a
HudClient are serialized, and reply ids must match the corresponding request.
A malformed or unknown call receives a JSON-RPC error frame.
One port, two connection types
The TCP listener accepts many connections but publishes only one address. The first frame on each connection selects its interpretation. Atunnel.open
preface creates a capability stream; any other first frame begins a control
session.
hud/environment/server.py · bind
The suspended task
bind creates one _ControlChannel for the served environment. That channel
owns one suspended TaskRunner per session id. A session’s tasks.start
replaces its runner, tasks.grade consumes it, and tasks.cancel removes it.
hud/environment/server.py · _ControlChannel
hellowith itssession_idresumes that exact parked session.- A plain
tasks.gradeadopts a parked runner only when exactly one exists.
no task in progress; multiple parked runners
produce an ambiguity error that names their session ids. This is the channel
mechanism behind split hud task start and hud task grade invocations.
Capability streams
A capability binding describes a backing daemon inside the environment’s substrate. The agent reaches that daemon through a second connection to the control address. Its first frame names the capability: The server resolves the named binding, opens its host and port, sends the one reply frame, and splices both byte streams until either side closes:hud/environment/server.py · _stream
tunnel.open connection carries one capability stream. Opening a shell and
a browser at the same time therefore creates two independent stream
connections alongside the control-session connection.
Client-side routes
connect(Runtime(url)) gives HudClient the control endpoint. During hello,
the client creates one loopback forwarder for every returned binding. Each
forwarder accepts local connections, opens a tunnel.open connection to the
control endpoint, and splices the local client to that tunnel.
hud/clients/client.py · HudClient.hello
binding(ref) returns the capability with its routed local URL.
open(ref) resolves that same binding, constructs the registered protocol
client, and caches it for the life of the HudClient. All external capability
traffic therefore follows the control address even when a manifest binding
contains a substrate-local or otherwise unreachable address.
The walkthrough places the handshake and
forwarders on the execution path. Placement explains
how the runtime behind the control address is selected and provisioned.