feat(missions): Slice 3 — agent teams behind a per-mission switch, solo by default
`missions.team_engine` (0069): NULL = solo, `'claude_code'` = Claude Code agent teams inside the mission's VM. Solo stays the default deliberately — Anthropic measure multi-agent at 3-10x the tokens with wall-clock often LONGER, since the benefit is thoroughness rather than speed — so a mission that said nothing does not get a team. In-process teammates live in the lead's process, so ONE VM hosts the whole team. That is why this is a prompt-and-env change rather than an orchestration one: no N-VM fan-out, no placement per teammate, no new completion path. The lead decides its own team size and there is no flag that limits it, so the cap (4) is stated in the prompt. The addendum also carries the two anti-patterns from Anthropic's guidance, because they are exactly the shapes our pipeline templates have: teammates must own DIFFERENT FILES (two in one file overwrite each other), and one change must not be split into stages across teammates (a handoff loses context at every step). And: wait for your teammates — a summary written before they report is the lead's own guess. A solo mission's prompt and env are byte-identical to before this change. That is enforced by test, not by intention: the comparison between solo and team is only meaningful if the solo side did not also move. Evidence, because a team mission that forms no team is silently just a solo run that looked fine and spent fewer tokens: a second probe counts members in `~/.claude/teams/*/config.json` (minus the lead), reported separately from the subagent count, and a team mission with zero teammates logs loudly with the two likely causes. The teammate path is DOCUMENTED BUT NOT YET VERIFIED in our image, unlike the subagent transcript path which was measured — so a zero there means "no evidence found", and the first real team mission is what turns it into a fact. `Option<u32>`: None means no team was asked for or the probe could not run. Hooks (`TaskCompleted` / `TeammateIdle` exit 2, which would move `done_when` from post-hoc into the agent's own loop) are the highest-value part of this slice and are deliberately NOT here — they deserve their own pass rather than a rushed tail. 482 tests pass, clippy clean.
This commit is contained in:
@@ -45,6 +45,9 @@ pub struct CreateMissionRequest {
|
||||
/// `glm:glm-4.7`. Omit to use the deployment default; send `""` to opt out of
|
||||
/// independent validation and judge with the house model.
|
||||
pub validator_model: Option<String>,
|
||||
/// Team engine: `"claude_code"` asks the mission's agent to form a team.
|
||||
/// Omit for solo, which is the default and much cheaper.
|
||||
pub team_engine: Option<String>,
|
||||
}
|
||||
|
||||
fn default_schedule() -> Value {
|
||||
@@ -290,6 +293,7 @@ pub async fn create(
|
||||
target_node_id: body.target_node_id,
|
||||
backend: body.backend.as_deref(),
|
||||
validator_model: body.validator_model.as_deref(),
|
||||
team_engine: body.team_engine.as_deref(),
|
||||
phases: phases_for_create(
|
||||
crate::workflow_registry::get(body.template_kind.trim()),
|
||||
body.phases,
|
||||
|
||||
Reference in New Issue
Block a user