How to Subscribe to Streaming Events (40+ Types) in Copilot SDK Sessions

Enable streaming when creating a CopilotClient, then use session.on() to register typed listeners for specific events or a wildcard handler for all 40+ event types defined in the SDK.

The GitHub Copilot SDK delivers real-time updates through Server-Sent Events (SSE) when you subscribe to streaming events in Copilot SDK sessions. By setting streaming: true in your ClientOptions, the SDK opens a persistent HTTP connection to the CAPI endpoint and forwards each SSE-formatted message as a strongly-typed TypeScript event. This architecture allows your application to react to partial model outputs, tool completions, and lifecycle updates as they arrive, rather than waiting for the complete response.

Enabling SSE Streaming in the SDK

To receive streaming events, you must explicitly enable streaming during client initialization. In nodejs/src/session.ts, the CopilotClient.createSession method checks for the streaming flag in your configuration and forwards it to the request body, which instructs the CAPI proxy to return a text/event-stream response instead of a standard JSON payload.

import { CopilotClient } from "@github/copilot-sdk";

const client = new CopilotClient({
  // ... your authentication configuration
  streaming: true, // <-- Enables SSE transport
});

When this flag is active, the SDK parses incoming SSE frames (lines beginning with event: and data:) and dispatches them through an internal EventEmitter that backs the public session.on API.

How to Subscribe to Streaming Events in Copilot SDK Sessions

The CopilotSession instance provides two overloads of the on method, defined in nodejs/src/session.ts, giving you flexibility in how you consume the 40+ event types declared in nodejs/src/generated/session-events.ts.

Typed Event Subscriptions

Use the typed overload session.on(eventType, handler) when you need to react to a specific event type. This approach leverages the TypedSessionEventHandler<T> type to guarantee that your handler receives the correct payload shape at compile time.

// Subscribe to assistant message deltas
const unsubscribeMessage = session.on(
  "assistant.message",
  (event) => {
    // event is typed as AssistantMessageEvent
    console.log("Content delta:", event.message.content);
  }
);

// Subscribe to tool execution results
session.on(
  "tool.result",
  (event) => {
    // event is typed as ToolResultEvent
    console.log("Tool output:", event.result);
  }
);

Wildcard Subscriptions

For scenarios requiring centralized logging, routing, or debugging, use the wildcard overload session.on(handler). This receives every event emitted by the session as a discriminated union of type SessionEvent.

import type { SessionEvent } from "@github/copilot-sdk";

const unsubscribeAll = session.on((event: SessionEvent) => {
  console.log(`Received event type: ${event.type}`, event);
});

Lifecycle Management

Both overloads of session.on return an unsubscribe function. Calling this function detaches the listener from the internal EventEmitter, which is critical for preventing memory leaks in long-running sessions or when dynamically changing event subscriptions.

// Later in your application lifecycle:
unsubscribeMessage();
unsubscribeAll();

Working with 40+ SessionEvent Types

The complete set of available events is defined in nodejs/src/generated/session-events.ts as the SessionEvent union type. This includes granular delta events for streaming content updates, tool invocation events, and session lifecycle markers. The end-to-end test suite in nodejs/test/e2e/streaming_fidelity.e2e.test.ts verifies that these events are emitted correctly when streaming is enabled and suppressed when disabled.

Common event types include:

  • assistant.message – Emitted for each content delta from the language model
  • tool.result – Emitted when a tool execution completes and returns data
  • error – Emitted when the session encounters a processing error

Complete Implementation Example

The following example demonstrates creating a streaming session, subscribing to specific and wildcard events, and properly cleaning up listeners:

import { CopilotClient, type SessionEvent } from "@github/copilot-sdk";

async function runStreamingSession() {
  // 1. Initialize client with streaming enabled
  const client = new CopilotClient({
    // ... auth config
    streaming: true,
  });

  // 2. Create session (e.g., using GPT-4)
  const session = await client.createSession({ model: "gpt-4" });

  // 3. Subscribe to specific event types
  const unsubscribeAssistant = session.on(
    "assistant.message",
    (event) => {
      process.stdout.write(event.message.content); // Stream to stdout
    }
  );

  const unsubscribeTool = session.on(
    "tool.result",
    (event) => {
      console.log("Tool finished:", event.result);
    }
  );

  // 4. Wildcard subscription for monitoring
  const unsubscribeLogger = session.on((event: SessionEvent) => {
    console.log(`[LOG] ${event.type} at ${new Date().toISOString()}`);
  });

  // 5. Send prompt to trigger streaming
  await session.send({
    messages: [
      { role: "user", content: "Explain the difference between HTTP and HTTPS" }
    ],
  });

  // 6. Cleanup when done (e.g., before closing the session)
  unsubscribeAssistant();
  unsubscribeTool();
  unsubscribeLogger();
}

For additional patterns, reference the sample implementations in nodejs/samples/chat.ts (basic chat streaming) and nodejs/samples/manual-tool-resume.ts (handling tool results while streaming).

Summary

  • Enable SSE streaming by setting streaming: true in your CopilotClient configuration before creating a session.
  • Use typed subscriptions (session.on("event.type", handler)) for compile-time safety and specific event handling, leveraging types from nodejs/src/generated/session-events.ts.
  • Use wildcard subscriptions (session.on(handler)) to capture all 40+ event types through the SessionEvent union.
  • Manage memory by invoking the unsubscribe function returned by session.on when listeners are no longer needed.
  • Reference test suites in nodejs/test/e2e/streaming_fidelity.e2e.test.ts to understand expected event sequences.

Frequently Asked Questions

How do I enable streaming in the Copilot SDK?

Pass streaming: true in the CopilotClient constructor options. This flag is forwarded to the CAPI endpoint, which switches the response format from standard JSON to Server-Sent Events (SSE), allowing the SDK to emit events as they arrive.

What is the difference between typed and wildcard event handlers?

Typed handlers (session.on("assistant.message", handler)) receive a specific payload type (e.g., AssistantMessageEvent) and provide compile-time type safety. Wildcard handlers (session.on(handler)) receive every event as the generic SessionEvent union, useful for logging or routing logic that must inspect all event types.

How many event types are available in the Copilot SDK?

The SDK exposes 40+ event types defined in nodejs/src/generated/session-events.ts, including delta content updates, tool results, error events, and lifecycle markers. The exact count grows as the API evolves, but all are accessible through the SessionEvent union type.

How do I prevent memory leaks when subscribing to events?

The session.on method returns an unsubscribe function. Store this function and call it when your component unmounts or when you no longer need the listener. This detaches the handler from the underlying EventEmitter and prevents accumulation of unused listeners in long-running sessions.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →