@deeflectcom/smart-spawn 1.0.4 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -30,6 +30,7 @@ Just use your agent normally. Smart Spawn adds a `smart_spawn` tool that the age
30
30
  - **Single** — Pick the best model, spawn one agent
31
31
  - **Collective** — Pick N diverse models, run in parallel, merge results
32
32
  - **Cascade** — Start cheap, escalate to premium if needed
33
+ - **Plan** — Decompose sequential multi-step tasks and assign best model per step
33
34
  - **Swarm** — Decompose complex tasks into a DAG of sub-tasks with optimal model per step
34
35
 
35
36
  ## Configuration
@@ -48,9 +49,10 @@ Optional — add to your OpenClaw config under `plugins.entries.smart-spawn.conf
48
49
  |---------|---------|---------|
49
50
  | `apiUrl` | `https://ss.deeflect.com/api` | Your own API URL if self-hosting |
50
51
  | `defaultBudget` | `medium` | `low`, `medium`, `high`, `any` |
51
- | `defaultMode` | `single` | `single`, `collective`, `cascade`, `swarm` |
52
+ | `defaultMode` | `single` | `single`, `collective`, `cascade`, `plan`, `swarm` |
52
53
  | `collectiveCount` | `3` | Number of models for collective mode (2-5) |
53
54
  | `telemetryOptIn` | `false` | Opt-in to anonymous community telemetry |
55
+ | `communityUrl` | `apiUrl` | Community API URL for shared telemetry |
54
56
 
55
57
  ## How It Works
56
58
 
package/index.ts CHANGED
@@ -434,7 +434,7 @@ export default function (api: any) {
434
434
  }
435
435
 
436
436
  // Build plan response with routed models
437
- const subtasks = decomposition.steps.map((step) => {
437
+ const subtasks = await Promise.all(decomposition.steps.map(async (step) => {
438
438
  const modelId = step.model
439
439
  ? routeModel(step.model.id, directProviders)
440
440
  : getFallback(step.category);
@@ -449,8 +449,14 @@ export default function (api: any) {
449
449
  context,
450
450
  });
451
451
 
452
- // Plan mode steps use task as-is — blocks are top-level only
453
- const stepTask = step.task;
452
+ const stepTask = await client.composeTaskPrompt({
453
+ task: step.task,
454
+ persona: input.persona,
455
+ stack: input.stack,
456
+ domain: input.domain,
457
+ format: input.format,
458
+ guardrails: input.guardrails,
459
+ }) ?? step.task;
454
460
 
455
461
  return {
456
462
  step: step.step,
@@ -461,7 +467,7 @@ export default function (api: any) {
461
467
  reason: step.reason,
462
468
  label: `smart-spawn-plan-${step.step}: ${step.category} (${modelId.split("/").pop()})`,
463
469
  };
464
- });
470
+ }));
465
471
 
