Skip to content

sendAndWait returns prematurely when orchestrator dispatches sub-agents via task and ends its turn #1275

@kevinlims

Description

@kevinlims

Summary

sendAndWait awaits session.idle. The CLI fires session.idle when the orchestrator's turn ends — including when the orchestrator ends its turn after dispatching task calls. The SDK does not track in-flight sub-agents; task is fire-and-forget from the SDK's perspective. Consumers' code believes the session is complete and tears down state while sub-agents are still running.

Repro

const session = await client.createSession({
  customAgents: [
    { name: "scanner", description: "Scans codebase", prompt: "..." },
    { name: "triager", description: "Triages findings", prompt: "..." },
  ],
});

await session.sendAndWait({
  prompt: "Dispatch a scanner agent to analyze the codebase, then a triager to rank findings.",
});

// `sendAndWait` resolves shortly after the orchestrator's `task(scanner)` + `task(triager)` calls
// — BEFORE the sub-agents have completed their work.

Expected

sendAndWait resolves only when all dispatched sub-agents have completed.

Actual

sendAndWait resolves on the first session.idle event. If the orchestrator's turn ends after dispatching but before sub-agent completion, the session is considered idle and sendAndWait returns. Sub-agents may still be running.

Frequency observed in another harness: ~30% of multi-sub-agent dispatch sessions.

Evidence (SDK source)

nodejs/src/session.ts: sendAndWait() listens for event.type === "session.idle" and calls resolveIdle() on the first occurrence. No task-dispatch tracking, no sub-agent counter, no subagent.completed accumulation.

Workaround (consumer-side)

Either:

  • Poll for a terminal artifact path on the filesystem (works if the sub-agents are expected to write a known output file).
  • Maintain a sub-agent counter in user code, incremented on subagent.started and decremented on subagent.completed. Only treat the session as complete when session.idle AND counter == 0.

Both reinvent state machine logic the SDK is best positioned to provide.

Suggested fix

  • Make sendAndWait track dispatched sub-agents (via subagent.started / subagent.completed) and resolve only when the session is idle AND all sub-agents have completed.
  • Or add a new sendAndWaitForCompletion({ prompt }) API consumers can opt into.

Related

Environment

- SDK: @github/copilot-sdk@0.3.0
- CLI: @github/copilot@1.0.45
- Node: 22 LTS
- OS: Windows 11
- Model: claude-sonnet-4-6

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions