architecture

Agent Service (the polyglot boundary)

The localhost HTTP/SSE contract that lets any language register as a Manifoldone agent runtime.

What the Agent Service is

The Agent Service is the local process that actually runs agents on a Node. The Node is now two layers: a shared TS adapter that owns the outbound relay WebSocket and the wire protocol, and a local Agent Service the adapter calls over localhost HTTP/SSE. Agent execution does not live inside the daemon embed anymore — it lives behind this API.

The point of splitting it out is polyglot: the Agent Service is a contract, not a language. The TypeScript reference implementation ships first (@manifoldone/agent-service), but anything that honors the HTTP shape below can register as a node — a Python runner, a Go binary, a thin shim around a vendor CLI. If it speaks the contract, the adapter can drive it.

The contract — six endpoints

The service binds to 127.0.0.1 only (never exposed to the network; the adapter is the only client) on port 8790 by default (MANIFOLDONE_AGENT_SERVICE_PORT).

MethodPathPurpose
GET/capabilitiesWhich agent kinds this machine can run (claude / codex / gemini), detected from what’s installed.
POST/executeStart a turn on a session — the adapter hands over the prompt and agent kind.
GET/sessions/:id/streamServer-Sent Events: live token deltas, tool uses, and the turn’s lifecycle.
POST/sessions/:id/respondFeed a mid-turn response back (e.g. answering an agent’s question).
GET/sessions/:idSnapshot the current session state.
POST/sessions/:id/interruptStop the in-flight turn.

Why this is the registration boundary

GET /capabilities is how a machine announces what it can be. The adapter probes it on boot, reconciles the result against the relay’s roster (mint a new agent / match an existing one / mark offline), and re-announces on every dashboard reconnect. So “add a new runtime” is not a code change in the adapter — it’s a new Agent Service that returns its kind from /capabilities and honors /execute + /sessions/:id/stream.

Where execution moved

Before the redesign, the daemon embedded a single Claude Code instance via the vendor Agent SDK — one runtime, hard-wired. Now the adapter is runtime-agnostic and the Agent Service owns execution. The user picks the agent per turn, like a model selector (next-turn semantics; mid-turn swap is out of scope). See Node for the two-layer picture and the System Diagram for how it sits in the topology.