466
472
  return {
467
473
  content: [{
@@ -523,7 +529,7 @@ export default function (api: any) {
523
529
 
524
530
  // Build swarm response with routed models
525
531
  const dag = swarmResult.dag;
526
- const dagTasks = dag.tasks.map((t) => {
532
+ const dagTasks = await Promise.all(dag.tasks.map(async (t) => {
527
533
  const modelId = t.model
528
534
  ? routeModel(t.model.id, directProviders)
529
535
  : getFallback(t.category);
@@ -538,9 +544,18 @@ export default function (api: any) {
538
544
  context,
539
545
  });
540
546
 
547
+ const swarmTask = await client.composeTaskPrompt({
548
+ task: t.description,
549
+ persona: input.persona,
550
+ stack: input.stack,
551
+ domain: input.domain,
552
+ format: input.format,
553
+ guardrails: input.guardrails,
554
+ }) ?? t.description;
555
+
541
556
  return {
542
557
  id: t.id,
543
- task: t.description,
558
+ task: swarmTask,
544
559
  category: t.category,
545
560
  model: modelId,
546
561
  budget: t.budget,
@@ -550,7 +565,7 @@ export default function (api: any) {
550
565
  reason: t.reason,
551
566
  label: `smart-spawn-${t.id}: ${t.category} (${modelId.split("/").pop()})`,
552
567
  };
553
- });
568
+ }));
554
569
 
555
570
  return {
556
571
  content: [{
@@ -2,7 +2,7 @@
2
2
  "id": "smart-spawn",
3
3
  "name": "Smart Spawn",
4
4
  "description": "Intelligent sub-agent spawning with automatic model selection, role composition, and multi-agent orchestration.",
5
- "version": "1.1.0",
5
+ "version": "1.0.5",
6
6
  "author": "deeflect",
7
7
  "skills": ["skills/smart-spawn"],
8
8
  "configSchema": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deeflectcom/smart-spawn",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Intelligent sub-agent spawning with automatic model selection for OpenClaw",
5
5
  "main": "index.ts",
6
6
  "type": "module",
@@ -22,5 +22,5 @@
22
22
  "url": "https://github.com/deeflect/smart-spawn.git",
23
23
  "directory": "smart-spawn"
24
24
  },
25
- "homepage": "https://github.com/deeflect/smart-spawn#readme"
25
+ "homepage": "https://ss.deeflect.com"
26
26
  }
@@ -68,11 +68,12 @@ This is the OpenClaw built-in tool you call AFTER smart_spawn:
68
68
  ## Role Blocks (Optional)
69
69
 
70
70
  You can hint what kind of expert is needed. **Only include what's clearly relevant — omit if unsure.** The API enriches the task prompt with expert context.
71
+ Under the hood this uses `POST /api/roles/compose` before model routing.
71
72
 
72
73
  ### persona — who the sub-agent should be
73
74
  `software-engineer` `frontend-engineer` `backend-engineer` `devops-engineer` `data-engineer` `ml-engineer` `architect` `analyst` `writer` `technical-writer` `product-manager` `debugger` `ui-designer` `sysadmin` `assistant`
74
75
 
75
- ### stack — tech expertise (array, max 4)
76
+ ### stack — tech expertise (array; include only relevant blocks)
76
77
  `react` `nextjs` `typescript` `python` `rust` `go` `nodejs` `postgres` `redis` `docker` `kubernetes` `aws` `tailwind` `llm` `rag` (and many more)
77
78
 
78
79
  ### domain — industry context (one)
package/skills/SKILL.md DELETED
@@ -1,214 +0,0 @@
1
- # Smart Spawn
2
-
3
- When delegating tasks to sub-agents, prefer `smart_spawn` over `sessions_spawn` unless:
4
- - The user explicitly requests a specific agent or model
5
- - You're doing a trivial task where you already know the right model
6
-
7
- ## How It Works
8
-
9
- `smart_spawn` returns a **JSON response** with a recommended model and action. You MUST then call `sessions_spawn` yourself with the recommended model and task. The tool cannot spawn directly — it only recommends.
10
-
11
- ## Handling Responses
12
-
13
- After calling `smart_spawn`, parse the JSON response and act on the `action` field:
14
-
15
- ### action: "spawn" (single mode)
16
-
17
- The tool picked one model. Spawn it:
18
-
19
- ```json
20
- {
21
- "action": "spawn",
22
- "model": "openrouter/anthropic/claude-opus-4-6",
23
- "task": "...",
24
- "category": "coding",
25
- "budget": "medium",
26
- "reason": "Best coding model at medium budget ($0-5/M) — score: 82",
27
- "source": "api",
28
- "label": "smart-spawn: coding (claude-opus-4-6)"
29
- }
30
- ```
31
-
32
- **You do:** Call `sessions_spawn` with the `model`, `task`, and `label` from the response.
33
-
34
- ### action: "collective"
35
-
36
- The tool picked N diverse models. Spawn all of them on the same task, then merge:
37
-
38
- ```json
39
- {
40
- "action": "collective",
41
- "models": [
42
- { "id": "openrouter/anthropic/claude-opus-4-6", "reason": "...", "label": "smart-spawn-collective-1: coding (claude-opus-4-6)" },
43
- { "id": "openrouter/google/gemini-2.5-pro", "reason": "...", "label": "smart-spawn-collective-2: coding (gemini-2.5-pro)" }
44
- ],
45
- "task": "...",
46
- "category": "coding",
47
- "budget": "medium",
48
- "count": 2,
49
- "mergeLabel": "smart-spawn-merge: coding"
50
- }
51
- ```
52
-
53
- **You do:**
54
- 1. Call `sessions_spawn` for each model using its `id`, the `task`, and its `label`, with `waitForCompletion: true`
55
- 2. Collect all outputs
56
- 3. Call `sessions_spawn` with a fast model, giving it all outputs to synthesize the best answer, using the `mergeLabel`
57
-
58
- ### action: "cascade"
59
-
60
- The tool picked a cheap and premium model. Try cheap first, escalate if quality is insufficient:
61
-
62
- ```json
63
- {
64
- "action": "cascade",
65
- "cheapModel": "openrouter/deepseek/deepseek-chat-v3-0324",
66
- "cheapScore": 71,
67
- "cheapPricing": { "prompt": 0.27, "completion": 1.1 },
68
- "premiumModel": "openrouter/anthropic/claude-opus-4-6",
69
- "premiumScore": 82,
70
- "premiumPricing": { "prompt": 5, "completion": 25 },
71
- "cheapLabel": "smart-spawn-cascade-cheap: coding (deepseek-chat-v3-0324)",
72
- "premiumLabel": "smart-spawn-cascade-premium: coding (claude-opus-4-6)",
73
- "task": "...",
74
- "category": "coding",
75
- "escalationHint": "If the cheap model's response is incomplete, incorrect, or low quality, escalate to the premium model."
76
- }
77
- ```
78
-
79
- **You do:**
80
- 1. Call `sessions_spawn` with `cheapModel`, the `task`, and `cheapLabel`, with `waitForCompletion: true`
81
- 2. Evaluate the output quality — escalate if you see:
82
- - Incomplete or partial answers
83
- - Syntax errors or incorrect code
84
- - Vague or generic responses that don't address the task
85
- - Missing key requirements
86
- 3. If good enough: use that result, done (saved money!)
87
- 4. If not good enough: call `sessions_spawn` with `premiumModel` and `premiumLabel`, include the cheap output as context for improvement
88
-
89
- ### action: "swarm"
90
-
91
- The tool decomposed a complex task into a dependency DAG with parallel waves:
92
-
93
- ```json
94
- {
95
- "action": "swarm",
96
- "dag": {
97
- "tasks": [
98
- { "id": "swarm-1", "task": "Design database schema", "category": "coding", "model": "openrouter/anthropic/claude-sonnet-4", "budget": "medium", "persona": "database-architect", "dependsOn": [], "wave": 0, "reason": "...", "label": "smart-spawn-swarm-1: coding (claude-sonnet-4)" },
99
- { "id": "swarm-2", "task": "Build REST API", "category": "coding", "model": "openrouter/anthropic/claude-sonnet-4", "budget": "medium", "persona": "backend-engineer", "dependsOn": ["swarm-1"], "wave": 1, "reason": "...", "label": "smart-spawn-swarm-2: coding (claude-sonnet-4)" },
100
- { "id": "swarm-3", "task": "Create React frontend", "category": "coding", "model": "openrouter/anthropic/claude-sonnet-4", "budget": "medium", "persona": "frontend-engineer", "dependsOn": ["swarm-1"], "wave": 1, "reason": "...", "label": "smart-spawn-swarm-3: coding (claude-sonnet-4)" },
101
- { "id": "swarm-4", "task": "Write integration tests", "category": "coding", "model": "openrouter/deepseek/deepseek-chat-v3-0324", "budget": "low", "persona": "software-engineer", "dependsOn": ["swarm-2", "swarm-3"], "wave": 2, "reason": "...", "label": "smart-spawn-swarm-4: coding (deepseek-chat-v3-0324)" }
102
- ],
103
- "waves": [
104
- { "wave": 0, "taskIds": ["swarm-1"], "description": "1 task" },
105
- { "wave": 1, "taskIds": ["swarm-2", "swarm-3"], "description": "2 parallel tasks" },
106
- { "wave": 2, "taskIds": ["swarm-4"], "description": "1 task" }
107
- ],
108
- "edges": [
109
- { "from": "swarm-1", "to": "swarm-2", "type": "phase" },
110
- { "from": "swarm-1", "to": "swarm-3", "type": "phase" },
111
- { "from": "swarm-2", "to": "swarm-4", "type": "phase" },
112
- { "from": "swarm-3", "to": "swarm-4", "type": "phase" }
113
- ],
114
- "totalTasks": 4,
115
- "totalWaves": 3,
116
- "estimatedCost": { "low": 0.02, "high": 0.18 }
117
- },
118
- "originalTask": "...",
119
- "executionHint": "Execute wave-by-wave. Spawn all tasks within a wave in parallel. Pass outputs from completed tasks as context to their dependents in the next wave."
120
- }
121
- ```
122
-
123
- **You do:**
124
- 1. Execute **wave by wave** — process all waves in order (wave 0, then wave 1, etc.)
125
- 2. Within each wave, spawn **all tasks in parallel** — call `sessions_spawn` for each task using its `model`, `task`, and `label`, with `waitForCompletion: true`
126
- 3. When a task has `dependsOn`, include the outputs from those dependency tasks as context in the task prompt
127
- 4. After each wave completes, collect outputs before moving to the next wave
128
- 5. After all waves complete, synthesize the results if needed
129
- 6. Call `smart_spawn_feedback` for each completed task to rate the model's output
130
-
131
- **Key differences from plan mode:**
132
- - Plan is sequential (step 1, then step 2, then step 3...)
133
- - Swarm maximizes parallelism — independent tasks run simultaneously
134
- - Each task has a `persona` for role-specific prompting
135
- - Tasks declare explicit `dependsOn` relationships
136
-
137
- ### action: "plan"
138
-
139
- The tool decomposed a multi-step task into subtasks, each with its own optimal model:
140
-
141
- ```json
142
- {
143
- "action": "plan",
144
- "subtasks": [
145
- { "step": 1, "task": "Set up database schema", "category": "coding", "model": "openrouter/anthropic/claude-sonnet-4", "budget": "medium", "reason": "Best coding model at medium budget ($0-5/M) — score: 78", "label": "smart-spawn-plan-1: coding (claude-sonnet-4)" },
146
- { "step": 2, "task": "Implement REST API", "category": "coding", "model": "openrouter/anthropic/claude-sonnet-4", "budget": "medium", "reason": "...", "label": "smart-spawn-plan-2: coding (claude-sonnet-4)" },
147
- { "step": 3, "task": "Write unit tests", "category": "coding", "model": "openrouter/deepseek/deepseek-chat-v3-0324", "budget": "low", "reason": "...", "label": "smart-spawn-plan-3: coding (deepseek-chat-v3-0324)" }
148
- ],
149
- "originalTask": "1. Set up database schema\n2. Implement REST API\n3. Write unit tests",
150
- "totalSteps": 3,
151
- "executionHint": "Execute steps sequentially. Pass each step's output as context to the next."
152
- }
153
- ```
154
-
155
- **You do:**
156
- 1. Execute steps **sequentially** — call `sessions_spawn` for step 1, wait for completion
157
- 2. Pass each step's output as context to the next step (include the previous result in the task prompt)
158
- 3. After each step completes, call `smart_spawn_feedback` to rate that step's model
159
- 4. If a step fails, you may retry with the same model or skip to the next step with a note
160
-
161
- **When plan mode is useful:**
162
- - The user provides a numbered list or multi-step instructions
163
- - The task naturally decomposes into sequential phases (e.g. "design, implement, test")
164
- - Different steps benefit from different model strengths (e.g. reasoning for architecture, coding for implementation)
165
-
166
- ## When to Use Each Mode
167
-
168
- - **single** (default) — most tasks. Fast, one model.
169
- - **collective** — important decisions, creative work, or when diverse perspectives help. Costs 3-4x more.
170
- - **cascade** — cost-sensitive tasks where a cheap model might suffice. Saves money when cheap model is good enough.
171
- - **plan** — structured multi-step tasks that must run sequentially. Decomposes into subtasks, picks the best model for each step.
172
- - **swarm** — complex projects with parallelizable subtasks. Builds a dependency DAG, assigns personas, runs independent tasks simultaneously. Best for multi-component projects (e.g. "build API + frontend + tests + deploy").
173
-
174
- ## Examples
175
-
176
- ```
177
- smart_spawn(task: "Write a Python function to merge two sorted arrays")
178
- smart_spawn(task: "Analyze this architecture", category: "reasoning", budget: "high")
179
- smart_spawn(task: "Write a product launch email", mode: "collective", category: "creative")
180
- smart_spawn(task: "Convert this JSON to YAML", mode: "cascade")
181
- smart_spawn(task: "1. Design the database schema\n2. Implement the API endpoints\n3. Write integration tests", mode: "plan")
182
- smart_spawn(task: "1. Design database schema\n2. Build REST API\n3. Create React frontend\n4. Write integration tests\n5. Deploy to AWS", mode: "swarm", context: "typescript,nextjs,postgres")
183
- ```
184
-
185
- ## Feedback (Learning Loop)
186
-
187
- After receiving a spawned agent's output, you SHOULD call `smart_spawn_feedback` to rate its quality. This trains the system to pick better models for your tasks over time.
188
-
189
- ```
190
- smart_spawn_feedback(model: "anthropic/claude-opus-4-6", category: "coding", rating: 5)
191
- ```
192
-
193
- **Rating scale:**
194
- - **5** — Excellent. Fully solved the task, high quality.
195
- - **4** — Good. Completed the task with minor issues.
196
- - **3** — Acceptable. Got the job done but not great.
197
- - **2** — Poor. Missed key requirements or had significant issues.
198
- - **1** — Terrible. Failed the task or produced unusable output.
199
-
200
- **When to rate:**
201
- - Always rate after single mode spawns
202
- - In cascade mode: rate the cheap model's output (this determines if escalation was needed)
203
- - In collective mode: rate the final merged output
204
- - Use the `model` and `category` from the original `smart_spawn` response
205
-
206
- After enough feedback (3+ ratings per model+category), the system starts blending your personal scores into recommendations. Models you rate highly get boosted; models you rate poorly get deprioritized.
207
-
208
- ## Tips
209
-
210
- - Let `category: "auto"` do its job — it's right most of the time
211
- - Use `collective` sparingly — it costs 3-4x more
212
- - If the API is down, the tool falls back to hardcoded defaults (still works)
213
- - Model IDs may or may not have `openrouter/` prefix depending on user's auth — pass them as-is to `sessions_spawn`
214
- - Always provide feedback — it makes future picks better for your specific workflow