Files
platform/todo/sub-agents/an-api-endpoint-for-spawning-an-agent-with-a.md
pastilhasandClaude Opus 5 9b0376ec39 todo: close the spawning endpoint
Both modes verified against the live server, not reasoned about.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 05:02:45 +00:00

3.9 KiB

id, title, theme, status, created, date_source, order
id title theme status created date_source order
sub-agents/an-api-endpoint-for-spawning-an-agent-with-a An API endpoint for spawning an agent with a prompt sub-agents done 2026-08-21 stated 1

An API endpoint for spawning an agent with a prompt. Wanted 2026-08-21. An agent calls it, names a prompt, and gets another agent running. A sub-agent system — but defined by the owner, which is the whole point of building one rather than leaning on the harness's own: the shapes, the limits and the vocabulary are Officer's, so every harness gets the same door and the definition does not change when a CLI does.

It has more of a starting point than it looks. startClaudeTurn already runs a turn with no browser attached (nudger.ts:102, ws: null), so the mechanism for "run an agent from the backend" is proven — what is missing is spawning a NEW one on request rather than feeding a known session, plus the surface an agent can actually call, which is MCP or an authenticated route.

Open: whether a spawned agent is a Command HQ commander (named, listed, costed — command_hq_sessions already does all three) or something lighter that disappears when it finishes; how its output returns to the caller, streamed or awaited; and what the caller may set — model, effort, cwd, permission mode — versus what Officer fixes.

Bounded by the budget rule in sub-agents/spawning-must-respect-the-account-s-own, which is not optional. An endpoint that spawns freely is exactly how a weekly limit gets spent by something nobody was watching.


2026-08-21, narrowing this considerably. The endpoint largely exists: POST /api/command-hq/commanders/new takes a prompt, starts a turn with ws: null, waits only for session:claude rather than the whole turn, and returns Claude's own transcript id. A commander is named, listed and costed by command_hq_sessions already.

So the open question "commander or something lighter" answers itself from the code: making a spawned agent a commander costs nothing and gets all three for free, where a lighter thing needs its own registry to become visible at all. The budget condition is now on that route, so anything spawned through it already respects the window.

What is genuinely left is the SURFACE an agent can call — MCP tool or authenticated route — and how output returns to the caller. That is the remaining work on this item; the mechanism underneath it is done.


Closed 2026-08-23. POST /api/sub-agents/spawn — prompt, optional cwd and model, and either the session key immediately or the result if you ask it to wait. GET /api/sub-agents/budget answers whether there is room without consuming any.

Verified both modes against the live server rather than reasoned about: the synchronous call returned the four words the agent was told to say, and the async call returned in milliseconds with the agent's file on disk five seconds later.

Three things settled while building it, each worth not re-deriving:

  • The budget check is a precondition, not a refinement. It runs before the spawn and refuses 429 naming the window. checkBudget() already existed and was already tested, which is the only reason this was a short job.
  • confined, and true on the day it shipped. The registry test's own comment records that chat sat on that list for a day before its turns actually ran as the member. This one inherits the mechanism rather than claiming it — chatIdentity off the token, member: { osUser, home } to the sidecar — and no path in the endpoint chooses a directory.
  • member is passed explicitly, never omitted. The field is required-but-may-be-undefined on purpose: optional let a call site forget it, and forgetting it means a member's agent running as the owner in the owner's home.

What it deliberately is not: a queue, a supervisor, or a retry. One call starts one agent.