GitHub Copilot SDK
Overview
The GitHub Copilot SDK exposes the same Copilot CLI agent runtime over JSON-RPC, so apps can drive Copilot programmatically instead of building their own orchestration layer.
Status: Public preview
SDKs: Node.js/TypeScript, Python, Go, .NET, Java
Architecture: Application -> SDK client -> JSON-RPC -> Copilot CLI
How to use this skill
When helping with the Copilot SDK:
- Prefer the official docs index and the language-specific README over memory.
- Treat the top-level SDK README plus
docs/ as the source of truth for shared behavior.
- Call out preview status when stability or breaking changes matter.
- Avoid hardcoding model lists when runtime discovery via
listModels() is available.
- Watch for stale guidance around permissions, lifecycle methods, and event names.
Current source of truth
Core SDK docs
Language-specific docs
Copilot CLI and GitHub Docs
Recipes and examples
High-value facts
Authentication and prerequisites
- A GitHub Copilot subscription is required for normal SDK use.
- BYOK is supported and does not require GitHub Copilot authentication.
- Node.js, Python, and .NET bundle the Copilot CLI automatically.
- Go can use an installed CLI or embed/bundle one with the
go tool bundler workflow.
- Java currently lives in
github/copilot-sdk-java and expects the CLI to be installed separately.
- Azure Managed Identity / Entra auth is supported as a documented BYOK pattern by passing short-lived bearer tokens from
DefaultAzureCredential.
Permissions
- The SDK uses a deny-by-default permission model.
- In practice, create/resume flows should provide an explicit permission handler such as:
- TypeScript:
approveAll
- Python:
PermissionHandler.approve_all
- Go:
copilot.PermissionHandler.ApproveAll
- .NET:
PermissionHandler.ApproveAll
- Java:
PermissionHandler.APPROVE_ALL
Session lifecycle
- Preferred cleanup method:
disconnect()
- Deprecated cleanup method:
destroy()
- To resume sessions reliably, provide your own
sessionId when creating them.
- BYOK provider configuration must be provided again when resuming because keys are not persisted.
Transport and deployment
- Default transport is stdio with an SDK-managed CLI process.
- You can connect to an external headless CLI server via
cliUrl.
- Current external server docs use:
copilot --headless --port 4321
Models
- Do not hardcode model support unless the user specifically needs a fixed list.
- Prefer
client.listModels() and the official supported-models page.
reasoningEffort exists for models that support it.
Installation
| SDK |
Install |
| Node.js / TypeScript |
npm install @github/copilot-sdk |
| Python |
pip install github-copilot-sdk |
| Go |
go get github.com/github/copilot-sdk/go |
| .NET |
dotnet add package GitHub.Copilot.SDK |
| Java |
Maven/Gradle package com.github:copilot-sdk-java |
Setup and deployment choices
Pick the setup that matches the application shape:
- Local CLI - simplest path for personal tools and development.
- Bundled CLI - ship a CLI binary with your app for desktop/distributable tooling.
- Backend services - run the CLI in headless mode and connect with
cliUrl.
- Scaling and multi-tenancy - shared CLI vs CLI-per-user, shared storage, and session locking.
- Azure Managed Identity - use BYOK with short-lived bearer tokens instead of static API keys when Azure auth is the real requirement.
Quick start pattern
Use the same mental model in every language:
- Create/start the client.
- Create a session with a permission handler.
- Register event handlers before
send() if you need streaming or progress.
- Send with
send() or sendAndWait().
- Wait for
session.idle or the returned final message.
disconnect() the session and stop/dispose the client.
TypeScript example
import { CopilotClient, approveAll } from "@github/copilot-sdk";
const client = new CopilotClient();
await client.start();
const session = await client.createSession({
model: "gpt-5",
streaming: true,
onPermissionRequest: approveAll,
});
session.on("assistant.message_delta", (event) => {
process.stdout.write(event.data.deltaContent ?? "");
});
await session.sendAndWait({ prompt: "What is 2+2?" });
await session.disconnect();
await client.stop();
Core capabilities to remember
Client and session APIs
Common operations across SDKs:
- Client lifecycle:
start(), stop(), forceStop()
- Session lifecycle:
createSession(), resumeSession(), disconnect()
- Messaging:
send(), sendAndWait(), abort(), getMessages()
- Discovery:
listModels(), listSessions(), getStatus() / ping()
Events and streaming
- Final assistant output arrives in
assistant.message.
- Streaming text arrives in
assistant.message_delta.
session.idle is the reliable "turn complete" signal.
- The event system now includes reasoning, tool progress, permission, elicitation, sub-agent, and skill events.
See references/event-system.md.
Custom tools
- Node uses
defineTool(...) with Zod or raw JSON Schema.
- Python uses
@define_tool with Pydantic models.
- Go prefers
DefineTool(...).
- .NET uses
AIFunctionFactory.Create(...).
- Overriding built-ins always requires explicit opt-in:
- TypeScript:
overridesBuiltInTool: true
- Python:
overrides_built_in_tool=True
- Go:
OverridesBuiltInTool = true
- .NET:
AdditionalProperties["is_override"] = true
- Custom tools can also opt into
skipPermission.
Custom agents, MCP, hooks, and skills
customAgents lets you define sub-agents per session.
mcpServers attaches local or remote MCP servers.
- Hooks provide control points such as
onPreToolUse, onPostToolUse, onUserPromptSubmitted, and lifecycle/error hooks.
- Skills are loaded with
skillDirectories; disable selectively with disabledSkills.
See references/cli-agents-mcp.md.
Attachments, commands, and interaction
- Sessions can send file, directory, and image attachments.
- Image input supports both file and blob attachments, and vision should be checked through model capabilities.
- In-flight messaging supports
mode: "immediate" for steering and mode: "enqueue" for queueing.
- The SDK can register custom slash
commands.
- Apps can answer user questions with
onUserInputRequest.
- Rich UI prompts are available through elicitation handlers and
session.ui when the connected client supports them.
Telemetry and observability
- The SDK supports OpenTelemetry configuration through
TelemetryConfig.
- Trace context propagation is built in, with Node using an explicit
onGetTraceContext callback for outbound propagation.
Persistence and long-running work
- Use a stable
sessionId for resumable sessions.
- Use
infiniteSessions for long-running workflows that may need compaction.
- Session state is stored under
~/.copilot/session-state/ unless configuration overrides it.
SDK vs. CLI-only features
- The SDK exposes programmatic surfaces for sessions, models, plans, mode switching, workspace files, custom agents, hooks, MCP, skills, and telemetry.
- Many terminal UX features remain CLI-only, such as most slash-command workflows, interactive pickers, and export/share commands.
- When translating a CLI workflow into app code, check the compatibility guide before assuming a slash command has an SDK equivalent.
Language conventions
| Concept |
TypeScript |
Python |
Go |
.NET |
Java |
| Create session |
createSession() |
create_session() |
CreateSession() |
CreateSessionAsync() |
createSession() |
| Resume session |
resumeSession() |
resume_session() |
ResumeSession() |
ResumeSessionAsync() |
resumeSession() |
| Final content |
event.data.content |
event.data.content |
*event.Data.Content |
evt.Data.Content |
event.getData().content() |
| Delta content |
event.data.deltaContent |
event.data.delta_content |
*event.Data.DeltaContent |
evt.Data.DeltaContent |
event.getData().deltaContent() |
| Skills field |
skillDirectories |
skill_directories |
SkillDirectories |
SkillDirectories |
setSkillDirectories(...) |
Common gotchas
- The SDK is public preview, so older examples drift quickly.
- Hardcoded model tables get stale; prefer runtime discovery.
destroy() still appears in older examples but disconnect() is the current method.
- A missing permission handler causes confusion fast; treat it as required for real sessions.
assistant.message and assistant.message_delta use event.data.*, not top-level event.content.
- Streaming/event subscriptions should be attached before
send().
- Session resumption without a caller-provided
sessionId is awkward to operationalize.
Local reference files in this skill
references/working-examples.md - current starter examples, including tools and resume patterns
references/event-system.md - event names, lifecycle, and language access patterns
references/cli-agents-mcp.md - custom agents, skills, MCP, headless CLI, and config locations
references/troubleshooting.md - common failures, debug logging, auth, permissions, and transport issues
1---2name: copilot-sdk-23description: This skill helps with GitHub Copilot SDK work across Node.js/TypeScript, Python, Go, .NET, and Java. It covers setup, authentication, permissions, streaming events, custom tools, custom agents, MCP servers, hooks, skills, and session persistence.4---56# GitHub Copilot SDK78## Overview910The GitHub Copilot SDK exposes the same Copilot CLI agent runtime over JSON-RPC, so apps can drive Copilot programmatically instead of building their own orchestration layer.1112**Status:** Public preview 13**SDKs:** Node.js/TypeScript, Python, Go, .NET, Java 14**Architecture:** Application -> SDK client -> JSON-RPC -> Copilot CLI1516## How to use this skill1718When helping with the Copilot SDK:19201. Prefer the official docs index and the language-specific README over memory.212. Treat the top-level SDK README plus `docs/` as the source of truth for shared behavior.223. Call out preview status when stability or breaking changes matter.234. Avoid hardcoding model lists when runtime discovery via `listModels()` is available.245. Watch for stale guidance around permissions, lifecycle methods, and event names.2526## Current source of truth2728### Core SDK docs2930- [GitHub Copilot SDK repository](https://github.com/github/copilot-sdk)31- [Documentation index](https://github.com/github/copilot-sdk/blob/main/docs/index.md)32- [Getting started guide](https://github.com/github/copilot-sdk/blob/main/docs/getting-started.md)33- [Setup guides](https://github.com/github/copilot-sdk/blob/main/docs/setup/index.md)34- [Local CLI setup](https://github.com/github/copilot-sdk/blob/main/docs/setup/local-cli.md)35- [Bundled CLI setup](https://github.com/github/copilot-sdk/blob/main/docs/setup/bundled-cli.md)36- [Backend services setup](https://github.com/github/copilot-sdk/blob/main/docs/setup/backend-services.md)37- [Scaling and multi-tenancy](https://github.com/github/copilot-sdk/blob/main/docs/setup/scaling.md)38- [Azure Managed Identity with BYOK](https://github.com/github/copilot-sdk/blob/main/docs/setup/azure-managed-identity.md)39- [Authentication](https://github.com/github/copilot-sdk/blob/main/docs/auth/index.md)40- [BYOK](https://github.com/github/copilot-sdk/blob/main/docs/auth/byok.md)41- [Features index](https://github.com/github/copilot-sdk/blob/main/docs/features/index.md)42- [Image input](https://github.com/github/copilot-sdk/blob/main/docs/features/image-input.md)43- [Steering and queueing](https://github.com/github/copilot-sdk/blob/main/docs/features/steering-and-queueing.md)44- [OpenTelemetry instrumentation](https://github.com/github/copilot-sdk/blob/main/docs/observability/opentelemetry.md)45- [Troubleshooting](https://github.com/github/copilot-sdk/blob/main/docs/troubleshooting/debugging.md)46- [SDK/CLI compatibility](https://github.com/github/copilot-sdk/blob/main/docs/troubleshooting/compatibility.md)4748### Language-specific docs4950- [Node.js / TypeScript README](https://github.com/github/copilot-sdk/blob/main/nodejs/README.md)51- [Python README](https://github.com/github/copilot-sdk/blob/main/python/README.md)52- [Go README](https://github.com/github/copilot-sdk/blob/main/go/README.md)53- [.NET README](https://github.com/github/copilot-sdk/blob/main/dotnet/README.md)54- [Java SDK repository](https://github.com/github/copilot-sdk-java)5556### Copilot CLI and GitHub Docs5758- [About GitHub Copilot CLI](https://docs.github.com/en/copilot/concepts/agents/about-copilot-cli)59- [Using GitHub Copilot CLI](https://docs.github.com/en/copilot/how-tos/use-copilot-agents/use-copilot-cli)60- [Custom agents configuration reference](https://docs.github.com/en/copilot/reference/custom-agents-configuration)61- [Enhancing agent mode with MCP](https://docs.github.com/en/copilot/tutorials/enhance-agent-mode-with-mcp)62- [Supported models](https://docs.github.com/en/copilot/reference/ai-models/supported-models)6364### Recipes and examples6566- [Copilot SDK cookbook](https://github.com/github/awesome-copilot/blob/main/cookbook/copilot-sdk/README.md)67- [Node.js samples](https://github.com/github/copilot-sdk/tree/main/nodejs/samples)68- [Go samples](https://github.com/github/copilot-sdk/tree/main/go/samples)69- [.NET samples](https://github.com/github/copilot-sdk/tree/main/dotnet/samples)7071---7273## High-value facts7475### Authentication and prerequisites7677- A GitHub Copilot subscription is required for normal SDK use.78- BYOK is supported and does **not** require GitHub Copilot authentication.79- Node.js, Python, and .NET bundle the Copilot CLI automatically.80- Go can use an installed CLI or embed/bundle one with the `go tool bundler` workflow.81- Java currently lives in `github/copilot-sdk-java` and expects the CLI to be installed separately.82- Azure Managed Identity / Entra auth is supported as a documented BYOK pattern by passing short-lived bearer tokens from `DefaultAzureCredential`.8384### Permissions8586- The SDK uses a deny-by-default permission model.87- In practice, create/resume flows should provide an explicit permission handler such as:88 - TypeScript: `approveAll`89 - Python: `PermissionHandler.approve_all`90 - Go: `copilot.PermissionHandler.ApproveAll`91 - .NET: `PermissionHandler.ApproveAll`92 - Java: `PermissionHandler.APPROVE_ALL`9394### Session lifecycle9596- Preferred cleanup method: `disconnect()`97- Deprecated cleanup method: `destroy()`98- To resume sessions reliably, provide your own `sessionId` when creating them.99- BYOK provider configuration must be provided again when resuming because keys are not persisted.100101### Transport and deployment102103- Default transport is stdio with an SDK-managed CLI process.104- You can connect to an external headless CLI server via `cliUrl`.105- Current external server docs use:106107```bash108copilot --headless --port 4321109```110111### Models112113- Do not hardcode model support unless the user specifically needs a fixed list.114- Prefer `client.listModels()` and the official supported-models page.115- `reasoningEffort` exists for models that support it.116117---118119## Installation120121| SDK | Install |122| --- | --- |123| Node.js / TypeScript | `npm install @github/copilot-sdk` |124| Python | `pip install github-copilot-sdk` |125| Go | `go get github.com/github/copilot-sdk/go` |126| .NET | `dotnet add package GitHub.Copilot.SDK` |127| Java | Maven/Gradle package `com.github:copilot-sdk-java` |128129## Setup and deployment choices130131Pick the setup that matches the application shape:132133- **Local CLI** - simplest path for personal tools and development.134- **Bundled CLI** - ship a CLI binary with your app for desktop/distributable tooling.135- **Backend services** - run the CLI in headless mode and connect with `cliUrl`.136- **Scaling and multi-tenancy** - shared CLI vs CLI-per-user, shared storage, and session locking.137- **Azure Managed Identity** - use BYOK with short-lived bearer tokens instead of static API keys when Azure auth is the real requirement.138139## Quick start pattern140141Use the same mental model in every language:1421431. Create/start the client.1442. Create a session with a permission handler.1453. Register event handlers before `send()` if you need streaming or progress.1464. Send with `send()` or `sendAndWait()`.1475. Wait for `session.idle` or the returned final message.1486. `disconnect()` the session and stop/dispose the client.149150### TypeScript example151152```typescript153import { CopilotClient, approveAll } from "@github/copilot-sdk";154155const client = new CopilotClient();156await client.start();157158const session = await client.createSession({159 model: "gpt-5",160 streaming: true,161 onPermissionRequest: approveAll,162});163164session.on("assistant.message_delta", (event) => {165 process.stdout.write(event.data.deltaContent ?? "");166});167168await session.sendAndWait({ prompt: "What is 2+2?" });169170await session.disconnect();171await client.stop();172```173174---175176## Core capabilities to remember177178### Client and session APIs179180Common operations across SDKs:181182- Client lifecycle: `start()`, `stop()`, `forceStop()`183- Session lifecycle: `createSession()`, `resumeSession()`, `disconnect()`184- Messaging: `send()`, `sendAndWait()`, `abort()`, `getMessages()`185- Discovery: `listModels()`, `listSessions()`, `getStatus()` / `ping()`186187### Events and streaming188189- Final assistant output arrives in `assistant.message`.190- Streaming text arrives in `assistant.message_delta`.191- `session.idle` is the reliable "turn complete" signal.192- The event system now includes reasoning, tool progress, permission, elicitation, sub-agent, and skill events.193194See `references/event-system.md`.195196### Custom tools197198- Node uses `defineTool(...)` with Zod or raw JSON Schema.199- Python uses `@define_tool` with Pydantic models.200- Go prefers `DefineTool(...)`.201- .NET uses `AIFunctionFactory.Create(...)`.202- Overriding built-ins always requires explicit opt-in:203 - TypeScript: `overridesBuiltInTool: true`204 - Python: `overrides_built_in_tool=True`205 - Go: `OverridesBuiltInTool = true`206 - .NET: `AdditionalProperties["is_override"] = true`207- Custom tools can also opt into `skipPermission`.208209### Custom agents, MCP, hooks, and skills210211- `customAgents` lets you define sub-agents per session.212- `mcpServers` attaches local or remote MCP servers.213- Hooks provide control points such as `onPreToolUse`, `onPostToolUse`, `onUserPromptSubmitted`, and lifecycle/error hooks.214- Skills are loaded with `skillDirectories`; disable selectively with `disabledSkills`.215216See `references/cli-agents-mcp.md`.217218### Attachments, commands, and interaction219220- Sessions can send file, directory, and image attachments.221- Image input supports both file and blob attachments, and vision should be checked through model capabilities.222- In-flight messaging supports `mode: "immediate"` for steering and `mode: "enqueue"` for queueing.223- The SDK can register custom slash `commands`.224- Apps can answer user questions with `onUserInputRequest`.225- Rich UI prompts are available through elicitation handlers and `session.ui` when the connected client supports them.226227### Telemetry and observability228229- The SDK supports OpenTelemetry configuration through `TelemetryConfig`.230- Trace context propagation is built in, with Node using an explicit `onGetTraceContext` callback for outbound propagation.231232### Persistence and long-running work233234- Use a stable `sessionId` for resumable sessions.235- Use `infiniteSessions` for long-running workflows that may need compaction.236- Session state is stored under `~/.copilot/session-state/` unless configuration overrides it.237238### SDK vs. CLI-only features239240- The SDK exposes programmatic surfaces for sessions, models, plans, mode switching, workspace files, custom agents, hooks, MCP, skills, and telemetry.241- Many terminal UX features remain CLI-only, such as most slash-command workflows, interactive pickers, and export/share commands.242- When translating a CLI workflow into app code, check the compatibility guide before assuming a slash command has an SDK equivalent.243244---245246## Language conventions247248| Concept | TypeScript | Python | Go | .NET | Java |249| --- | --- | --- | --- | --- | --- |250| Create session | `createSession()` | `create_session()` | `CreateSession()` | `CreateSessionAsync()` | `createSession()` |251| Resume session | `resumeSession()` | `resume_session()` | `ResumeSession()` | `ResumeSessionAsync()` | `resumeSession()` |252| Final content | `event.data.content` | `event.data.content` | `*event.Data.Content` | `evt.Data.Content` | `event.getData().content()` |253| Delta content | `event.data.deltaContent` | `event.data.delta_content` | `*event.Data.DeltaContent` | `evt.Data.DeltaContent` | `event.getData().deltaContent()` |254| Skills field | `skillDirectories` | `skill_directories` | `SkillDirectories` | `SkillDirectories` | `setSkillDirectories(...)` |255256---257258## Common gotchas259260- The SDK is **public preview**, so older examples drift quickly.261- Hardcoded model tables get stale; prefer runtime discovery.262- `destroy()` still appears in older examples but `disconnect()` is the current method.263- A missing permission handler causes confusion fast; treat it as required for real sessions.264- `assistant.message` and `assistant.message_delta` use `event.data.*`, not top-level `event.content`.265- Streaming/event subscriptions should be attached before `send()`.266- Session resumption without a caller-provided `sessionId` is awkward to operationalize.267268---269270## Local reference files in this skill271272- `references/working-examples.md` - current starter examples, including tools and resume patterns273- `references/event-system.md` - event names, lifecycle, and language access patterns274- `references/cli-agents-mcp.md` - custom agents, skills, MCP, headless CLI, and config locations275- `references/troubleshooting.md` - common failures, debug logging, auth, permissions, and transport issues