@bradygaster/squad-sdk 0.6.1 → 0.7.0
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 +266 -20
- package/package.json +25 -1
package/README.md
CHANGED
|
@@ -1,50 +1,296 @@
|
|
|
1
1
|
# @bradygaster/squad-sdk
|
|
2
2
|
|
|
3
|
-
Programmable multi-agent runtime for GitHub Copilot
|
|
3
|
+
**Programmable multi-agent runtime for GitHub Copilot.** Build AI teams that persist, learn, and coordinate — with real governance, not vibes.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
[](#requirements)
|
|
6
|
+
[](#requirements)
|
|
7
|
+
[](#requirements)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Install
|
|
6
12
|
|
|
7
13
|
```bash
|
|
8
14
|
npm install @bradygaster/squad-sdk
|
|
9
15
|
```
|
|
10
16
|
|
|
11
|
-
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## What Makes This Different
|
|
20
|
+
|
|
21
|
+
Most multi-agent setups are prompt engineering. You write a wall of text describing who each agent is, what they can do, and hope the model follows the rules. It works — until it doesn't. Agents ignore routing. They write files they shouldn't. They leak data. There's no enforcement, just suggestions.
|
|
22
|
+
|
|
23
|
+
Squad's SDK moves orchestration out of prompts and into code:
|
|
24
|
+
|
|
25
|
+
**Prompt-only orchestration** stuffs everything into a single context window. The coordinator is text. Agents read it, interpret it, maybe follow it.
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
Prompt says:
|
|
29
|
+
"If the agent is Backend, route auth tasks to it."
|
|
30
|
+
Agent reads it (consumes tokens), decides what to do (might ignore it).
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**SDK orchestration** compiles rules into typed functions. Sessions are objects. Routing is deterministic. Tools are validated before execution.
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
Router.matchRoute(message) → { agent: 'Backend', priority: 'high' }
|
|
37
|
+
// TypeScript knows exactly which agent runs, with what permissions.
|
|
38
|
+
// HookPipeline runs file-write guards BEFORE the tool executes.
|
|
39
|
+
// No interpretation. No ambiguity. Just code.
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Architecture
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
┌─────────────────────────────────────────────┐
|
|
48
|
+
│ Your Code (TypeScript) │
|
|
49
|
+
│ - createSession(), spawnParallel() │
|
|
50
|
+
│ - SquadClient, EventBus, HookPipeline │
|
|
51
|
+
└─────────────────────────────────────────────┘
|
|
52
|
+
↓
|
|
53
|
+
┌─────────────────────────────────────────────┐
|
|
54
|
+
│ Agent Orchestration Runtime │
|
|
55
|
+
│ - Router (matchRoute, compileRoutingRules) │
|
|
56
|
+
│ - Charter Compiler (permissions, voice) │
|
|
57
|
+
│ - Tool Registry (squad_route, etc.) │
|
|
58
|
+
│ - Hook Pipeline (governance enforcement) │
|
|
59
|
+
└─────────────────────────────────────────────┘
|
|
60
|
+
↓
|
|
61
|
+
┌─────────────────────────────────────────────┐
|
|
62
|
+
│ Session Pool + Event Bus │
|
|
63
|
+
│ - Each agent gets a persistent session │
|
|
64
|
+
│ - Cross-session event pub/sub │
|
|
65
|
+
│ - Crash recovery via session state │
|
|
66
|
+
└─────────────────────────────────────────────┘
|
|
67
|
+
↓
|
|
68
|
+
┌─────────────────────────────────────────────┐
|
|
69
|
+
│ @github/copilot-sdk │
|
|
70
|
+
│ - Real-time agent streaming │
|
|
71
|
+
│ - Tool execution │
|
|
72
|
+
└─────────────────────────────────────────────┘
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Your code sits at the top. The runtime handles routing, permissions, and governance. Sessions are persistent and recoverable. Everything runs on top of the official Copilot SDK.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Custom Tools
|
|
80
|
+
|
|
81
|
+
Five tools let agents coordinate without calling you back. Here are the three you'll reach for first.
|
|
82
|
+
|
|
83
|
+
### `squad_route` — Hand off work between agents
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
const tool = toolRegistry.getTool('squad_route');
|
|
87
|
+
await tool.handler({
|
|
88
|
+
targetAgent: 'McManus',
|
|
89
|
+
task: 'Write a blog post on the new casting system',
|
|
90
|
+
priority: 'high',
|
|
91
|
+
context: 'Feature launches next week',
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The lead routes a task to DevRel. A new session is created, context is passed, and the task is queued with priority. No human in the loop.
|
|
96
|
+
|
|
97
|
+
### `squad_decide` — Record a team decision
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
await tool.handler({
|
|
101
|
+
author: 'Keaton',
|
|
102
|
+
summary: 'Use PostgreSQL, not MongoDB',
|
|
103
|
+
body: 'Chose PostgreSQL for: (1) transactions, (2) team expertise, (3) JSONB flexibility.',
|
|
104
|
+
references: ['architecture-spike'],
|
|
105
|
+
});
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Writes to the shared decision log. Every agent reads decisions before working — one call propagates context to the entire team.
|
|
109
|
+
|
|
110
|
+
### `squad_memory` — Teach an agent something permanent
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
await tool.handler({
|
|
114
|
+
agent: 'Frontend',
|
|
115
|
+
section: 'learnings',
|
|
116
|
+
content: 'Project uses Tailwind v4 with dark mode plugin. Config at .styles/theme.config.ts',
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Agents learn as they work. Next session, Frontend reads this and knows immediately. No context hunting, no re-explaining.
|
|
121
|
+
|
|
122
|
+
> Two more tools — `squad_status` (query the session pool) and `squad_skill` (read/write compressed learnings) — round out the coordination layer. See the [full docs](https://github.com/bradygaster/squad-pr#the-custom-tools) for details.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Hook Pipeline
|
|
127
|
+
|
|
128
|
+
Rules don't live in prompts. They run as code, before tools execute.
|
|
129
|
+
|
|
130
|
+
### File-Write Guards
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
const pipeline = new HookPipeline({
|
|
134
|
+
allowedWritePaths: ['src/**/*.ts', '.squad/**', 'docs/**'],
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// An agent tries to write to /etc/passwd
|
|
138
|
+
// → Blocked. "File write blocked: '/etc/passwd' does not match allowed paths"
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
No agent — compromised or confused — can write outside your safe zones. Not because you asked nicely in the prompt. Because code won't let them.
|
|
142
|
+
|
|
143
|
+
### PII Scrubbing
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
const pipeline = new HookPipeline({
|
|
147
|
+
scrubPii: true,
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// Agent logs: "contact brady@example.com about deploy"
|
|
151
|
+
// Output becomes: "contact [EMAIL_REDACTED] about deploy"
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Sensitive data never escapes. Automatic, invisible to the agent, applied to every tool output.
|
|
155
|
+
|
|
156
|
+
### Reviewer Lockout
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
const lockout = pipeline.getReviewerLockout();
|
|
160
|
+
lockout.lockout('src/auth.ts', 'Backend');
|
|
161
|
+
|
|
162
|
+
// Backend tries to re-write auth.ts after a review rejection
|
|
163
|
+
// → Blocked. "Agent 'Backend' is locked out of artifact 'src/auth.ts'"
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
When a reviewer says "no," it sticks. The original author can't sneak a fix in. Protocol enforced by code, not convention.
|
|
167
|
+
|
|
168
|
+
### Ask-User Rate Limiter
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
const pipeline = new HookPipeline({
|
|
172
|
+
maxAskUserPerSession: 3,
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
// Fourth attempt to prompt the user → Blocked.
|
|
176
|
+
// "ask_user rate limit exceeded: 3/3 calls used. Proceed without user input."
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Agents don't stall waiting for you. They decide or move on.
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## Persistent Sessions & Crash Recovery
|
|
184
|
+
|
|
185
|
+
Sessions aren't ephemeral. They're durable objects that survive failures.
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
const session = await client.createSession({
|
|
189
|
+
agentName: 'Backend',
|
|
190
|
+
task: 'Implement user auth endpoints',
|
|
191
|
+
persistPath: '.squad/sessions/backend-auth-001.json',
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// Agent dies mid-work — network hiccup, model timeout, anything.
|
|
195
|
+
// Later:
|
|
196
|
+
|
|
197
|
+
const resumed = await client.resumeSession(
|
|
198
|
+
'.squad/sessions/backend-auth-001.json'
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
// Backend wakes up knowing:
|
|
202
|
+
// - What the task was
|
|
203
|
+
// - What it already wrote
|
|
204
|
+
// - Where it left off
|
|
205
|
+
// No repetition, no lost context.
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## The Casting Engine
|
|
211
|
+
|
|
212
|
+
Agents aren't `role-1`, `role-2`. They have names, personalities, and persistent identities across sessions. The casting engine assigns them automatically from a thematic universe.
|
|
12
213
|
|
|
13
214
|
```typescript
|
|
14
|
-
|
|
215
|
+
const casting = new CastingEngine({
|
|
216
|
+
universe: 'usual-suspects',
|
|
217
|
+
agentCount: 5,
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
const cast = casting.castTeam({
|
|
221
|
+
roles: ['lead', 'frontend', 'backend', 'tester', 'scribe'],
|
|
222
|
+
});
|
|
223
|
+
// → [
|
|
224
|
+
// { role: 'lead', agentName: 'Keaton' },
|
|
225
|
+
// { role: 'frontend', agentName: 'McManus' },
|
|
226
|
+
// { role: 'backend', agentName: 'Verbal' },
|
|
227
|
+
// { role: 'tester', agentName: 'Fenster' },
|
|
228
|
+
// { role: 'scribe', agentName: 'Kobayashi' },
|
|
229
|
+
// ]
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Names are memorable ("Keaton handles routing"), persistent (same name every session), and extensible (add a sixth agent — the casting engine picks the next name from the universe). You build a relationship with your agents over time.
|
|
233
|
+
|
|
234
|
+
---
|
|
15
235
|
|
|
16
|
-
|
|
17
|
-
const squadDir = await resolveSquad();
|
|
236
|
+
## Event-Driven Monitoring
|
|
18
237
|
|
|
19
|
-
|
|
20
|
-
const config = await loadConfig();
|
|
238
|
+
Ralph is the built-in work monitor — a persistent agent session that subscribes to everything happening on the team.
|
|
21
239
|
|
|
22
|
-
|
|
240
|
+
```typescript
|
|
241
|
+
const ralph = new RalphMonitor({
|
|
242
|
+
teamRoot: '.squad',
|
|
243
|
+
healthCheckInterval: 30000,
|
|
244
|
+
statePath: '.squad/ralph-state.json',
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
ralph.subscribe('agent:task-complete', (event) => {
|
|
248
|
+
console.log(`✅ ${event.agentName} finished: ${event.task}`);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
ralph.subscribe('agent:error', (event) => {
|
|
252
|
+
console.log(`❌ ${event.agentName} failed: ${event.error}`);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
await ralph.start();
|
|
23
256
|
```
|
|
24
257
|
|
|
25
|
-
|
|
258
|
+
When agents complete work, record decisions, or hit errors — Ralph knows. If an agent crashes, Ralph remembers where it left off.
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## API Reference
|
|
26
263
|
|
|
27
264
|
| Module | Key Exports | Purpose |
|
|
28
265
|
|--------|------------|---------|
|
|
29
|
-
| `resolution` | `resolveSquad()`, `resolveGlobalSquadPath()`, `ensureSquadPath()` |
|
|
266
|
+
| `resolution` | `resolveSquad()`, `resolveGlobalSquadPath()`, `ensureSquadPath()` | Find `.squad/` directory; platform-specific global path; path validation |
|
|
30
267
|
| `config` | `loadConfig()`, `loadConfigSync()` | Load and parse squad configuration from disk |
|
|
31
268
|
| `agents` | Agent onboarding utilities | Register and initialize agents; manage team discovery |
|
|
32
|
-
| `casting` |
|
|
33
|
-
| `skills` | Skills system |
|
|
269
|
+
| `casting` | `CastingEngine` | Universe selection, name allocation, persistent registry |
|
|
270
|
+
| `skills` | Skills system | SKILL.md lifecycle, confidence levels |
|
|
34
271
|
| `coordinator` | `selectResponseTier()`, `getTier()` | Route requests to Direct/Lightweight/Standard/Full tiers |
|
|
35
|
-
| `runtime` | Streaming pipeline, cost tracker, telemetry
|
|
272
|
+
| `runtime` | Streaming pipeline, cost tracker, telemetry | Core async execution, event streaming, i18n |
|
|
36
273
|
| `cli` | `checkForUpdate()`, `performUpgrade()` | SDK version management and update checking |
|
|
37
|
-
| `
|
|
38
|
-
|
|
274
|
+
| `marketplace` | Plugin marketplace | Discover and manage plugins |
|
|
275
|
+
|
|
276
|
+
---
|
|
39
277
|
|
|
40
278
|
## Requirements
|
|
41
279
|
|
|
42
|
-
- **Node.js
|
|
43
|
-
- **TypeScript
|
|
44
|
-
- **
|
|
280
|
+
- **Node.js** ≥ 20.0.0
|
|
281
|
+
- **TypeScript** ≥ 5.0
|
|
282
|
+
- **ESM-only** — no CommonJS. Set `"type": "module"` in your `package.json`.
|
|
283
|
+
|
|
284
|
+
---
|
|
45
285
|
|
|
46
286
|
## Links
|
|
47
287
|
|
|
48
288
|
- **Repository:** [github.com/bradygaster/squad-pr](https://github.com/bradygaster/squad-pr)
|
|
289
|
+
- **CLI package:** [@bradygaster/squad-cli](https://www.npmjs.com/package/@bradygaster/squad-cli)
|
|
49
290
|
- **Issues:** [github.com/bradygaster/squad-pr/issues](https://github.com/bradygaster/squad-pr/issues)
|
|
50
|
-
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## License
|
|
295
|
+
|
|
296
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bradygaster/squad-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Squad SDK — Programmable multi-agent runtime for GitHub Copilot",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -9,6 +9,30 @@
|
|
|
9
9
|
".": {
|
|
10
10
|
"types": "./dist/index.d.ts",
|
|
11
11
|
"import": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./parsers": {
|
|
14
|
+
"types": "./dist/parsers.d.ts",
|
|
15
|
+
"import": "./dist/parsers.js"
|
|
16
|
+
},
|
|
17
|
+
"./types": {
|
|
18
|
+
"types": "./dist/types.d.ts",
|
|
19
|
+
"import": "./dist/types.js"
|
|
20
|
+
},
|
|
21
|
+
"./config": {
|
|
22
|
+
"types": "./dist/config/index.d.ts",
|
|
23
|
+
"import": "./dist/config/index.js"
|
|
24
|
+
},
|
|
25
|
+
"./skills": {
|
|
26
|
+
"types": "./dist/skills/index.d.ts",
|
|
27
|
+
"import": "./dist/skills/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./agents": {
|
|
30
|
+
"types": "./dist/agents/index.d.ts",
|
|
31
|
+
"import": "./dist/agents/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./cli": {
|
|
34
|
+
"types": "./dist/cli/index.d.ts",
|
|
35
|
+
"import": "./dist/cli/index.js"
|
|
12
36
|
}
|
|
13
37
|
},
|
|
14
38
|
"files": [
|