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).
| Method | Path | Purpose |
|---|---|---|
GET | /capabilities | Which agent kinds this machine can run (claude / codex / gemini), detected from what’s installed. |
POST | /execute | Start a turn on a session — the adapter hands over the prompt and agent kind. |
GET | /sessions/:id/stream | Server-Sent Events: live token deltas, tool uses, and the turn’s lifecycle. |
POST | /sessions/:id/respond | Feed a mid-turn response back (e.g. answering an agent’s question). |
GET | /sessions/:id | Snapshot the current session state. |
POST | /sessions/:id/interrupt | Stop 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.