SDK Reference
⚠️ Experimental — Squad is alpha software. APIs, commands, and behavior may change between releases.
Complete reference for @bradygaster/squad-sdk — the programmatic API for Squad.
npm install @bradygaster/squad-sdk
All imports work from the barrel export:
import { resolveSquad, loadConfig, SquadCoordinator, defineTool } from '@bradygaster/squad-sdk';
Resolution
Find .squad/ directories on disk.
| Function | Description |
|---|---|
resolveSquad(startPath?) | Find .squad/ walking up from startPath (throws if not found) |
resolveGlobalSquadPath() | Get personal squad directory path (platform-specific) |
ensureSquadPath(startPath?) | Like resolveSquad, but creates .squad/ if missing |
const squadPath = resolveSquad(); // '/home/user/project/.squad'
const globalPath = resolveGlobalSquadPath(); // Platform-specific: ~/.config/squad/ (Linux), ~/Library/Application Support/squad/ (macOS), %APPDATA%\squad\ (Windows)
const safePath = ensureSquadPath(); // Creates if needed
Configuration
loadConfig(squadPath): Promise<ConfigLoadResult>
Load and validate Squad configuration asynchronously.
const config = await loadConfig('./.squad');
config.team.name; // Team name
Object.keys(config.agents); // Agent names
config.routing.workTypes; // Routing rules
loadConfigSync(squadPath): ConfigLoadResult
Synchronous version for scripts and CLI tools.
defineConfig(partial): SquadConfig
Create a typed config with defaults and editor autocomplete:
// squad.config.ts
import { defineConfig } from '@bradygaster/squad-sdk';
export default defineConfig({
team: { name: 'my-squad', root: '.squad' },
agents: {
backend: { model: 'claude-sonnet-4', tools: ['route', 'memory', 'decision'] },
},
routing: {
workTypes: [
{ pattern: /\bAPI|backend\b/i, targets: ['backend'], tier: 'standard' },
],
},
models: {
default: 'claude-sonnet-4',
fallbackChains: {
premium: ['claude-opus-4', 'gpt-4.1'],
standard: ['claude-sonnet-4', 'gpt-4.1'],
fast: ['claude-haiku-3.5', 'gpt-4.1-mini'],
},
},
});
Key Types
interface ConfigLoadResult {
team: { name: string; root: string; description?: string };
agents?: Record<string, AgentConfig>;
routing?: RoutingConfig;
models?: ModelConfig;
}
interface AgentConfig {
role: string;
model?: string;
tools?: string[];
status?: 'active' | 'inactive';
}
Builder Functions (SDK-First Mode)
Type-safe team configuration with runtime validation. Each builder accepts a config object, validates it, and returns the typed value.
New in Phase 1 — SDK-First Mode lets you define teams in TypeScript instead of manually maintaining markdown. Run
squad buildto generate.squad/files.
See SDK-First Mode Guide for comprehensive documentation and examples.
defineTeam(config): TeamDefinition
Define team metadata, members, and project context.
const team = defineTeam({
name: 'Platform Squad',
description: 'Full-stack engineering team',
projectContext: 'React/Node monorepo, TypeScript strict mode',
members: ['@edie', '@mcmanus', '@fenster'],
});
Type:
interface TeamDefinition {
readonly name: string;
readonly description?: string;
readonly projectContext?: string;
readonly members: readonly string[];
}
defineAgent(config): AgentDefinition
Define a single agent with role, tools, model, and capabilities.
const edie = defineAgent({
name: 'edie',
role: 'TypeScript Engineer',
model: 'claude-sonnet-4',
tools: ['grep', 'edit', 'powershell', 'view'],
capabilities: [
{ name: 'type-system', level: 'expert' },
{ name: 'testing', level: 'proficient' },
],
status: 'active',
});
Type:
interface AgentDefinition {
readonly name: string;
readonly role: string;
readonly charter?: string;
readonly model?: string;
readonly tools?: readonly string[];
readonly capabilities?: readonly AgentCapability[];
readonly status?: 'active' | 'inactive' | 'retired';
}
interface AgentCapability {
readonly name: string;
readonly level: 'expert' | 'proficient' | 'basic';
}
defineRouting(config): RoutingDefinition
Define routing rules with pattern matching and tier assignment.
const routing = defineRouting({
rules: [
{ pattern: 'feature-*', agents: ['@edie'], tier: 'standard' },
{ pattern: 'docs-*', agents: ['@mcmanus'], tier: 'lightweight' },
],
defaultAgent: '@coordinator',
fallback: 'coordinator',
});
Type:
interface RoutingDefinition {
readonly rules: readonly RoutingRule[];
readonly defaultAgent?: string;
readonly fallback?: 'ask' | 'default-agent' | 'coordinator';
}
interface RoutingRule {
readonly pattern: string;
readonly agents: readonly string[];
readonly tier?: 'direct' | 'lightweight' | 'standard' | 'full';
readonly priority?: number;
}
defineCeremony(config): CeremonyDefinition
Define ceremonies (standups, retros, etc.) with schedule and participants.
const standup = defineCeremony({
name: 'standup',
trigger: 'schedule',
schedule: '0 9 * * 1-5',
participants: ['@edie', '@mcmanus'],
agenda: 'Yesterday / Today / Blockers',
});
Type:
interface CeremonyDefinition {
readonly name: string;
readonly trigger?: string;
readonly schedule?: string;
readonly participants?: readonly string[];
readonly agenda?: string;
readonly hooks?: readonly string[];
}
defineHooks(config): HooksDefinition
Define governance hooks — write paths, blocked commands, PII scrubbing.
const hooks = defineHooks({
allowedWritePaths: ['src/**', 'test/**', '.squad/**'],
blockedCommands: ['rm -rf /', 'DROP TABLE'],
maxAskUser: 3,
scrubPii: true,
reviewerLockout: true,
});
Type:
interface HooksDefinition {
readonly allowedWritePaths?: readonly string[];
readonly blockedCommands?: readonly string[];
readonly maxAskUser?: number;
readonly scrubPii?: boolean;
readonly reviewerLockout?: boolean;
}
defineCasting(config): CastingDefinition
Define casting configuration — universe allowlists and overflow behavior.
const casting = defineCasting({
allowlistUniverses: ['The Usual Suspects', 'Breaking Bad'],
overflowStrategy: 'generic',
capacity: { 'The Usual Suspects': 8 },
});
Type:
interface CastingDefinition {
readonly allowlistUniverses?: readonly string[];
readonly overflowStrategy?: 'reject' | 'generic' | 'rotate';
readonly capacity?: Readonly<Record<string, number>>;
}
defineTelemetry(config): TelemetryDefinition
Define OpenTelemetry configuration for observability.
const telemetry = defineTelemetry({
enabled: true,
endpoint: 'http://localhost:4317',
serviceName: 'squad-prod',
sampleRate: 1.0,
aspireDefaults: true,
});
Type:
interface TelemetryDefinition {
readonly enabled?: boolean;
readonly endpoint?: string;
readonly serviceName?: string;
readonly sampleRate?: number;
readonly aspireDefaults?: boolean;
}
defineSquad(config): SquadSDKConfig
Compose all builders into a single SDK config.
export default defineSquad({
version: '1.0.0',
team: defineTeam({ /* ... */ }),
agents: [defineAgent({ /* ... */ })],
routing: defineRouting({ /* ... */ }),
});
Type:
interface SquadSDKConfig {
readonly version?: string;
readonly team: TeamDefinition;
readonly agents: readonly AgentDefinition[];
readonly routing?: RoutingDefinition;
readonly ceremonies?: readonly CeremonyDefinition[];
readonly hooks?: HooksDefinition;
readonly casting?: CastingDefinition;
readonly telemetry?: TelemetryDefinition;
}
SquadClient
Wraps @github/copilot-sdk with lifecycle management and auto-reconnection.
import { SquadClient } from '@bradygaster/squad-sdk';
const client = new SquadClient({
port: 3000,
auth: { token: process.env.COPILOT_TOKEN },
reconnection: { maxRetries: 5, backoffMs: 1000 },
});
await client.connect();
Connection states: disconnected → connecting → connected → reconnecting → error
SquadClientWithPool
Production-ready client composing SquadClient, SessionPool, and EventBus:
import { SquadClientWithPool } from '@bradygaster/squad-sdk';
const squad = new SquadClientWithPool({
client: clientOptions,
pool: { maxConcurrent: 10, idleTimeout: 60_000 },
});
const session = await squad.createSession({ agent: 'backend' });
const response = await session.sendMessage('Implement the /users endpoint');
await session.destroy();
Session states: creating → active → idle → error → destroyed
Coordinator
Central routing and orchestration engine.
SquadCoordinator
import { SquadCoordinator } from '@bradygaster/squad-sdk';
const coordinator = new SquadCoordinator({ teamRoot: './.squad', enableParallel: true });
await coordinator.initialize();
const decision = await coordinator.route('refactor the API');
// decision.tier: 'direct' | 'lightweight' | 'standard' | 'full'
// decision.agents: ['backend', 'tester']
// decision.parallel: true
// decision.rationale: 'Backend refactor with test coverage'
await coordinator.execute(decision, 'refactor the API');
await coordinator.shutdown();
selectResponseTier(context): TierName
const tier = selectResponseTier({ complexity: 'high', budget: 10, userTeam: true });
// → 'standard' or 'full'
getTier(name): TierDefinition
const tier = getTier('standard');
tier.maxAgents; // Max parallel agents
tier.defaultModel; // Default model
tier.toolset; // Available tools
Event Handling
Typed pub/sub for session lifecycle events:
squad.events.on('session.created', (event) => {
console.log(`Session ${event.sessionId} started`);
});
squad.events.on('session.status_changed', (event) => {
if (event.payload.status === 'error') { /* handle */ }
});
Events: session.created, session.destroyed, session.status_changed, tool execution events.
Tools & Hooks
defineTool<TArgs>(config): SquadTool<TArgs>
import { defineTool } from '@bradygaster/squad-sdk';
const myTool = defineTool<{ query: string }>({
name: 'search_docs',
description: 'Search project documentation',
parameters: {
type: 'object',
properties: { query: { type: 'string' } },
required: ['query'],
},
handler: async (args) => ({
textResultForLlm: `Found results for "${args.query}"`,
resultType: 'success',
}),
});
ToolRegistry
const registry = new ToolRegistry('./.squad');
registry.getTools(); // All tools
registry.getToolsForAgent(['squad_route', 'squad_decide']); // Agent-specific
registry.getTool('squad_route'); // Single lookup
Built-in tools:
| Tool | Purpose |
|---|---|
squad_route | Route a task to another agent |
squad_decide | Write decisions to the inbox |
squad_memory | Append to agent history |
squad_status | Query session pool state |
squad_skill | Read/write agent skills |
HookPipeline
Intercept tool calls before (PreToolUseHook) and after (PostToolUseHook) execution:
import { HookPipeline, type PreToolUseHook } from '@bradygaster/squad-sdk';
const auditHook: PreToolUseHook = async (toolName, params, context) => {
console.log(`Agent ${context.agentId} calling ${toolName}`);
return { action: 'allow' };
};
const pipeline = new HookPipeline();
pipeline.addPreHook(auditHook);
Hook actions: allow, block, modify
Built-in policies: ReviewerLockout, File Guards, Shell Restrictions, Rate Limits, PII Filters.
Agents & Casting
onboardAgent(options): Promise<OnboardResult>
const result = await onboardAgent({
teamRoot: './.squad',
agentName: 'data-analyst',
role: 'backend',
displayName: 'Dana — Data Analyst',
projectContext: 'A recipe sharing app',
});
// result.agentDir, result.charterPath, result.historyPath
CastingEngine
import { CastingEngine } from '@bradygaster/squad-sdk';
const engine = new CastingEngine({ universes: ['The Wire'], activeUniverse: 'The Wire' });
const members = await engine.castTeam([
{ role: 'lead', title: 'Lead Developer' },
{ role: 'backend', title: 'Backend Engineer' },
]);
// members[0].name → 'Stringer', members[0].universe → 'The Wire'
Runtime Constants
import { MODELS, TIMEOUTS, AGENT_ROLES } from '@bradygaster/squad-sdk';
MODELS.premium; // ['claude-opus-4.6', 'gpt-5.2', ...]
MODELS.standard; // ['claude-sonnet-4.5', 'gpt-5.1', ...]
MODELS.fast; // ['claude-haiku-4.5', 'gpt-5-mini', ...]
TIMEOUTS.agentInitMs; // 30000
TIMEOUTS.agentExecuteMs; // 300000
TIMEOUTS.coordinatorRouteMs; // 5000
Upstream Inheritance
Share skills, decisions, and routing across teams.
import { readUpstreamConfig, resolveUpstreams, buildInheritedContextBlock } from '@bradygaster/squad-sdk';
const config = await readUpstreamConfig('./.squad');
const resolved = await resolveUpstreams(config, './.squad');
const contextBlock = buildInheritedContextBlock(resolved);
Upstream types: local, git, export
Observability (OpenTelemetry)
Quick Setup
import { initSquadTelemetry } from '@bradygaster/squad-sdk';
const telemetry = await initSquadTelemetry({
endpoint: 'http://localhost:4318',
serviceName: 'my-squad',
eventBus: myEventBus,
});
// ... run agents ...
await telemetry.shutdown();
Low-Level Control
import { initializeOTel, shutdownOTel, getTracer, getMeter } from '@bradygaster/squad-sdk';
await initializeOTel({ endpoint: 'http://localhost:4318' });
const tracer = getTracer('my-component');
const span = tracer.startSpan('my-work');
// ... do work ...
span.end();
const meter = getMeter('my-component');
const counter = meter.createCounter('requests_total');
counter.add(1);
await shutdownOTel();
Error Classes
All errors extend SquadError with severity, category, and recoverability:
| Error | When |
|---|---|
SDKConnectionError | Connection failures (retryable) |
AuthenticationError | Bad credentials (fatal) |
SessionLifecycleError | Session state transitions |
ToolExecutionError | Tool call failures |
ModelAPIError | Model unavailable or rate limited |
ConfigurationError | Invalid config (includes field + reason) |
RateLimitError | Too many requests |
ValidationError | Schema validation failures |
Exports at a Glance
| Export | Type | Module |
|---|---|---|
resolveSquad | function | resolution |
resolveGlobalSquadPath | function | resolution |
ensureSquadPath | function | resolution |
MODELS | constant | runtime/constants |
TIMEOUTS | constant | runtime/constants |
AGENT_ROLES | constant | runtime/constants |
loadConfig / loadConfigSync | function | config |
onboardAgent | function | agents |
CastingEngine / CastingHistory | class | casting |
SquadCoordinator | class | coordinator |
selectResponseTier / getTier | function | coordinator |
defineTool / ToolRegistry | function/class | tools |
initializeOTel / shutdownOTel | function | runtime/otel |
getTracer / getMeter | function | runtime/otel |
initSquadTelemetry | function | runtime/otel-init |
See Also
- CLI Reference — Shell commands and config files
- Recipes & Advanced Scenarios — Prompt-driven cookbook