agent-backend#
The live edge of the Clover Agent stack. A detached worker owns each provider session and durable recording. The backend attaches those workers to HTTP and WebSocket clients, so restarting the backend does not restart an active Claude or Codex harness. Sessions are reused by id; each client keeps its own selection while the user profile and workspace presence are pushed to every window.
provider ⇄ detached session worker ⇄ backend ⇄ extension host ⇄ webview
Run it#
# terminal 1 — backend (spawns a real claude session)
AGENT_CWD=/path/to/repo pnpm --filter agent-backend serve
# terminal 2 — UI (vite proxies /api → :8787)
pnpm --filter agent-ui dev
Open the vite URL, switch source → live (model), and message the agent.
| env | default | note |
|---|---|---|
PORT |
8787 |
http/SSE port |
AGENT_CWD |
process.cwd() |
the session's working dir — where the model reads/edits |
AGENT_BACKEND_RECORD |
— | backend process discovery record written after listen |
AGENT_USER_PROFILE |
— | backend-owned durable user profile |
AGENT_SESSION_WORKER_ENTRY |
source entry | packaged detached worker entry |
Submits run in auto mode. Resolving interaction cards (question/permission/plan) rides the
respond client message and is not wired yet — a turn that gates will sit waiting.
HTTP#
GET /api/health?client=ID—{ ok, session, model, cwd }for that clientGET /api/events?client=ID— SSEServerMessagestream for the client's selected sessionPOST /api/message?client=ID— aClientMessagerouted to that selectionPOST /api/client?client=ID— register that window's workspace and model defaults
Extension WebSocket#
GET /api/socket?client=ID&cwd=PATHupgrades to the window's sole backend connection.- The first frame is
backend.hello, a complete resync tied toinstanceIdandrevision. - Session index, user profile, workspace presence, service status, and selected-session messages
are pushed as entity events. Commands return
command.resultorcommand.errorby request id. - The webview has no loopback network permission. The extension host forwards the selected-session
stream and local editor state over
postMessage.
Client identity belongs to the transport, not agent-protocol: two windows can select different
sessions without receiving each other's deltas, while clients selecting the same session share its
one provider session and both receive the same stream.