# Changelog All notable changes to the Copilot SDK are documented in this file. This changelog is automatically generated by an AI agent when stable releases are published. See [GitHub Releases](https://github.com/github/copilot-sdk/releases) for the full list. ## [v1.0.7](https://github.com/github/copilot-sdk/releases/tag/v1.0.7) (2026-07-16) ### Feature: in-process (FFI) transport The SDK can now host the Copilot runtime in-process by loading the native runtime library via its C ABI (FFI), eliminating the overhead of spawning a child process. This experimental transport is available for Node.js, Rust, Python, and Go. ([#1953](https://github.com/github/copilot-sdk/pull/1953), [#1915](https://github.com/github/copilot-sdk/pull/1915), [#1975](https://github.com/github/copilot-sdk/pull/1975), [#1976](https://github.com/github/copilot-sdk/pull/1976)) ```ts const client = new CopilotClient({ connection: RuntimeConnection.forInProcess() }); ``` ```cs var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.ForInProcess() }); ``` ### Feature: tool search configuration A new `toolSearch` session option controls how the SDK defers tools when the total tool count exceeds a threshold. When enabled (the default), excess MCP and external tools are surfaced on demand through the built-in `tool_search_tool` rather than pre-loaded into every prompt. Tool results can also include `toolReferences` to link cited sources back to the tool that produced them. ([#1933](https://github.com/github/copilot-sdk/pull/1933)) ```ts const session = await client.createSession({ toolSearch: { defer: "auto" }, }); ``` ```cs var session = await client.CreateSessionAsync(new SessionConfig { ToolSearch = new ToolSearchConfig { Defer = "auto" }, }); ``` ### Feature: opaque metadata passthrough on tool definitions Tool definitions now accept an optional `metadata` bag that is forwarded verbatim in `session.create` and `session.resume` RPC calls. This lets hosts attach namespaced, implementation-specific metadata to tools without expanding the typed public contract; unknown keys are preserved and round-tripped untouched. ([#1864](https://github.com/github/copilot-sdk/pull/1864)) ```ts session.defineTool("my-tool", { metadata: { "myapp:priority": 1 } }, handler); ``` ```cs session.DefineTool("my-tool", new ToolOptions { Metadata = new() { ["myapp:priority"] = 1 } }, handler); ``` ### Other changes - feature: **[All SDKs]** add `canvasProvider` field to session create/resume config so hosts can supply a stable canvas-provider identity that survives cold resume ([#1847](https://github.com/github/copilot-sdk/pull/1847)) - feature: **[All SDKs]** forward `enableManagedSettings` flag in session create/resume for enterprise managed-settings enforcement ([#1925](https://github.com/github/copilot-sdk/pull/1925)) - feature: **[All SDKs]** propagate `agentId`, `parentAgentId`, and `interactionType` from LLM inference start frames into request-handler contexts ([#1949](https://github.com/github/copilot-sdk/pull/1949)) - improvement: **[Rust]** make tool schema and MCP server serialization deterministic by replacing `HashMap` with `IndexMap` ([#1931](https://github.com/github/copilot-sdk/pull/1931)) - improvement: **[Rust]** use `native-tls` for the build-time CLI download ([#1964](https://github.com/github/copilot-sdk/pull/1964)) - bugfix: **[.NET]** avoid Windows in-process test teardown deadlock ([#1997](https://github.com/github/copilot-sdk/pull/1997)) ### New contributors - @agoncal made their first contribution in [#1951](https://github.com/github/copilot-sdk/pull/1951) - @Shivam60 made their first contribution in [#1964](https://github.com/github/copilot-sdk/pull/1964) - @rinceyuan made their first contribution in [#1978](https://github.com/github/copilot-sdk/pull/1978) - @belaltaher8 made their first contribution in [#1864](https://github.com/github/copilot-sdk/pull/1864) ## [java/v1.0.6](https://github.com/github/copilot-sdk/releases/tag/java/v1.0.6) (2026-07-08) ### Feature: inline lambda tool definitions Developers can now define tools directly at the call site using `ToolDefinition.from(...)` with typed lambda handlers and `Param.of(...)` parameter metadata — no separate annotated class required. Async variants (`fromAsync`) and `ToolInvocation` context injection (`fromWithToolInvocation`) are also available. ([#1895](https://github.com/github/copilot-sdk/pull/1895)) ```java ToolDefinition greet = ToolDefinition.from( "greet", "Greets a user by name", Param.of(String.class, "name", "The user's name"), name -> "Hello, " + name + "!"); ``` ### Other changes - bugfix: **[Java]** preserve explicit null map values in JSON-RPC params so user setting clears reach the CLI ([#1906](https://github.com/github/copilot-sdk/pull/1906)) - feature: **[Java]** add experimental `onGitHubTelemetry` callback on `CopilotClientOptions` for receiving forwarded GitHub telemetry events ([#1835](https://github.com/github/copilot-sdk/pull/1835)) ## [java/v1.0.5-01](https://github.com/github/copilot-sdk/releases/tag/java/v1.0.5-01) (2026-07-01) ### Feature: new session options — citations, agent exclusions, and credit limits Three new options are available on `SessionConfig` and `ResumeSessionConfig`. `enableCitations` (experimental) enables native model citations for supported providers; `excludedBuiltInAgents` hides named built-in agents from discovery; and `sessionLimits` sets a per-session AI-credit budget. ([#1865](https://github.com/github/copilot-sdk/pull/1865)) ```java SessionConfig config = new SessionConfig() .setEnableCitations(true) .setExcludedBuiltInAgents(List.of("copilot")) .setSessionLimits(new SessionLimitsConfig(100.0)); ``` ### New contributors - @coleflennikenmsft made their first contribution in [#1854](https://github.com/github/copilot-sdk/pull/1854) - @szabta89 made their first contribution in [#1856](https://github.com/github/copilot-sdk/pull/1856) ## [v1.0.5](https://github.com/github/copilot-sdk/releases/tag/v1.0.5) (2026-07-01) ### Feature: MCP OAuth host token handlers SDK applications can now handle OAuth challenges from MCP servers that require host-provided authentication. Register an `onMcpAuthRequest` callback on the session config and the SDK will invoke it whenever an MCP server responds with a `401 WWW-Authenticate` challenge; return an access token (or cancel the request). Supports initial auth, refresh, reauth, and upscope flows across all SDKs. ([#1669](https://github.com/github/copilot-sdk/pull/1669)) ```ts const session = await client.createSession({ onMcpAuthRequest: async (request) => ({ accessToken: await myIdentityProvider.getToken(request.serverUrl), }), }); ``` ```cs var session = await client.CreateSessionAsync(new SessionConfig { OnMcpAuthRequest = async ctx => McpAuthResult.FromToken(new McpAuthToken { AccessToken = await myIdentityProvider.GetTokenAsync(ctx.ServerUrl) }), }); ``` ### Feature: session options for citations, excluded agents, and spending limits Three additional session configuration options are now available across all SDKs. ([#1865](https://github.com/github/copilot-sdk/pull/1865)) ```ts const session = await client.createSession({ enableCitations: true, excludedBuiltinAgents: ["github-search"], sessionLimits: { maxAiCredits: 10 }, }); ``` ```cs var session = await client.CreateSessionAsync(new SessionConfig { EnableCitations = true, ExcludedBuiltInAgents = ["github-search"], SessionLimits = new SessionLimitsConfig { MaxAiCredits = 10 }, }); ``` ### Other changes - improvement: **[All SDKs]** rename BYOK callback field `getBearerToken` → `bearerTokenProvider`; add `sessionId` to `ProviderTokenArgs` for per-session token scoping ([#1796](https://github.com/github/copilot-sdk/pull/1796)) - bugfix: **[Node]** fix MCP OAuth `registerInterest` sent before `session.resume`, causing "Session not found" errors when resuming a session with `onMcpAuthRequest` ([#1861](https://github.com/github/copilot-sdk/pull/1861)) - feature: **[Java]** `@CopilotTool` and `@CopilotToolParam` annotations with compile-time annotation processor for ergonomic tool registration via `ToolDefinition.fromObject()` ([#1792](https://github.com/github/copilot-sdk/pull/1792), [#1838](https://github.com/github/copilot-sdk/pull/1838)) - feature: **[Java]** `ToolInvocation` parameter injection in `@CopilotTool` methods for accessing session context without exposing it to the LLM schema ([#1832](https://github.com/github/copilot-sdk/pull/1832)) - feature: **[Rust]** add 9 GitHub-anchored variants to `Attachment` enum (`GitHubCommit`, `GitHubRelease`, `GitHubActionsJob`, `GitHubRepository`, `GitHubFileDiff`, `GitHubTreeComparison`, `GitHubUrl`, `GitHubFile`, `GitHubSnippet`) ([#1823](https://github.com/github/copilot-sdk/pull/1823)) ### New contributors - @pallaviraiturkar0 made their first contribution in [#1823](https://github.com/github/copilot-sdk/pull/1823) - @roji made their first contribution in [#1827](https://github.com/github/copilot-sdk/pull/1827) ## [java/v1.0.4](https://github.com/github/copilot-sdk/releases/tag/java/v1.0.4) (2026-06-25) ### Feature: HTTP request callback support Register a `CopilotRequestHandler` on the client to intercept every outbound LLM inference HTTP or WebSocket request — for both BYOK and CAPI — and mutate, replace, or fully forward it. Useful for logging, header injection, model substitution, or custom routing. ([#1689](https://github.com/github/copilot-sdk/pull/1689), [#1775](https://github.com/github/copilot-sdk/pull/1775), [#1784](https://github.com/github/copilot-sdk/pull/1784)) ```java final class MyHandler extends CopilotRequestHandler { @Override protected HttpResponse sendRequest(HttpRequest request, CopilotRequestContext ctx) throws Exception { HttpRequest mutated = HttpRequest.newBuilder(request, (n, v) -> true) .header("X-Debug-Session", ctx.sessionId() == null ? "none" : ctx.sessionId()) .build(); return super.sendRequest(mutated, ctx); } } CopilotClient client = new CopilotClient( new CopilotClientOptions().setRequestHandler(new MyHandler())); ``` ### Feature: `getBearerToken` callback for BYOK providers (Managed Identity) BYOK provider configs now accept a `getBearerToken` callback so the SDK consumer can resolve bearer tokens (e.g. Azure Managed Identity) on demand. The SDK takes zero Azure SDK dependency — the consumer supplies the callback using any identity library. ([#1748](https://github.com/github/copilot-sdk/pull/1748)) ```java var provider = new ProviderConfig() .setType("openai") .setBaseUrl(baseUrl) .setGetBearerToken(args -> cred.getToken(ctx).map(AccessToken::getToken).toFuture()); ``` ### Feature: experimental multi-provider BYOK registry Register multiple named providers and models on a single session via `NamedProviderConfig` and `ProviderModelConfig`. Custom agents can reference provider-qualified model IDs such as `"alpha/sonnet"`. This feature is experimental. ([#1718](https://github.com/github/copilot-sdk/pull/1718)) ### Feature: `preamble` system message section and `preserve` action Two new customization options for system message sections. `SystemMessageSections.PREAMBLE` targets only the identity preamble without affecting its sibling sub-sections (`identity` and `tool_instructions` are now documented as section groups). The new `preserve` action protects an individually-addressable section from a group-level `remove`. ([#1713](https://github.com/github/copilot-sdk/pull/1713)) ### Other changes - feature: add optional `memory` configuration (`MemoryConfiguration`) to session create and resume ([#1617](https://github.com/github/copilot-sdk/pull/1617)) - feature: `defer` parameter on tool definitions controls eager vs. lazy tool loading (`"auto"` or `"never"`) ([#1632](https://github.com/github/copilot-sdk/pull/1632)) - feature: `otlpProtocol` telemetry option for configuring OTLP export transport (`"http/json"` or `"http/protobuf"`) ([#1648](https://github.com/github/copilot-sdk/pull/1648)) - feature: `ModelBilling.tokenPrices` surfaced on public SDK types, exposing per-tier pricing and context window limits ([#1633](https://github.com/github/copilot-sdk/pull/1633)) - feature: `CapiSessionOptions.enableWebSocketResponses` and `ProviderConfig.transport` for WebSocket transport control on session create/resume ([#1711](https://github.com/github/copilot-sdk/pull/1711)) - improvement: call `runtime.shutdown` during client stop for deterministic OTEL telemetry flush before process cleanup ([#1667](https://github.com/github/copilot-sdk/pull/1667)) - improvement: rename `SystemPromptSections` → `SystemMessageSections` for cross-SDK consistency; old class deprecated with `forRemoval=true` ([#1683](https://github.com/github/copilot-sdk/pull/1683)) ### New contributors - @almaleksia made their first contribution in [#1632](https://github.com/github/copilot-sdk/pull/1632) - @dereklegenzoff made their first contribution in [#1711](https://github.com/github/copilot-sdk/pull/1711) - @ellismg made their first contribution in [#1750](https://github.com/github/copilot-sdk/pull/1750) ## [v1.0.2](https://github.com/github/copilot-sdk/releases/tag/v1.0.2) (2026-06-18) ### Feature: opt-in memory for sessions Sessions can now be configured with persistent memory, allowing the agent to recall information across turns. Set `memory: { enabled: true }` when creating or resuming a session; when omitted the runtime default applies. ([#1617](https://github.com/github/copilot-sdk/pull/1617)) ```ts const session = await client.createSession({ memory: { enabled: true }, }); ``` ```cs var session = await client.CreateSessionAsync(new SessionConfig { Memory = new MemoryConfiguration { Enabled = true } }); ``` ### Feature: `defer` parameter for tool definitions Tools now support a `defer` option controlling whether they are pre-loaded eagerly or surfaced lazily through tool search. Use `"auto"` (the default) to allow lazy loading, or `"never"` to force pre-loading. ([#1632](https://github.com/github/copilot-sdk/pull/1632)) ```ts defineTool("lookup_issue", { description: "Fetch issue details", parameters: z.object({ id: z.string() }), defer: "auto", handler: async ({ id }) => { /* ... */ }, }); ``` ```cs var tool = CopilotTool.DefineTool( async ([Description("Issue ID")] string id) => { /* ... */ }, toolOptions: new CopilotToolOptions { Defer = CopilotToolDefer.Auto }); ``` ### Other changes - feature: **[All SDKs]** add `otlpProtocol` telemetry option (`"http/json"` or `"http/protobuf"`) for configuring OTLP export transport ([#1648](https://github.com/github/copilot-sdk/pull/1648)) - feature: **[All SDKs]** surface `ModelBilling.tokenPrices` on public SDK types, exposing per-tier input/output/cache pricing and context window limits ([#1633](https://github.com/github/copilot-sdk/pull/1633)) - improvement: **[All SDKs]** call `runtime.shutdown` during normal client stop for deterministic OTEL telemetry flush before process cleanup ([#1667](https://github.com/github/copilot-sdk/pull/1667)) - improvement: **[Go]** thread `context.Context` through the JSON-RPC request path for proper cancellation support ([#1643](https://github.com/github/copilot-sdk/pull/1643)) - improvement: **[Java]** add `getOpenCanvases()` to `CopilotSession` to track currently open canvas instances, matching the other SDKs ([#1606](https://github.com/github/copilot-sdk/pull/1606)) - improvement: **[Java]** rename `SystemPromptSections` to `SystemMessageSections` for cross-SDK consistency; old class deprecated with `forRemoval=true` ([#1683](https://github.com/github/copilot-sdk/pull/1683)) - bugfix: **[Python]** round sub-millisecond durations in `to_timedelta_int` to avoid serialization errors ([#1668](https://github.com/github/copilot-sdk/pull/1668)) - bugfix: **[Rust]** skip CLI binary download in `build.rs` when `DOCS_RS` env var is set ([#1660](https://github.com/github/copilot-sdk/pull/1660)) ### New contributors - @andyfeller made their first contribution in [#1631](https://github.com/github/copilot-sdk/pull/1631) - @almaleksia made their first contribution in [#1632](https://github.com/github/copilot-sdk/pull/1632) - @idryzhov made their first contribution in [#1668](https://github.com/github/copilot-sdk/pull/1668) - @scottaddie made their first contribution in [#1636](https://github.com/github/copilot-sdk/pull/1636) ## [v0.2.2](https://github.com/github/copilot-sdk/releases/tag/v0.2.2) (2026-04-10) ### Feature: `enableConfigDiscovery` for automatic MCP and skill config loading Set `enableConfigDiscovery: true` when creating a session to let the runtime automatically discover MCP server configurations (`.mcp.json`, `.vscode/mcp.json`) and skill directories from the working directory. Discovered settings are merged with any explicitly provided values; explicit values take precedence on name collision. ([#1044](https://github.com/github/copilot-sdk/pull/1044)) ```ts const session = await client.createSession({ enableConfigDiscovery: true, }); ``` ```cs var session = await client.CreateSessionAsync(new SessionConfig { EnableConfigDiscovery = true, }); ``` - Python: `await client.create_session(enable_config_discovery=True)` - Go: `client.CreateSession(ctx, &copilot.SessionConfig{EnableConfigDiscovery: ptr(true)})` ## [v0.2.1](https://github.com/github/copilot-sdk/releases/tag/v0.2.1) (2026-04-03) ### Feature: commands and UI elicitation across all four SDKs Register slash commands that CLI users can invoke and drive interactive input dialogs from any SDK language. This feature was previously Node.js-only; it now ships in Python, Go, and .NET as well. ([#906](https://github.com/github/copilot-sdk/pull/906), [#908](https://github.com/github/copilot-sdk/pull/908), [#960](https://github.com/github/copilot-sdk/pull/960)) ```ts const session = await client.createSession({ onPermissionRequest: approveAll, commands: [{ name: "summarize", description: "Summarize the conversation", handler: async (context) => { /* ... */ }, }], onElicitationRequest: async (context) => { if (context.type === "confirm") return { action: "confirm" }; }, }); // Drive dialogs from the session const confirmed = await session.ui.confirm({ message: "Proceed?" }); const choice = await session.ui.select({ message: "Pick one", options: ["A", "B"] }); ``` ```cs var session = await client.CreateSessionAsync(new SessionConfig { OnPermissionRequest = PermissionHandler.ApproveAll, Commands = [ new CommandDefinition { Name = "summarize", Description = "Summarize the conversation", Handler = async (context) => { /* ... */ }, } ], }); // Drive dialogs from the session var confirmed = await session.Ui.ConfirmAsync(new ConfirmOptions { Message = "Proceed?" }); ``` > **⚠️ Breaking change (Node.js):** The `onElicitationRequest` handler signature changed from two arguments (`request, invocation`) to a single `ElicitationContext` that combines both. Update callers to use `context.sessionId` and `context.message` directly. ### Feature: `session.getMetadata` across all SDKs Efficiently fetch metadata for a single session by ID without listing all sessions. Returns `undefined`/`null` (not an error) when the session is not found. ([#899](https://github.com/github/copilot-sdk/pull/899)) - TypeScript: `const meta = await client.getSessionMetadata(sessionId);` - C#: `var meta = await client.GetSessionMetadataAsync(sessionId);` - Python: `meta = await client.get_session_metadata(session_id)` - Go: `meta, err := client.GetSessionMetadata(ctx, sessionID)` ### Feature: `sessionFs` for virtualizing per-session storage (Node SDK) Supply a custom `sessionFs` adapter in Node SDK session config to redirect the runtime's per-session storage (event log, large output files) to any backing store — useful for serverless deployments or custom persistence layers. ([#917](https://github.com/github/copilot-sdk/pull/917)) ### Other changes - bugfix: structured tool results (with `toolTelemetry`, `resultType`, etc.) now sent via RPC as objects instead of being stringified, preserving metadata for Node, Go, and Python SDKs ([#970](https://github.com/github/copilot-sdk/pull/970)) - feature: **[Python]** `CopilotClient` and `CopilotSession` now support `async with` for automatic resource cleanup ([#475](https://github.com/github/copilot-sdk/pull/475)) - improvement: **[Python]** `copilot.types` module removed; import types directly from `copilot` ([#871](https://github.com/github/copilot-sdk/pull/871)) - improvement: **[Python]** `workspace_path` now accepts any `os.PathLike` and `session.workspace_path` returns a `pathlib.Path` ([#901](https://github.com/github/copilot-sdk/pull/901)) - improvement: **[Go]** simplified `rpc` package API: renamed structs drop the redundant `Rpc` infix (e.g. `ModelRpcApi` → `ModelApi`) ([#905](https://github.com/github/copilot-sdk/pull/905)) - fix: **[Go]** `Session.SetModel` now takes a pointer for optional options instead of a variadic argument ([#904](https://github.com/github/copilot-sdk/pull/904)) ### New contributors - @Sumanth007 made their first contribution in [#475](https://github.com/github/copilot-sdk/pull/475) - @jongalloway made their first contribution in [#957](https://github.com/github/copilot-sdk/pull/957) - @Morabbin made their first contribution in [#970](https://github.com/github/copilot-sdk/pull/970) - @schneidafunk made their first contribution in [#998](https://github.com/github/copilot-sdk/pull/998) ## [v0.2.0](https://github.com/github/copilot-sdk/releases/tag/v0.2.0) (2026-03-20) This is a big update with a broad round of API refinements, new capabilities, and cross-SDK consistency improvements that have shipped incrementally through preview releases since v0.1.32. ## Highlights ### Fine-grained system prompt customization A new `"customize"` mode for `systemMessage` lets you surgically edit individual sections of the Copilot system prompt — without replacing the entire thing. Ten sections are configurable: `identity`, `tone`, `tool_efficiency`, `environment_context`, `code_change_rules`, `guidelines`, `safety`, `tool_instructions`, `custom_instructions`, and `last_instructions`. Each section supports four static actions (`replace`, `remove`, `append`, `prepend`) and a `transform` callback that receives the current rendered content and returns modified text — useful for regex mutations, conditional edits, or logging what the prompt contains. ([#816](https://github.com/github/copilot-sdk/pull/816)) ```ts const session = await client.createSession({ onPermissionRequest: approveAll, systemMessage: { mode: "customize", sections: { identity: { action: (current) => current.replace("GitHub Copilot", "Acme Assistant"), }, tone: { action: "replace", content: "Be concise and professional." }, code_change_rules: { action: "remove" }, }, }, }); ``` ```cs var session = await client.CreateSessionAsync(new SessionConfig { OnPermissionRequest = PermissionHandler.ApproveAll, SystemMessage = new SystemMessageConfig { Mode = SystemMessageMode.Customize, Sections = new Dictionary { ["identity"] = new() { Transform = current => Task.FromResult(current.Replace("GitHub Copilot", "Acme Assistant")), }, ["tone"] = new() { Action = SectionOverrideAction.Replace, Content = "Be concise and professional." }, ["code_change_rules"] = new() { Action = SectionOverrideAction.Remove }, }, }, }); ``` ### OpenTelemetry support across all SDKs All four SDK languages now support distributed tracing with the Copilot CLI. Set `telemetry` in your client options to configure an OTLP exporter; W3C trace context is automatically propagated on `session.create`, `session.resume`, and `session.send`, and restored in tool handlers so tool execution is linked to the originating trace. ([#785](https://github.com/github/copilot-sdk/pull/785)) ```ts const client = new CopilotClient({ telemetry: { otlpEndpoint: "http://localhost:4318", sourceName: "my-app", }, }); ``` ```cs var client = new CopilotClient(new CopilotClientOptions { Telemetry = new TelemetryConfig { OtlpEndpoint = "http://localhost:4318", SourceName = "my-app", }, }); ``` - Python: `CopilotClient(SubprocessConfig(telemetry={"otlp_endpoint": "http://localhost:4318", "source_name": "my-app"}))` - Go: `copilot.NewClient(&copilot.ClientOptions{Telemetry: &copilot.TelemetryConfig{OTLPEndpoint: "http://localhost:4318", SourceName: "my-app"}})` ### Blob attachments for inline binary data A new `blob` attachment type lets you send images or other binary content directly to a session without writing to disk — useful when data is already in memory (screenshots, API responses, generated images). ([#731](https://github.com/github/copilot-sdk/pull/731)) ```ts await session.send({ prompt: "What's in this image?", attachments: [{ type: "blob", data: base64Str, mimeType: "image/png" }], }); ``` ```cs await session.SendAsync(new MessageOptions { Prompt = "What's in this image?", Attachments = [new UserMessageDataAttachmentsItemBlob { Data = base64Str, MimeType = "image/png" }], }); ``` ### Pre-select a custom agent at session creation You can now specify which custom agent should be active when a session starts, eliminating the need for a separate `session.rpc.agent.select()` call. ([#722](https://github.com/github/copilot-sdk/pull/722)) ```ts const session = await client.createSession({ customAgents: [ { name: "researcher", prompt: "You are a research assistant." }, { name: "editor", prompt: "You are a code editor." }, ], agent: "researcher", onPermissionRequest: approveAll, }); ``` ```cs var session = await client.CreateSessionAsync(new SessionConfig { CustomAgents = [ new CustomAgentConfig { Name = "researcher", Prompt = "You are a research assistant." }, new CustomAgentConfig { Name = "editor", Prompt = "You are a code editor." }, ], Agent = "researcher", OnPermissionRequest = PermissionHandler.ApproveAll, }); ``` --- ## New features - **`skipPermission` on tool definitions** — Tools can now be registered with `skipPermission: true` to bypass the confirmation prompt for low-risk operations like read-only queries. Available in all four SDKs. ([#808](https://github.com/github/copilot-sdk/pull/808)) - **`reasoningEffort` when switching models** — All SDKs now accept an optional `reasoningEffort` parameter in `setModel()` for models that support it. ([#712](https://github.com/github/copilot-sdk/pull/712)) - **Custom model listing for BYOK** — Applications using bring-your-own-key providers can supply `onListModels` in client options to override `client.listModels()` with their own model list. ([#730](https://github.com/github/copilot-sdk/pull/730)) - **`no-result` permission outcome** — Permission handlers can now return `"no-result"` so extensions can attach to sessions without actively answering permission requests. ([#802](https://github.com/github/copilot-sdk/pull/802)) - **`SessionConfig.onEvent` catch-all** — A new `onEvent` handler on session config is registered *before* the RPC is issued, guaranteeing that early events like `session.start` are never dropped. ([#664](https://github.com/github/copilot-sdk/pull/664)) - **Node.js CJS compatibility** — The Node.js SDK now ships both ESM and CJS builds, fixing crashes in VS Code extensions and other tools bundled with esbuild's `format: "cjs"`. No changes needed in consumer code. ([#546](https://github.com/github/copilot-sdk/pull/546)) - **Experimental API annotations** — APIs marked experimental in the schema (agent, fleet, compaction groups) are now annotated in all four SDKs: `[Experimental]` in C#, `/** @experimental */` in TypeScript, and comments in Python and Go. ([#875](https://github.com/github/copilot-sdk/pull/875)) - **System notifications and session log APIs** — Updated to match the latest CLI runtime, adding `system.notification` events and a session log RPC API. ([#737](https://github.com/github/copilot-sdk/pull/737)) ## Improvements - **[.NET, Go]** Serialize event dispatch so handlers are invoked in registration order with no concurrent calls ([#791](https://github.com/github/copilot-sdk/pull/791)) - **[Go]** Detach CLI process lifespan from the context passed to `Client.Start` so cancellation no longer kills the child process ([#689](https://github.com/github/copilot-sdk/pull/689)) - **[Go]** Stop RPC client logging expected EOF errors ([#609](https://github.com/github/copilot-sdk/pull/609)) - **[.NET]** Emit XML doc comments from schema descriptions in generated RPC code ([#724](https://github.com/github/copilot-sdk/pull/724)) - **[.NET]** Use lazy property initialization in generated RPC classes ([#725](https://github.com/github/copilot-sdk/pull/725)) - **[.NET]** Add `DebuggerDisplay` attribute to `SessionEvent` for easier debugging ([#726](https://github.com/github/copilot-sdk/pull/726)) - **[.NET]** Optional RPC params are now represented as optional method params for forward-compatible generated code ([#733](https://github.com/github/copilot-sdk/pull/733)) - **[.NET]** Replace `Task.WhenAny` + `Task.Delay` timeout pattern with `.WaitAsync(TimeSpan)` ([#805](https://github.com/github/copilot-sdk/pull/805)) - **[.NET]** Add NuGet package icon ([#688](https://github.com/github/copilot-sdk/pull/688)) - **[Node]** Don't resolve `cliPath` when `cliUrl` is already set ([#787](https://github.com/github/copilot-sdk/pull/787)) ## New RPC methods We've added low-level RPC methods to control a lot more of what's going on in the session. These are emerging APIs that don't yet have friendly wrappers, and some may be flagged as experimental or subject to change. - `session.rpc.skills.list()`, `.enable(name)`, `.disable(name)`, `.reload()` - `session.rpc.mcp.list()`, `.enable(name)`, `.disable(name)`, `.reload()` - `session.rpc.extensions.list()`, `.enable(name)`, `.disable(name)`, `.reload()` - `session.rpc.plugins.list()` - `session.rpc.ui.elicitation(...)` — structured user input - `session.rpc.shell.exec(command)`, `.kill(pid)` - `session.log(message, level, ephemeral)` In an forthcoming update, we'll add friendlier wrappers for these. ## Bug fixes - **[.NET]** Fix `SessionEvent.ToJson()` failing for events with `JsonElement`-backed payloads (`assistant.message`, `tool.execution_start`, etc.) ([#868](https://github.com/github/copilot-sdk/pull/868)) - **[.NET]** Add fallback `TypeInfoResolver` for `StreamJsonRpc.RequestId` to fix NativeAOT compatibility ([#783](https://github.com/github/copilot-sdk/pull/783)) - **[.NET]** Fix codegen for discriminated unions nested within other types ([#736](https://github.com/github/copilot-sdk/pull/736)) - **[.NET]** Handle unknown session event types gracefully instead of throwing ([#881](https://github.com/github/copilot-sdk/pull/881)) --- ## ⚠️ Breaking changes ### All SDKs - **`autoRestart` removed** — The `autoRestart` option has been deprecated across all SDKs (it was never fully implemented). The property still exists but has no effect and will be removed in a future release. Remove any references to `autoRestart` from your client options. ([#803](https://github.com/github/copilot-sdk/pull/803)) ### Python The Python SDK received a significant API surface overhaul in this release, replacing loosely-typed `TypedDict` config objects with proper keyword arguments and dataclasses. These changes improve IDE autocompletion, type safety, and readability. - **`CopilotClient` constructor redesigned** — The `CopilotClientOptions` TypedDict has been replaced by two typed config dataclasses. ([#793](https://github.com/github/copilot-sdk/pull/793)) ```python # Before (v0.1.x) client = CopilotClient({"cli_url": "localhost:3000"}) client = CopilotClient({"cli_path": "/usr/bin/copilot", "log_level": "debug"}) # After (v0.2.0) client = CopilotClient(ExternalServerConfig(url="localhost:3000")) client = CopilotClient(SubprocessConfig(cli_path="/usr/bin/copilot", log_level="debug")) ``` - **`create_session()` and `resume_session()` now take keyword arguments** instead of a `SessionConfig` / `ResumeSessionConfig` TypedDict. `on_permission_request` is now a required keyword argument. ([#587](https://github.com/github/copilot-sdk/pull/587)) ```python # Before session = await client.create_session({ "on_permission_request": PermissionHandler.approve_all, "model": "gpt-4.1", }) # After session = await client.create_session( on_permission_request=PermissionHandler.approve_all, model="gpt-4.1", ) ``` - **`send()` and `send_and_wait()` take a positional `prompt` string** instead of a `MessageOptions` TypedDict. Attachments and mode are now keyword arguments. ([#814](https://github.com/github/copilot-sdk/pull/814)) ```python # Before await session.send({"prompt": "Hello!"}) await session.send_and_wait({"prompt": "What is 2+2?"}) # After await session.send("Hello!") await session.send_and_wait("What is 2+2?") ``` - **`MessageOptions`, `SessionConfig`, and `ResumeSessionConfig` removed from public API** — These TypedDicts are no longer exported. Use the new keyword-argument signatures directly. ([#587](https://github.com/github/copilot-sdk/pull/587), [#814](https://github.com/github/copilot-sdk/pull/814)) - **Internal modules renamed to private** — `copilot.jsonrpc`, `copilot.sdk_protocol_version`, and `copilot.telemetry` are now `copilot._jsonrpc`, `copilot._sdk_protocol_version`, and `copilot._telemetry`. If you were importing from these modules directly, update your imports. ([#884](https://github.com/github/copilot-sdk/pull/884)) - **Typed overloads for `CopilotClient.on()`** — Event registration now uses typed overloads for better autocomplete. This shouldn't break existing code but changes the type signature. ([#589](https://github.com/github/copilot-sdk/pull/589)) ### Go - **`Client.Start()` context no longer kills the CLI process** — Previously, canceling the `context.Context` passed to `Start()` would terminate the spawned CLI process (it used `exec.CommandContext`). Now the CLI process lifespan is independent of that context — call `client.Stop()` or `client.ForceStop()` to shut it down. ([#689](https://github.com/github/copilot-sdk/pull/689)) - **`LogOptions.Ephemeral` changed from `bool` to `*bool`** — This enables proper three-state semantics (unset/true/false). Use `copilot.Bool(true)` instead of a bare `true`. ([#827](https://github.com/github/copilot-sdk/pull/827)) ```go // Before session.Log(ctx, copilot.LogOptions{Level: copilot.LevelInfo, Ephemeral: true}, "message") // After session.Log(ctx, copilot.LogOptions{Level: copilot.LevelInfo, Ephemeral: copilot.Bool(true)}, "message") ``` ## [v0.1.32](https://github.com/github/copilot-sdk/releases/tag/v0.1.32) (2026-03-07) ### Feature: backward compatibility with v2 CLI servers SDK applications written against the v3 API now also work when connected to a v2 CLI server, with no code changes required. The SDK detects the server's protocol version and automatically adapts v2 `tool.call` and `permission.request` messages into the same user-facing handlers used by v3. ([#706](https://github.com/github/copilot-sdk/pull/706)) ```ts const session = await client.createSession({ tools: [myTool], // unchanged — works with v2 and v3 servers onPermissionRequest: approveAll, }); ``` ```cs var session = await client.CreateSessionAsync(new SessionConfig { Tools = [myTool], // unchanged — works with v2 and v3 servers OnPermissionRequest = approveAll, }); ``` ## [v0.1.31](https://github.com/github/copilot-sdk/releases/tag/v0.1.31) (2026-03-07) ### Feature: multi-client tool and permission broadcasts (protocol v3) The SDK now uses protocol version 3, where the runtime broadcasts `external_tool.requested` and `permission.requested` as session events to all connected clients. This enables multi-client architectures where different clients contribute different tools, or where multiple clients observe the same permission prompts — if one client approves, all clients see the result. Your existing tool and permission handler code is unchanged. ([#686](https://github.com/github/copilot-sdk/pull/686)) ```ts // Two clients each register different tools; the agent can use both const session1 = await client1.createSession({ tools: [defineTool("search", { handler: doSearch })], onPermissionRequest: approveAll, }); const session2 = await client2.resumeSession(session1.id, { tools: [defineTool("analyze", { handler: doAnalyze })], onPermissionRequest: approveAll, }); ``` ```cs var session1 = await client1.CreateSessionAsync(new SessionConfig { Tools = [AIFunctionFactory.Create(DoSearch, "search")], OnPermissionRequest = PermissionHandlers.ApproveAll, }); var session2 = await client2.ResumeSessionAsync(session1.Id, new ResumeSessionConfig { Tools = [AIFunctionFactory.Create(DoAnalyze, "analyze")], OnPermissionRequest = PermissionHandlers.ApproveAll, }); ``` ### Feature: strongly-typed `PermissionRequestResultKind` for .NET and Go Rather than comparing `result.Kind` against undiscoverable magic strings like `"approved"` or `"denied-interactively-by-user"`, .NET and Go now provide typed constants. Node and Python already had typed unions for this; this brings full parity. ([#631](https://github.com/github/copilot-sdk/pull/631)) ```cs session.OnPermissionCompleted += (e) => { if (e.Result.Kind == PermissionRequestResultKind.Approved) { /* ... */ } if (e.Result.Kind == PermissionRequestResultKind.DeniedInteractivelyByUser) { /* ... */ } }; ``` ```go // Go: PermissionKindApproved, PermissionKindDeniedByRules, // PermissionKindDeniedCouldNotRequestFromUser, PermissionKindDeniedInteractivelyByUser if result.Kind == copilot.PermissionKindApproved { /* ... */ } ``` ### Other changes - feature: **[Python]** **[Go]** add `get_last_session_id()` / `GetLastSessionID()` for SDK-wide parity (was already available in Node and .NET) ([#671](https://github.com/github/copilot-sdk/pull/671)) - improvement: **[Python]** add `timeout` parameter to generated RPC methods, allowing callers to override the default 30s timeout for long-running operations ([#681](https://github.com/github/copilot-sdk/pull/681)) - bugfix: **[Go]** `PermissionRequest` fields are now properly typed (`ToolName`, `Diff`, `Path`, etc.) instead of a generic `Extra map[string]any` catch-all ([#685](https://github.com/github/copilot-sdk/pull/685)) ## [v0.1.30](https://github.com/github/copilot-sdk/releases/tag/v0.1.30) (2026-03-03) ### Feature: support overriding built-in tools Applications can now override built-in tools such as `grep`, `edit_file`, or `read_file`. To do this, register a custom tool with the same name and set the override flag. Without the flag, the runtime will return an error if the name clashes with a built-in. ([#636](https://github.com/github/copilot-sdk/pull/636)) ```ts import { defineTool } from "@github/copilot-sdk"; const session = await client.createSession({ tools: [defineTool("grep", { overridesBuiltInTool: true, handler: async (params) => `CUSTOM_GREP_RESULT: ${params.query}`, })], onPermissionRequest: approveAll, }); ``` ```cs var grep = AIFunctionFactory.Create( ([Description("Search query")] string query) => $"CUSTOM_GREP_RESULT: {query}", "grep", "Custom grep implementation", new AIFunctionFactoryOptions { AdditionalProperties = new ReadOnlyDictionary( new Dictionary { ["is_override"] = true }) }); ``` ### Feature: simpler API for changing model mid-session While `session.rpc.model.switchTo()` already worked, there is now a convenience method directly on the session object. ([#621](https://github.com/github/copilot-sdk/pull/621)) - TypeScript: `await session.setModel("gpt-4.1")` - C#: `await session.SetModelAsync("gpt-4.1")` - Python: `await session.set_model("gpt-4.1")` - Go: `err := session.SetModel(ctx, "gpt-4.1")` ### Other changes - improvement: **[C#]** use event delegate for thread-safe, insertion-ordered event handler dispatch ([#624](https://github.com/github/copilot-sdk/pull/624)) - improvement: **[C#]** deduplicate `OnDisposeCall` and improve implementation ([#626](https://github.com/github/copilot-sdk/pull/626)) - improvement: **[C#]** remove unnecessary `SemaphoreSlim` locks for handler fields ([#625](https://github.com/github/copilot-sdk/pull/625)) - bugfix: **[Python]** correct `PermissionHandler.approve_all` type annotations ([#618](https://github.com/github/copilot-sdk/pull/618)) ### New contributors - @giulio-leone made their first contribution in [#618](https://github.com/github/copilot-sdk/pull/618)