@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 +3 -1
- package/index.ts +22 -7
- package/openclaw.plugin.json +1 -1
- package/package.json +2 -2
- package/skills/smart-spawn/SKILL.md +2 -1
- package/skills/SKILL.md +0 -214
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
|
-
|
|
453
|
-
|
|
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:
|
|
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: [{
|
package/openclaw.plugin.json
CHANGED
|
@@ -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.
|
|
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.
|
|
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://
|
|
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
|
|
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
|