hive-subagent-mcp: name a role at dispatch, load it as the system prompt
A `start` may now name a role: `role: "reviewer"` loads the spawning agent's own `subagent_roles/reviewer.md` and renders it, alone, into one per-session file that `--append-system-prompt-file` points at. The role is the system prompt; the task is the turn, never the other way round — a task baked into the system prompt would re-assert itself as an instruction on every later turn of a continued session, not just the one it was written for. The task instructions (`prompt_file`) are read and folded ahead of the turn's own prompt instead, the same channel that carries them to the subagent without a role. The argument is optional, so every existing call is unchanged — pinned by a test that a pre-role payload still deserializes with `role` absent from the schema's required set, and another that the no-role path reaches claude with the caller's own file, unrendered, and the trigger untouched. With a role, one test pins the system-prompt file to the role's text and nothing of the task, and another pins the task still reaching the subagent as the turn's prompt. A role name with no file fails the call, before the session name is even reserved, and the error lists the roles the directory does hold. No agent ships roles yet, so named-but-missing is the ordinary first-run state; a fallback there would spawn a subagent under a prompt missing every clause the role existed to carry. An empty file and a name that is not a plain identifier refuse the same way.
This commit is contained in:
parent
aaedff20a9
commit
657875b2fa
6 changed files with 545 additions and 11 deletions
|
|
@ -71,6 +71,48 @@ after a restart has to re-supply `dir` when the session lives anywhere
|
|||
other than the daemon's own working directory — and a restart is the
|
||||
situation you reach for `continue` in most often.
|
||||
|
||||
## Roles
|
||||
|
||||
A `start` may name a **role**: `role: "reviewer"` runs that subagent under
|
||||
the spawning agent's own `reviewer.md`. Role files live in one directory
|
||||
per agent, `subagent_roles/` inside that agent's state directory, one
|
||||
markdown file per role, and the `role` argument is the filename without
|
||||
its extension.
|
||||
|
||||
One convention directory of named files, because a named set enumerates.
|
||||
Anything that watches roles — a check for a safety clause that has gone
|
||||
stale, an operator asking what this agent can dispatch — lists the
|
||||
directory and has the answer. Per-agent rather than hive-wide: the clauses
|
||||
a role carries come out of that one agent's own prompt files, and the
|
||||
daemon only ever spawns on that agent's behalf.
|
||||
|
||||
**The role is the system prompt; the task is the turn — never the other
|
||||
way round.** The daemon writes the named role's text, alone, into a
|
||||
per-session file under the harness directory and points
|
||||
`--append-system-prompt-file` at it — nothing about the task reaches that
|
||||
file. It reads the task instructions (`prompt_file`) and folds them ahead
|
||||
of the turn's own prompt instead, the same channel that carries them to
|
||||
the subagent without a role. A task baked into the system prompt would
|
||||
re-assert itself as an instruction on every later turn of the session, not
|
||||
just the one the caller wrote it for — the system prompt is the
|
||||
subagent's standing identity, not a one-shot channel. The caller's own
|
||||
task file stays untouched either way.
|
||||
|
||||
### A role with no file refuses the call
|
||||
|
||||
A named role with no file **fails the `start`** and names the roles the
|
||||
directory does hold. No fallback, no spawn, no reservation — the refusal
|
||||
lands before the daemon claims the session name, so a caller that fixes
|
||||
the name may retry it immediately.
|
||||
|
||||
The reason is the state every agent starts in. The directory starts
|
||||
empty: hyperhive ships no role files, and nothing creates one until an
|
||||
agent writes its own, so a name with no file behind it counts as the
|
||||
ordinary first-run answer rather than a rare corruption. Falling back to a spawn
|
||||
without the role would hand that subagent a prompt missing every clause
|
||||
the role existed to carry, and would do it quietly. An empty role file
|
||||
draws the same refusal, for the same reason.
|
||||
|
||||
## Goals, and turns toward them
|
||||
|
||||
`start` takes an optional `goal`. Without one a session is a single turn,
|
||||
|
|
|
|||
Loading…
Reference in a new issue