How to Handle Copilot Suggestions and Responses Using the Copilot SDK
To handle Copilot suggestions and responses, instantiate a CopilotClient to manage the runtime connection, create a CopilotSession to maintain conversation state, and subscribe to typed events like assistant.message and external_tool.requested to process the assistant's output and tool calls.
The GitHub Copilot SDK provides a Node.js interface for programmatically driving Copilot CLI sessions, enabling applications to send prompts and handle Copilot suggestions and responses through a JSON-RPC bridge. The architecture separates concerns between the CopilotClient class in [nodejs/src/index.ts](https://github.com/github/copilot-sdk/blob/main/nodejs/src/index.ts), which handles global lifecycle and configuration, and the CopilotSession class implemented in [nodejs/src/session.ts](https://github.com/github/copilot-sdk/blob/main/nodejs/src/session.ts) (lines 33-34), which manages individual conversation state, event emission, and capability negotiation.
Initialize the Client and Create a Session
The workflow begins with the CopilotClient entry point, which configures how the SDK communicates with the Copilot runtime via stdio, TCP, or in-process connections. Calling new CopilotClient() initializes the configuration, while client.start() spawns the runtime and establishes the JSON-RPC channel (createSessionRpc in [session.ts](https://github.com/github/copilot-sdk/blob/main/nodejs/src/session.ts) lines 81-86).
To begin handling suggestions, create a session using client.createSession(), which instantiates the CopilotSession class (lines 165-173). The session object stores event listeners, tool registries, and UI capabilities, providing the primary interface for sending prompts and receiving responses.
import { CopilotClient, approveAll } from "@github/copilot-sdk";
const client = new CopilotClient(); // defaults to stdio
await client.start();
const session = await client.createSession({
model: "gpt-4o-mini",
onPermissionRequest: approveAll, // auto-approve tool use
});
Send Prompts and Listen for Responses
To dispatch a prompt, use the session.send() method (defined in [session.ts](https://github.com/github/copilot-sdk/blob/main/nodejs/src/session.ts) lines 44-61), which transmits the message to the Copilot runtime. For synchronous-style execution, session.sendAndWait() blocks until the session reaches an idle state.
The SDK exposes an event-driven API via session.on() (lines 85-110), supporting typed subscriptions to specific events or wildcard handlers. To capture the assistant's text suggestions, listen for the assistant.message event. To detect when processing completes, watch for session.idle.
// Set up listeners before sending
const done = new Promise<void>((resolve) => {
session.on("assistant.message", (ev) => {
console.log("🤖:", ev.data.content);
});
session.on("session.idle", () => resolve());
});
await session.send({ prompt: "Explain async/await in JavaScript." });
await done; // waits until idle
Handle Tool Calls and Permissions
When the assistant requires external data, it emits external_tool.requested events. The SDK routes these to registered tool handlers via _executeToolAndRespond ([session.ts](https://github.com/github/copilot-sdk/blob/main/nodejs/src/session.ts) lines 608-656), which executes your ToolHandler and returns the result via RPC.
Register tools during session creation or via registerTools (lines 994-1005). For security, tool execution requires permission approval. Handle permission.requested events through onPermissionRequest or rely on _executePermissionAndRespond (lines 672-690) to approve or deny specific tool invocations.
const session = await client.createSession({
model: "gpt-4o",
tools: [{
name: "weather",
description: "Get current weather",
handler: async (args) => {
const { city } = args as { city: string };
return `Sunny, 23°C in ${city}`;
}
}],
onPermissionRequest: approveAll,
});
session.on("external_tool.requested", (ev) => {
console.log("Executing:", ev.data.toolName);
});
Process UI Elicitation Requests
When the host supports interactive capabilities, the assistant may request user input through elicitation dialogs. Check session.capabilities.ui?.elicitation (capability getter in [session.ts](https://github.com/github/copilot-sdk/blob/main/nodejs/src/session.ts) lines 199-203) to determine UI availability.
The SDK routes elicitation.requested events to your handler via _handleElicitationRequest (lines 661-667), which invokes UI helpers like _confirm, _select, and _input (lines 545-616) to render dialogs and return user responses.
const session = await client.createSession({
model: "gpt-4",
onElicitationRequest: async (ctx) => {
// Returns boolean based on user interaction
const confirmed = await ctx.session.ui.confirm("Deploy to production?");
return confirmed ? { action: "accept" } : { action: "cancel" };
},
});
await session.send({ prompt: "Should we deploy now?" });
Monitor All Events with Wildcard Subscriptions
For debugging or comprehensive logging, subscribe to all session events using a wildcard handler. This receives every event type—including assistant.message, session.error, external_tool.requested, and permission.requested—as defined in [nodejs/src/generated/session-events.ts](https://github.com/github/copilot-sdk/blob/main/nodejs/src/generated/session-events.ts).
session.on((ev) => {
console.log(`[${ev.type}]`, ev.data);
});
Wildcard subscriptions are processed alongside specific listeners, allowing you to log all traffic while handling specific events with dedicated callbacks.
Summary
- Create a
CopilotClientto manage the runtime lifecycle and global configuration. - Instantiate
CopilotSessionviaclient.createSession()to maintain conversation state and event handlers. - Send prompts using
session.send()orsession.sendAndWait(), then capture output viaassistant.messageevents. - Register tool handlers and permission callbacks to manage external tool execution and security approvals.
- Check capabilities before invoking UI methods like
session.ui.confirm()to ensure host support. - Use wildcard listeners for debugging or generic event logging across the entire session lifecycle.
Frequently Asked Questions
What is the difference between send() and sendAndWait()?
The send() method (lines 44-61 in session.ts) dispatches a prompt asynchronously and returns immediately, requiring you to listen for session.idle to detect completion. In contrast, sendAndWait() blocks execution until the session transitions to an idle state, providing a synchronous-style API for simpler scripts.
How do I automatically approve all tool permissions?
Pass the approveAll helper function (exported from [nodejs/src/index.ts](https://github.com/github/copilot-sdk/blob/main/nodejs/src/index.ts)) to the onPermissionRequest option when creating a session. This bypasses the _executePermissionAndRespond validation (lines 672-690) and automatically approves every tool invocation.
Can I use the SDK without UI capabilities?
Yes. UI features are optional and depend on the host runtime configuration. Check session.capabilities.ui (lines 199-203 in session.ts) before calling elicitation methods. If unsupported, the assistant will not emit elicitation.requested events, and you can rely solely on text-based assistant.message events.
Where are the RPC method signatures defined?
Auto-generated RPC method signatures reside in [nodejs/src/generated/rpc.ts](https://github.com/github/copilot-sdk/blob/main/nodejs/src/generated/rpc.ts), while session event payload definitions are located in [nodejs/src/generated/session-events.ts](https://github.com/github/copilot-sdk/blob/main/nodejs/src/generated/session-events.ts). These generated files provide the type definitions used by the JSON-RPC channel established in session.ts lines 81-86.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →