Repository navigation
Description
Bug: squad_route SDK tool returns false success without spawning a session
Summary
The squad_route tool exported by @bradygaster/squad-sdk is documented as routing tasks and creating new sessions for a target agent, but the current implementation never actually spawns anything. It returns resultType: 'success' with a confident "Task routed to X" payload, so SDK embedders following the documented usage receive a silent no-op masquerading as success.
Where it is documented as working
-
packages/squad-sdk/README.md(lines ~83–95):squad_route— Hand off work between agentsconst tool = toolRegistry.getTool('squad_route'); await tool.handler({ targetAgent: 'McManus', task: '...', priority: 'high' });
"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."
-
docs/src/content/docs/reference/sdk.md— Built-in tools table:squad_route— "Route a task to another agent". -
docs/src/content/docs/reference/api-reference.md— Built-in tools table: same. -
docs/src/content/docs/guide/build-autonomous-agent.md— Listed alongsidesquad_decide/squad_memory(which work fully) as "Routes a follow-up task to a teammate".
None of these surfaces disclose that squad_route is an unimplemented stub.
What the implementation actually does
packages/squad-sdk/src/tools/index.ts (current dev):
handler: async (args) => {
// Validate target agent exists (stub for now, will check roster later)
if (!args.targetAgent || args.targetAgent.trim() === '') { /* ... */ }
// Create route request (session creation wired later)
const routeRequest: RouteRequest = { /* ... */ };
return {
textResultForLlm: `Task routed to ${args.targetAgent}. Priority: ${routeRequest.priority}. Session creation will be implemented when session lifecycle is in place.`,
resultType: 'success',
toolTelemetry: { routeRequest },
};
},The two "stub for now" / "wired later" notes are inline source comments only. The "will be implemented" caveat is in textResultForLlm (visible to the calling agent at runtime), not in any user-facing doc that an embedder would read before integrating.
Impact
- Severity: silent data-integrity bug for SDK embedders.
resultType: 'success'is a contract claim. Embedders that branch on success vs. failure will record successful routing telemetry, advance workflow state, or report completion to users while no spawn occurred. - Who is affected: any consumer of
@bradygaster/squad-sdkwho callstoolRegistry.getTool('squad_route').handler(...)as documented, or exposessquad_routeto an LLM as part of a custom session built on the SDK. - Who is not affected: the squad CLI itself. The CLI's coordinator path delegates via the Copilot CLI
tasktool /Coordinator.route()→spawnParalleldirectly (packages/squad-sdk/src/coordinator/coordinator.ts:168), bypassing the tool registry entirely. CLI-level concurrency/fan-out is unrelated to this bug.
Repro
import { ToolRegistry } from '@bradygaster/squad-sdk/tools';
const registry = new ToolRegistry('./.squad');
const route = registry.getTool('squad_route')!;
const result = await route.handler({
targetAgent: 'McManus',
task: 'Write a blog post on the new casting system',
priority: 'high',
});
console.log(result.resultType); // 'success'
// No session was created. No agent was spawned. No event was emitted.Expected
One of:
- The handler actually spawns the target agent (matching documentation), or
- The handler returns a structured
failureso embedders can detect the unimplemented state, or - Documentation is updated to mark the tool as a non-functional stub / preview.
(1) is preferable — the rest of the documented surface around squad_decide, squad_memory, squad_status, squad_skill is implemented; squad_route is the odd one out.
Proposed fix
Wire the handler to spawnParallel (the same primitive Coordinator.route() already uses) via an optional fanOutDepsGetter constructor argument on ToolRegistry:
- When
fanOutDepsGetterreturns dependencies,squad_routecallsspawnParallelwith a single config (charter compile → model resolve →createSession→ initial message). - When absent or
undefined, the handler returnsresultType: 'failure'witherror: 'fan-out-deps-unavailable'and remediation guidance instead of fake-success. - The new constructor parameter is the 5th positional and optional, so existing 4-arg constructions remain compatible.
A behavior change: embedders that today rely on the stub's unconditional success would start seeing honest failures unless they wire fanOutDepsGetter or intercept squad_route via SquadSessionHooks.onPreToolUse. That is the intended fix — false success → honest failure or real spawn.
Related
- Bug: explicit named-agent delegation can resume same coordinator session but still answer inline before launching the requested agent #1029 — named-agent delegation answering inline before launching the requested agent. Different code path (Copilot CLI
tasktool / coordinator prompt), but shares the same root-cause family of silent-no-op delegation primitives. Not closed by the proposed fix. - Bug: Coordinator is doing work instead of routing work #853 — coordinator doing work instead of routing (closed; addressed via prompt rule). Same family.
Activity
fix(sdk): squad_route handler returns false success without spawning …
fix(sdk): squad_route handler returns false success without spawning …
fix(sdk): squad_route handler returns false success without spawning …