Both modes verified against the live server, not reasoned about. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
70 lines
3.9 KiB
Markdown
70 lines
3.9 KiB
Markdown
---
|
|
id: sub-agents/an-api-endpoint-for-spawning-an-agent-with-a
|
|
title: 'An API endpoint for spawning an agent with a prompt'
|
|
theme: sub-agents
|
|
status: done
|
|
created: 2026-08-21
|
|
date_source: stated
|
|
order: 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.
|