Agent Relay separates what a message means from where it is delivered. Messaging writes a durable record; delivery gets that record into a session. This page describes the delivery side end to end: the node and provider model, the agent runtime that hosts sessions on a machine, and how spawn flows through the engine.
The engine is the hub
A node is an enrolled context in a workspace — usually a project directory, sometimes an
application. Providers attach to a node: each is a process that connects directly to the engine
over /v1/node/ws, shares the node's token, and registers a subset of the node's capabilities. The
engine is the only hub; there is no local one.
Realtime delivery is node-only and reliable: each agent has a per-agent sequence, and the
provider that owns an agent acknowledges deliveries so the engine can replay anything unacked after a
reconnect. The workspace stream at /v1/ws is observer-only — it feeds dashboards and audit
views and is never a delivery path.
Providers on a node
A node's abilities are split across its providers, each connecting to the engine on its own:
engine (cast.agentrelay.com)
├─ /v1/node/ws ← agent runtime (Rust) — spawn:*, release, agent delivery
├─ /v1/node/ws ← capability provider (TS) — project agent-relay.ts actions
├─ /v1/node/ws ← capability provider (py) — project agent-relay.py actions
└─ /v1/node/ws ← app provider (Swift) — its own nodeagent runtime — the Rust provider that spawns and owns agent processes (PTYs). It registers the
node's capacity (spawn:<harness>, release) and the agents it hosts, receives deliver frames
for those agents, and heartbeats its own load. It owns a generic PTY engine that reads, writes,
injects deliveries into, and tears down agent processes; it is harness-agnostic, with no per-CLI logic
baked in.
capability provider — a process in TypeScript, Python, or Swift that registers actions: named
handlers the engine dispatches to it. A capability that needs to spawn an agent calls the engine's
placement through ctx.spawnAgent, which lands on an agent runtime — it never tunnels through a local
process.
@agent-relay/harness-driver — the client SDK for the agent runtime's PTY engine, used to spawn a
PTY ({ command, args, env }) and drive it.
Capabilities, capacity, and placement
Providers register two kinds of capability. An action is an invokable handler; the engine
materializes it and dispatches invokes to the registering provider. Capacity — spawn:<harness>
and release — is what the node can run; the agent runtime registers it for placement and delegation,
and it is never materialized as an action.
Invocation is node-addressed: POST /v1/nodes/:node/actions/:name/invoke resolves the capability to
its provider and sends action.invoke down that socket. The provider replies
action.result { invocation_id, output | error }, delivered back to the calling agent as the
action's completion. See Nodes and providers for the model and
Nodes for placement and the node API.
Delivery flow
A message travels from the engine to an agent's session like this:
- The engine sends
deliver { delivery_id, agent_id, seq, payload }over/v1/node/wsto the provider that owns the agent — its agent runtime. - The agent runtime injects it into the agent's PTY.
- The runtime acks with
delivery.ack { agent, up_to_seq }.
Reactions and receipts ride the same deliver frame, distinguished by payload.type
(message.reacted / message.read).
Spawn flow
Spawning an agent runs through capacity. The request carries the harness or cli, a name, an
optional target_node, and optional harnessConfig — not a raw command to run:
- The engine places the spawn on a node whose agent runtime advertises the harness and sends
action.invoke(spawn:…). - The agent runtime resolves the harness and spawns the PTY.
- The new agent registers through the node, so it is born bound to that node, and the runtime
replies
action.result.
Because the agent is node-bound, its future deliveries route back to the agent runtime that spawned
it — closing the loop with the delivery flow above. A spawn carrying a session id resumes the agent on
its origin node. Release invokes the release capacity on the owning node.
A provider can register an action named spawn:<harness> that shadows native capacity: the engine
routes spawn invokes for that harness to the handler, which mutates the spec and delegates via
ctx.spawnAgent. The delegation addresses capacity directly, so a shadow never re-enters itself, and
while it is registered the native capacity is reachable only through it.
Vocabulary
| Term | Meaning |
|---|---|
| node | an enrolled context in a workspace (a project directory or an application) |
| provider | a process attached to a node that connects directly to the engine and registers capabilities |
| agent runtime | the Rust provider that owns PTYs and registers the node's spawn/release capacity |
| capability provider | a per-language provider that registers invokable actions |
| @agent-relay/harness-driver | client SDK for the agent runtime's PTY engine |
| capacity | what a node can run (spawn:<harness>, release); feeds placement, never invoked |
| action | an invokable capability with a handler hosted by a provider |
| invoke | calling an action (POST /v1/nodes/:node/actions/:name/invoke) |
Nodes and providers
The node, provider, and capability model, with onboarding.
Nodes
Provider registration, placement, delivery kinds, and the node API.
Delivery
Durable delivery records, receipts, retries, and delivery modes.
Harness driver package
The client SDK that drives the agent runtime's PTY engine.