master planner: add 'Team' mode + size bands per mode
Modes now: specialists (2–3 domain experts, deep prompts) · team (4–8 balanced roles, coordinator + complements) · swarm (10+ workers, self- verifying loop) · scheduled (ephemeral, cron/one-shot) · triggered (ephemeral, webhook). Backend planner_system_for() gains a TEAM_NOTE using PLANNER_SYSTEM; specialists / scheduled / triggered notes are rewritten to bake in the size + ephemeral guidance. Swarm's system prompt now targets task_count>=10 explicitly. Frontend MODES / INTRO copy match. Chat-preserving switchMode from the prior commit handles the new mode transparently — no state-plumbing changes needed.
This commit is contained in:
@@ -51,30 +51,38 @@ pub struct PlannerMessage {
|
|||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct PlannerChatRequest {
|
pub struct PlannerChatRequest {
|
||||||
pub messages: Vec<PlannerMessage>,
|
pub messages: Vec<PlannerMessage>,
|
||||||
/// Deploy mode: specialists | swarm | scheduled | triggered (default specialists).
|
/// Deploy mode: specialists | team | swarm | scheduled | triggered (default specialists).
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub mode: String,
|
pub mode: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
const SPECIALISTS_NOTE: &str = "\n\nMODE: Specialists. Each member is a DOMAIN SPECIALIST — set each member's \
|
const SPECIALISTS_NOTE: &str = "\n\nMODE: Specialists. Propose a TIGHTLY-SCOPED group of 2 or 3 DOMAIN \
|
||||||
brain_query to a concrete domain brain keyword (e.g. 'rust-2024', 'react-native', 'pentest-web', 'db-ops').";
|
SPECIALISTS with high-quality, focused system_prompts. Each member's brain_query MUST be a concrete domain \
|
||||||
const SCHEDULED_NOTE: &str = "\n\nMODE: Scheduled. Include a schedule in the proposal. Recurring: \
|
brain keyword (e.g. 'rust-2024', 'react-native', 'pentest-web', 'db-ops'). Prefer depth over breadth.";
|
||||||
{\"cron\":\"<5-field>\",\"prompt\":\"<mission run each cycle>\"}. One-time: \
|
const TEAM_NOTE: &str = "\n\nMODE: Team. Propose a balanced team of 4 to 8 agents that covers the goal \
|
||||||
{\"one_shot_at\":\"<RFC3339 UTC datetime>\",\"prompt\":\"<mission>\"}.";
|
end-to-end — a coordinator plus complementary roles. Bias toward roles that will actually be exercised each \
|
||||||
const TRIGGERED_NOTE: &str =
|
iteration; do not pad. Each member's brain_query should be a keyword the brain registry can resolve.";
|
||||||
"\n\nMODE: Triggered. The team will be fired by a webhook on demand. Set the \
|
const SCHEDULED_NOTE: &str = "\n\nMODE: Scheduled. Propose a team (2–8 agents is typical) and INCLUDE a \
|
||||||
schedule field to {\"prompt\":\"<the default task the webhook runs>\"} (NO cron / one_shot_at).";
|
schedule in the proposal. Recurring: {\"cron\":\"<5-field>\",\"prompt\":\"<mission run each cycle>\"}. \
|
||||||
|
One-time: {\"one_shot_at\":\"<RFC3339 UTC datetime>\",\"prompt\":\"<mission>\"}. The team is EPHEMERAL — \
|
||||||
|
provisioned at fire time and destroyed after the run — so keep member count tight.";
|
||||||
|
const TRIGGERED_NOTE: &str = "\n\nMODE: Triggered. Propose a team the user can fire by hitting a webhook \
|
||||||
|
(with a JSON payload the mission can reference). The team is EPHEMERAL — spun up on receipt, torn down when \
|
||||||
|
the run terminates — so keep the roster tight. Set schedule to {\"prompt\":\"<default task the webhook \
|
||||||
|
runs>\"} (NO cron / one_shot_at).";
|
||||||
const SWARM_SYSTEM: &str = "You are the planner for a self-verifying agent SWARM (Opus plans + verifies, a worker \
|
const SWARM_SYSTEM: &str = "You are the planner for a self-verifying agent SWARM (Opus plans + verifies, a worker \
|
||||||
swarm executes, the loop repeats until every output passes). The user describes a job; you turn it into a swarm \
|
swarm executes, the loop repeats until every output passes). Swarms are for BIG parallel jobs — target 10 or more \
|
||||||
spec. The CHECKLIST is the verification contract — each item must be objectively checkable per task (e.g. 'states \
|
workers (`task_count >= 10`). The user describes a job; you turn it into a swarm spec. The CHECKLIST is the \
|
||||||
a revenue figure', 'cites a resolvable source URL', 'no field left empty'). Have a brief conversation, then emit \
|
verification contract — each item must be objectively checkable per task (e.g. 'states a revenue figure', 'cites \
|
||||||
the spec. ALWAYS respond with STRICT JSON ONLY: {\"reply\":\"<concise message>\",\"swarm\":null|{\"goal\":\"<the \
|
a resolvable source URL', 'no field left empty'). Have a brief conversation, then emit the spec. ALWAYS respond \
|
||||||
decomposable job>\",\"checklist\":[\"...\",\"...\"],\"task_count\":<int>,\"worker_model\":\"auto\"}}. Set swarm to \
|
with STRICT JSON ONLY: {\"reply\":\"<concise message>\",\"swarm\":null|{\"goal\":\"<the decomposable job>\",\
|
||||||
null while still clarifying; include it once the job + checklist are concrete.";
|
\"checklist\":[\"...\",\"...\"],\"task_count\":<int>,\"worker_model\":\"auto\"}}. Set swarm to null while still \
|
||||||
|
clarifying; include it once the job + checklist are concrete.";
|
||||||
|
|
||||||
fn planner_system_for(mode: &str) -> String {
|
fn planner_system_for(mode: &str) -> String {
|
||||||
match mode {
|
match mode {
|
||||||
"swarm" => SWARM_SYSTEM.to_string(),
|
"swarm" => SWARM_SYSTEM.to_string(),
|
||||||
|
"team" => format!("{PLANNER_SYSTEM}{TEAM_NOTE}"),
|
||||||
"scheduled" => format!("{PLANNER_SYSTEM}{SCHEDULED_NOTE}"),
|
"scheduled" => format!("{PLANNER_SYSTEM}{SCHEDULED_NOTE}"),
|
||||||
"triggered" => format!("{PLANNER_SYSTEM}{TRIGGERED_NOTE}"),
|
"triggered" => format!("{PLANNER_SYSTEM}{TRIGGERED_NOTE}"),
|
||||||
_ => format!("{PLANNER_SYSTEM}{SPECIALISTS_NOTE}"),
|
_ => format!("{PLANNER_SYSTEM}{SPECIALISTS_NOTE}"),
|
||||||
|
|||||||
@@ -11,18 +11,20 @@ import { Activity, CalendarClock, Send, Sparkles, Users, Webhook } from "lucide-
|
|||||||
|
|
||||||
const mono = "'JetBrains Mono', ui-monospace, monospace";
|
const mono = "'JetBrains Mono', ui-monospace, monospace";
|
||||||
|
|
||||||
type Mode = "specialists" | "swarm" | "scheduled" | "triggered";
|
type Mode = "specialists" | "team" | "swarm" | "scheduled" | "triggered";
|
||||||
const MODES: { key: Mode; label: string; hint: string }[] = [
|
const MODES: { key: Mode; label: string; hint: string }[] = [
|
||||||
{ key: "specialists", label: "Specialists", hint: "domain experts" },
|
{ key: "specialists", label: "Specialists", hint: "2–3 domain experts" },
|
||||||
{ key: "swarm", label: "Swarm", hint: "self-verifying loop" },
|
{ key: "team", label: "Team", hint: "4–8 agents, balanced" },
|
||||||
{ key: "scheduled", label: "Scheduled", hint: "date / time" },
|
{ key: "swarm", label: "Swarm", hint: "10+ workers, self-verifying" },
|
||||||
{ key: "triggered", label: "Triggered", hint: "webhook" },
|
{ key: "scheduled", label: "Scheduled", hint: "ephemeral · date/time" },
|
||||||
|
{ key: "triggered", label: "Triggered", hint: "ephemeral · webhook" },
|
||||||
];
|
];
|
||||||
const INTRO: Record<Mode, string> = {
|
const INTRO: Record<Mode, string> = {
|
||||||
specialists: "Describe what you need — e.g. “a team of specialists for a React Native app: a Rust backend expert, a RN UI dev, and a release engineer.”",
|
specialists: "Describe what you need — e.g. “a group of 2–3 specialists for a React Native app: a Rust backend expert, a RN UI dev, and a release engineer.” I'll write high-quality prompts for each.",
|
||||||
swarm: "Describe a job to verify-loop — e.g. “analyze 100 EV companies; every figure needs a resolvable source URL.” I'll turn it into a checklist the verifier enforces.",
|
team: "Describe the goal — e.g. “build me a 4–6 person growth team: a coordinator, a researcher, a writer, an analyst, and a critic.” I'll pick roles that actually get exercised each iteration.",
|
||||||
scheduled: "Describe a team and when it should run — e.g. “a market-news digest team, every weekday at 7am.”",
|
swarm: "Describe a job to verify-loop across 10+ workers — e.g. “analyze 100 EV companies; every figure needs a resolvable source URL.” I'll turn it into a checklist the verifier enforces.",
|
||||||
triggered: "Describe a team to fire from a webhook — e.g. “when a support ticket arrives, triage and draft a reply.”",
|
scheduled: "Describe a team and when it should run — e.g. “a market-news digest team, every weekday at 7am.” The team is spun up at fire time and torn down after.",
|
||||||
|
triggered: "Describe a team to fire from a webhook — e.g. “when a support ticket arrives, triage and draft a reply.” The team is ephemeral — created on webhook receipt, destroyed after.",
|
||||||
};
|
};
|
||||||
|
|
||||||
type Member = { name: string; role: string; model: string; rationale?: string };
|
type Member = { name: string; role: string; model: string; rationale?: string };
|
||||||
|
|||||||
Reference in New Issue
Block a user