Phase 7/13 — API Surface

Phase 7: Complete API Surface Reference

Every public symbol, method, type, and extension point across TypeScript Python Go C#.

1. Exported Symbols Per SDK

TypeScript nodejs/src/index.ts

// Classes
export { CopilotClient } from "./client.js";
export { CopilotSession, type AssistantMessageEvent } from "./session.js";

// Functions
export { defineTool, approveAll } from "./types.js";

// Types (re-exported)
export type {
    ConnectionState, CopilotClientOptions, CustomAgentConfig,
    ForegroundSessionInfo, GetAuthStatusResponse, GetStatusResponse,
    InfiniteSessionConfig, MCPLocalServerConfig, MCPRemoteServerConfig,
    MCPServerConfig, MessageOptions, ModelBilling, ModelCapabilities,
    ModelInfo, ModelPolicy, PermissionHandler, PermissionRequest,
    PermissionRequestResult, ResumeSessionConfig, SessionConfig,
    SessionEvent, SessionEventHandler, SessionEventPayload,
    SessionEventType, SessionLifecycleEvent, SessionLifecycleEventType,
    SessionLifecycleHandler, SessionContext, SessionListFilter,
    SessionMetadata, SystemMessageAppendConfig, SystemMessageConfig,
    SystemMessageReplaceConfig, Tool, ToolHandler, ToolInvocation,
    ToolResultObject, TypedSessionEventHandler,
    TypedSessionLifecycleHandler, ZodSchema,
} from "./types.js";

Python python/copilot/__init__.py

# Classes
from .client import CopilotClient
from .session import CopilotSession

# Functions
from .tools import define_tool

# Types (re-exported)
from .types import (
    AzureProviderOptions, ConnectionState, CustomAgentConfig,
    GetAuthStatusResponse, GetStatusResponse, MCPLocalServerConfig,
    MCPRemoteServerConfig, MCPServerConfig, MessageOptions,
    ModelBilling, ModelCapabilities, ModelInfo, ModelPolicy,
    PermissionHandler, PermissionRequest, PermissionRequestResult,
    PingResponse, ProviderConfig, ResumeSessionConfig, SessionConfig,
    SessionContext, SessionEvent, SessionListFilter, SessionMetadata,
    StopError, Tool, ToolHandler, ToolInvocation, ToolResult,
)

Go go/ package

CategorySymbols
StructsClient, Session, ClientOptions, SessionConfig, ResumeSessionConfig, Tool, ToolInvocation, ToolResult, ToolBinaryResult, MessageOptions, ProviderConfig, AzureProviderOptions, SystemMessageConfig, MCPLocalServerConfig, MCPRemoteServerConfig, CustomAgentConfig, InfiniteSessionConfig, PermissionRequestResult, SessionHooks, PreToolUseHookInput/Output, PostToolUseHookInput/Output, SessionStartHookInput/Output, SessionEndHookInput/Output, ErrorOccurredHookInput/Output, ModelInfo, SessionContext, SessionMetadata
Type AliasesConnectionState, SessionEventHandler, SessionLifecycleHandler, PermissionRequestResultKind, MCPServerConfig
FunctionsNewClient(), Bool(), String(), Float64(), DefineTool()
VariablesPermissionHandler.ApproveAll
ConstantsStateDisconnected, StateConnecting, StateConnected, StateError, PermissionRequestResultKindApproved, ...Denied*, SessionLifecycleCreated/Deleted/Updated/Foreground/Background

C# dotnet/src/ namespace GitHub.Copilot.SDK

CategorySymbols
ClassesCopilotClient, CopilotSession, CopilotClientOptions, SessionConfig, ResumeSessionConfig, ToolResultObject, ToolInvocation, PermissionRequestResult, SessionHooks, PreToolUseHookInput/Output, PostToolUseHookInput/Output, SessionStartHookInput/Output, SessionEndHookInput/Output, ErrorOccurredHookInput/Output, ProviderConfig, McpLocalServerConfig, McpRemoteServerConfig, CustomAgentConfig, InfiniteSessionConfig, SystemMessageConfig, ModelInfo, SessionContext, SessionMetadata
EnumsConnectionState, SystemMessageMode
DelegatesToolHandler, PermissionRequestHandler, UserInputHandler, PreToolUseHandler, PostToolUseHandler, SessionEventHandler
StaticPermissionHandler.ApproveAll

2. Client API

Constructor

LanguageSignature
TSnew CopilotClient(options?: CopilotClientOptions)
PyCopilotClient(options?: CopilotClientOptions)
GoNewClient(options *ClientOptions) *Client
C#new CopilotClient(options?: CopilotClientOptions)

CopilotClientOptions

FieldTSPyGoC#
CLI pathcliPath?: stringcli_path: strCLIPath stringCliPath string?
CLI argscliArgs?: string[]cli_args: list[str]CLIArgs []stringCliArgs string[]?
Working dircwd?: stringcwd: strCwd stringCwd string?
Portport?: numberport: intPort intPort int
Use stdiouseStdio?: booleanuse_stdio: boolUseStdio *boolUseStdio bool
CLI URLcliUrl?: stringcli_url: strCLIUrl stringCliUrl string?
Auto startautoStart?: booleanauto_start: boolAutoStart *boolAutoStart bool
Auto restartautoRestart?: booleanauto_restart: boolAutoRestart *boolAutoRestart bool
Environmentenv?: Record<string,string>env: dictEnv []stringEnvironment IReadOnlyDictionary?
GitHub tokengithubToken?: stringgithub_token: strGitHubToken stringGitHubToken string?
Model listeronListModels?: () => Promise<ModelInfo[]>on_list_models: CallableOnListModels func(ctx)([]ModelInfo, error)OnListModels Func<..., Task<List<ModelInfo>>>?

Client Methods

MethodTSPyGoC#
Startstart(): Promise<void>async start()Start(ctx) errorStartAsync(ct) Task
Stopstop(): Promise<Error[]>async stop()Stop() errorStopAsync(ct) Task
Force stopforceStop()async force_stop()ForceStop()ForceStopAsync() Task
Create sessioncreateSession(config)create_session(config)CreateSession(ctx, *SessionConfig)CreateSessionAsync(config, ct)
Resume sessionresumeSession(id, config)resume_session(id, config)ResumeSession(ctx, id, *ResumeSessionConfig)ResumeSessionAsync(id, config, ct)
Pingping(msg?)ping(msg?)Ping(ctx, msg)PingAsync(msg?, ct)
Get statusgetStatus()get_status()GetStatus(ctx)GetStatusAsync(ct)
Auth statusgetAuthStatus()get_auth_status()GetAuthStatus(ctx)GetAuthStatusAsync(ct)
List modelslistModels()list_models()ListModels(ctx)ListModelsAsync(ct)
List sessionslistSessions(filter?)list_sessions(filter?)ListSessions(ctx, *SessionListFilter)ListSessionsAsync(filter?, ct)
Delete sessiondeleteSession(id)delete_session(id)DeleteSession(ctx, id)DeleteSessionAsync(id, ct)
Lifecycle eventson(handler): () => voidon(handler) -> CallableOn(handler) func()On(handler) IDisposable
Dispose[Symbol.asyncDispose]()async __aexit__()Stop()DisposeAsync()

3. Session API

Session Properties

PropertyTSPyGoC#
Session IDreadonly sessionId: stringsession_id: strSessionID stringSessionId { get; }
Workspaceget workspacePath()workspace_path (property)WorkspacePath() stringWorkspacePath { get; }
Typed RPCget rpc()rpc (property)RPC *rpc.SessionRpcRpc (property)

Session Methods

MethodTSPyGoC#
Sendsend(options)send(options)Send(ctx, MessageOptions)SendAsync(options, ct)
Send & waitsendAndWait(options, timeout?)send_and_wait(options, timeout?)SendAndWait(ctx, MessageOptions)SendAndWaitAsync(options, timeout?, ct)
Subscribeon(handler): () => voidon(handler) -> CallableOn(handler) func()On(handler) IDisposable
Typed subscribeon<K>(type, handler)N/AN/AN/A (pattern matching)
Get messagesgetMessages()get_messages()GetMessages(ctx)GetMessagesAsync(ct)
Disconnectdisconnect()disconnect()Disconnect() errorDisposeAsync()
Abortabort()abort()Abort(ctx) errorAbortAsync(ct)
Set modelsetModel(model)set_model(model)SetModel(ctx, model)SetModelAsync(model, ct)
Loglog(message, options?)log(message, level?, ephemeral?)Log(ctx, message, *LogOptions)LogAsync(message, level?, ephemeral?, ct)

MessageOptions

interface MessageOptions {
    prompt: string;
    attachments?: Array<FileAttachment | DirectoryAttachment | SelectionAttachment>;
    mode?: "enqueue" | "immediate";
}
class MessageOptions(TypedDict):
    prompt: str
    attachments: NotRequired[list[Attachment]]
    mode: NotRequired[Literal["enqueue", "immediate"]]
type MessageOptions struct {
    Prompt      string
    Attachments []Attachment
    Mode        string  // "enqueue" or "immediate"
}
public class MessageOptions {
    public string Prompt { get; init; }
    public List<Attachment>? Attachments { get; init; }
    public string? Mode { get; init; }
}

4. Type System

SessionConfig

The most important configuration type — controls model selection, tools, permissions, hooks, provider, MCP servers, and more.

FieldTSPyGoC#
Modelmodel?: stringmodel: strModel stringModel string?
Toolstools?: Tool<any>[]tools: list[Tool]Tools []ToolTools List<AIFunction>?
System messagesystemMessage?: SystemMessageConfigsystem_messageSystemMessage *SystemMessageConfigSystemMessage?
Permission handleronPermissionRequest: PermissionHandleron_permission_requestOnPermissionRequest PermissionHandlerFuncOnPermissionRequest?
User inputonUserInputRequest?on_user_input_requestOnUserInputRequestOnUserInputRequest?
Hookshooks?: SessionHookshooksHooks *SessionHooksHooks?
Provider (BYOK)provider?: ProviderConfigproviderProvider *ProviderConfigProvider?
MCP serversmcpServers?: Record<string, MCPServerConfig>mcp_servers: dictMCPServers map[string]MCPServerConfigMcpServers Dictionary?
Custom agentscustomAgents?: CustomAgentConfig[]custom_agentsCustomAgents []CustomAgentConfigCustomAgents?
Working dirworkingDirectory?: stringworking_directoryWorkingDirectory stringWorkingDirectory?
Streamingstreaming?: booleanstreaming: boolStreaming boolStreaming bool?
Infinite sessionsinfiniteSessions?infinite_sessionsInfiniteSessionsInfiniteSessions?
Reasoning effortreasoningEffort?reasoning_effortReasoningEffort stringReasoningEffort?

ProviderConfig (BYOK)

interface ProviderConfig {
    type?: "openai" | "azure" | "anthropic";
    wireApi?: "completions" | "responses";
    baseUrl: string;
    apiKey?: string;
    bearerToken?: string;
    azure?: { apiVersion?: string };
}
type ProviderConfig struct {
    Type        string                 `json:"type,omitempty"`
    WireApi     string                 `json:"wireApi,omitempty"`
    BaseURL     string                 `json:"baseUrl"`
    APIKey      string                 `json:"apiKey,omitempty"`
    BearerToken string                 `json:"bearerToken,omitempty"`
    Azure       *AzureProviderOptions  `json:"azure,omitempty"`
}

SessionEvent

Code-generated from a shared schema. Different patterns per language:

// Discriminated union on `type`
type SessionEvent =
  | { type: "assistant.message"; data: { content: string; ... }; ... }
  | { type: "session.idle"; data: { ... }; ... }
  | { type: "session.error"; data: { message: string; ... }; ... }
  | { type: "external_tool.requested"; data: { requestId: string; ... }; ... }
  | { type: "permission.requested"; data: { ... }; ... }
  // ... many more
// Single struct with typed data
type SessionEvent struct {
    Data      Data             `json:"data"`
    Ephemeral *bool            `json:"ephemeral,omitempty"`
    ID        string           `json:"id"`
    ParentID  *string          `json:"parentId"`
    Timestamp time.Time        `json:"timestamp"`
    Type      SessionEventType `json:"type"`
}
// Class hierarchy
public abstract class SessionEvent { ... }
public class AssistantMessageEvent : SessionEvent { ... }
public class SessionIdleEvent : SessionEvent { ... }
public class SessionErrorEvent : SessionEvent { ... }
public class ExternalToolRequestedEvent : SessionEvent { ... }
public class PermissionRequestedEvent : SessionEvent { ... }

ConnectionState

TSPyGoC#
"disconnected" | "connecting" | "connected" | "error"Literal["disconnected", ...]StateDisconnected | StateConnecting | ...enum ConnectionState { ... }

5. Tool Definition API

// defineTool() with Zod schema for type inference
import { defineTool } from "@github/copilot-sdk";

const weatherTool = defineTool("get_weather", {
    description: "Get weather for a location",
    parameters: z.object({ location: z.string() }),
    handler: async (args) => {
        // args is typed as { location: string }
        return { temperature: 72 };
    },
});

// Tool interface
interface Tool<TArgs = unknown> {
    name: string;
    description?: string;
    parameters?: ZodSchema<TArgs> | Record<string, unknown>;
    handler: ToolHandler<TArgs>;
    overridesBuiltInTool?: boolean;
}
from pydantic import BaseModel, Field
from copilot import define_tool

class GetWeatherParams(BaseModel):
    city: str = Field(description="City name")
    unit: str = Field(description="Temperature unit")

# Decorator approach
@define_tool(description="Get weather for a city")
def get_weather(params: GetWeatherParams) -> str:
    return f"Weather in {params.city}: 22 degrees {params.unit}"

# Tool dataclass
@dataclass
class Tool:
    name: str
    description: str
    handler: ToolHandler
    parameters: dict[str, Any] | None = None
    overrides_built_in_tool: bool = False
type GetWeatherParams struct {
    City string `json:"city" jsonschema:"city name"`
    Unit string `json:"unit" jsonschema:"temperature unit"`
}

tool := copilot.DefineTool("get_weather", "Get weather for a city",
    func(params GetWeatherParams, inv copilot.ToolInvocation) (any, error) {
        return fmt.Sprintf("Weather in %s: 22 degrees %s",
            params.City, params.Unit), nil
    })

// Tool struct
type Tool struct {
    Name                 string         `json:"name"`
    Description          string         `json:"description,omitempty"`
    Parameters           map[string]any `json:"parameters,omitempty"`
    OverridesBuiltInTool bool           `json:"overridesBuiltInTool,omitempty"`
    Handler              ToolHandler    `json:"-"`
}
using Microsoft.Extensions.AI;

// Define tool from a method
[Description("Get weather for a location")]
static string GetWeather(string location) => $"Weather in {location}: 72F";

var session = await client.CreateSessionAsync(new()
{
    OnPermissionRequest = PermissionHandler.ApproveAll,
    Tools = [AIFunctionFactory.Create(GetWeather)]
});

// ToolInvocation class
public class ToolInvocation {
    public string SessionId { get; set; }
    public string ToolCallId { get; set; }
    public string ToolName { get; set; }
    public object? Arguments { get; set; }
}

ToolResult Types

type ToolResultObject = {
    textResultForLlm: string;
    binaryResultsForLlm?: ToolBinaryResult[];
    resultType: "success" | "failure" | "rejected" | "denied";
    error?: string;
    sessionLog?: string;
    toolTelemetry?: Record<string, unknown>;
};
type ToolResult struct {
    TextResultForLLM    string             `json:"textResultForLlm"`
    BinaryResultsForLLM []ToolBinaryResult `json:"binaryResultsForLlm,omitempty"`
    ResultType          string             `json:"resultType"`
    Error               string             `json:"error,omitempty"`
    SessionLog          string             `json:"sessionLog,omitempty"`
    ToolTelemetry       map[string]any     `json:"toolTelemetry,omitempty"`
}

6. Hook / Callback API

Six lifecycle hooks via SessionHooks:

HookWhen InvokedInputOutput
onPreToolUseBefore tool executionPreToolUseHookInputallow / deny / ask + modified args
onPostToolUseAfter tool executionPostToolUseHookInputOptional modifications
onUserPromptSubmittedUser sends promptUserPromptSubmittedHookInputOptional modifications
onSessionStartSession startsSessionStartHookInputOptional system prompt additions
onSessionEndSession endsSessionEndHookInputOptional summary
onErrorOccurredError happensErrorOccurredHookInputretry / skip / abort

PreToolUseHookInput/Output

interface PreToolUseHookInput {
    timestamp: number;       // Unix ms
    cwd: string;
    toolName: string;
    toolArgs: unknown;
}

interface PreToolUseHookOutput {
    permissionDecision?: "allow" | "deny" | "ask";
    permissionDecisionReason?: string;
    modifiedArgs?: unknown;
    additionalContext?: string;
    suppressOutput?: boolean;
}

SessionHooks Configuration

interface SessionHooks {
    onPreToolUse?: PreToolUseHandler;
    onPostToolUse?: PostToolUseHandler;
    onUserPromptSubmitted?: UserPromptSubmittedHandler;
    onSessionStart?: SessionStartHandler;
    onSessionEnd?: SessionEndHandler;
    onErrorOccurred?: ErrorOccurredHandler;
}
class SessionHooks(TypedDict, total=False):
    on_pre_tool_use: PreToolUseHandler
    on_post_tool_use: PostToolUseHandler
    on_user_prompt_submitted: UserPromptSubmittedHandler
    on_session_start: SessionStartHandler
    on_session_end: SessionEndHandler
    on_error_occurred: ErrorOccurredHandler
type SessionHooks struct {
    OnPreToolUse          PreToolUseHandler
    OnPostToolUse         PostToolUseHandler
    OnUserPromptSubmitted UserPromptSubmittedHandler
    OnSessionStart        SessionStartHandler
    OnSessionEnd          SessionEndHandler
    OnErrorOccurred       ErrorOccurredHandler
}
public class SessionHooks {
    public PreToolUseHandler? OnPreToolUse { get; set; }
    public PostToolUseHandler? OnPostToolUse { get; set; }
    public UserPromptSubmittedHandler? OnUserPromptSubmitted { get; set; }
    public SessionStartHandler? OnSessionStart { get; set; }
    public SessionEndHandler? OnSessionEnd { get; set; }
    public ErrorOccurredHandler? OnErrorOccurred { get; set; }
}

7. Permission API

Permission Handler Signature

LanguageSignature
TS(request: PermissionRequest, inv: { sessionId }) => Promise<PermissionRequestResult>
Py(request, inv) -> PermissionRequestResult | Awaitable[...]
Gofunc(request, inv) (PermissionRequestResult, error)
C#delegate Task<PermissionRequestResult> PermissionRequestHandler(...)

PermissionRequest

interface PermissionRequest {
    kind: "shell" | "write" | "mcp" | "read" | "url" | "custom-tool";
    toolCallId?: string;
    [key: string]: unknown;  // Additional fields vary by kind
}

PermissionRequestResult

type PermissionRequestResult = {
    kind: "approved"
        | "denied-by-rules"
        | "denied-interactively-by-user"
        | "denied-no-approval-rule-and-could-not-request-from-user";
    rules?: any[];
};

Built-in approveAll

LanguageUsage
TSimport { approveAll } from "@github/copilot-sdk"
PyPermissionHandler.approve_all
Gocopilot.PermissionHandler.ApproveAll
C#PermissionHandler.ApproveAll

User Input Handler

type UserInputHandler = (
    request: UserInputRequest,
    invocation: { sessionId: string }
) => Promise<UserInputResponse> | UserInputResponse;

interface UserInputRequest {
    question: string;
    choices?: string[];
    allowFreeform?: boolean;
}

interface UserInputResponse {
    answer: string;
    wasFreeform: boolean;
}

8. Extension Points

Extension Points
flowchart LR
    A["<b>1. Custom Tools</b><br/>Register via SessionConfig.tools.<br/>Each has name, description,<br/>schema, handler."]
    B["<b>2. Permission Handlers</b><br/>Required for session creation.<br/>Controls shell, write, MCP, read,<br/>URL, and custom-tool permissions."]
    C["<b>3. User Input Handlers</b><br/>Optional. Enables ask_user tool<br/>for agent-to-user questions."]
    D["<b>4. Lifecycle Hooks</b><br/>Six hook points #40;see Section 6#41;.<br/>Intercept and modify<br/>session lifecycle."]
    A ~~~ B ~~~ C ~~~ D
            

5. Custom Agents

const config: SessionConfig = {
    customAgents: [{
        name: "code-reviewer",
        displayName: "Code Reviewer",
        description: "Reviews code for quality",
        prompt: "You are a code reviewer...",
        tools: ["read_file", "grep"],
        mcpServers: { ... },
        infer: true,
    }],
    agent: "code-reviewer",  // Activate this agent
};

6. MCP Server Integration

const config: SessionConfig = {
    mcpServers: {
        "my-server": {
            type: "local",
            tools: ["*"],
            command: "node",
            args: ["./mcp-server.js"],
            env: { API_KEY: "..." },
        },
        "remote-server": {
            type: "http",
            tools: ["*"],
            url: "https://example.com/mcp",
            headers: { Authorization: "Bearer ..." },
        },
    },
};

7. BYOK Provider Configuration

const config: SessionConfig = {
    provider: {
        type: "openai",
        baseUrl: "https://api.openai.com/v1",
        apiKey: "sk-...",
    },
    model: "gpt-4",
};

8. Extension Module (TypeScript Only)

// nodejs/src/extension.ts
import { joinSession } from "@github/copilot-sdk/extension";

const session = await joinSession({
    onPermissionRequest: approveAll,
    tools: [myTool],
});

9. Custom Model Lister

const client = new CopilotClient({
    onListModels: async () => [
        { id: "my-model", name: "My Model", capabilities: { ... } }
    ],
});

10. Typed RPC Access

await session.rpc.tools.handlePendingToolCall({ requestId, result });
await session.rpc.permissions.handlePendingPermissionRequest({ requestId, result });
await session.rpc.model.switchTo({ modelId: "gpt-4.1" });
await session.rpc.log({ message: "Hello", level: "info" });

9. JSON-RPC Methods

All SDKs communicate with the Copilot CLI via the same JSON-RPC protocol.

Server-Level Methods

RPC MethodDirectionDescription
pingClient → ServerHealth check, returns message + timestamp + protocol version
status.getClient → ServerGet CLI version and protocol version
auth.getStatusClient → ServerGet authentication status
models.listClient → ServerList available models

Session Lifecycle Methods

RPC MethodDirectionDescription
session.createClient → ServerCreate a new session
session.resumeClient → ServerResume an existing session
session.destroyClient → ServerDisconnect / release a session
session.deleteClient → ServerPermanently delete session data
session.listClient → ServerList all sessions
session.getLastIdClient → ServerGet most recently used session ID
session.getForegroundClient → ServerGet TUI foreground session ID
session.setForegroundClient → ServerSet TUI foreground session

Session Communication Methods

RPC MethodDirectionDescription
session.sendClient → ServerSend a message to a session
session.abortClient → ServerAbort current processing
session.getMessagesClient → ServerGet session event history

Session-Scoped RPC Methods

RPC MethodDirectionDescription
session.tools.handlePendingToolCallClient → ServerRespond to a tool call request
session.permissions.handlePendingPermissionRequestClient → ServerRespond to a permission request
session.model.switchToClient → ServerChange model mid-session
session.logClient → ServerLog a message to timeline

Server → Client Notifications (Session Events)

Event TypeDescription
assistant.messageFinal assistant response
assistant.message_deltaStreaming message chunk
assistant.reasoning_deltaStreaming reasoning chunk
session.idleSession finished processing
session.errorSession encountered an error
session.startSession started
external_tool.requestedTool call broadcast (v3)
permission.requestedPermission request broadcast (v3)
user_input.requestedUser input request broadcast
hook.invokedHook invocation request
tool.executingTool is being executed
tool.executedTool execution completed
plan.updatedPlan file updated

Client-Level Lifecycle Notifications

Event TypeDescription
session.createdA session was created
session.deletedA session was deleted
session.updatedA session was updated
session.foregroundSession moved to foreground
session.backgroundSession moved to background

10. Cross-Language API Comparison

Creating a Client and Session

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

const client = new CopilotClient({ autoStart: true });
const session = await client.createSession({
    onPermissionRequest: approveAll,
    model: "gpt-4",
});
from copilot import CopilotClient, PermissionHandler

async with CopilotClient() as client:
    session = await client.create_session({
        "on_permission_request": PermissionHandler.approve_all,
        "model": "gpt-4",
    })
client := copilot.NewClient(nil)
if err := client.Start(ctx); err != nil {
    log.Fatal(err)
}
defer client.Stop()

session, err := client.CreateSession(ctx, &copilot.SessionConfig{
    OnPermissionRequest: copilot.PermissionHandler.ApproveAll,
    Model:               "gpt-4",
})
await using var client = new CopilotClient();
await using var session = await client.CreateSessionAsync(new()
{
    OnPermissionRequest = PermissionHandler.ApproveAll,
    Model = "gpt-4",
});

Sending a Message

const response = await session.sendAndWait({ prompt: "What is 2+2?" });
console.log(response?.data.content);
response = await session.send_and_wait({"prompt": "What is 2+2?"})
if response:
    print(response.data.content)
response, err := session.SendAndWait(ctx, copilot.MessageOptions{
    Prompt: "What is 2+2?",
})
if response != nil {
    fmt.Println(*response.Data.Content)
}
var response = await session.SendAndWaitAsync(new MessageOptions
{
    Prompt = "What is 2+2?"
});
Console.WriteLine(response?.Data?.Content);

Defining a Custom Tool

const tool = defineTool("get_weather", {
    description: "Get weather for a location",
    parameters: z.object({ city: z.string() }),
    handler: async (args) => `Weather in ${args.city}: 72F`,
});
from pydantic import BaseModel
from copilot import define_tool

class WeatherParams(BaseModel):
    city: str

@define_tool(description="Get weather for a location")
def get_weather(params: WeatherParams) -> str:
    return f"Weather in {params.city}: 72F"
type WeatherParams struct {
    City string `json:"city"`
}

tool := copilot.DefineTool("get_weather", "Get weather for a location",
    func(params WeatherParams, inv copilot.ToolInvocation) (any, error) {
        return fmt.Sprintf("Weather in %s: 72F", params.City), nil
    })
[Description("Get weather for a location")]
static string GetWeather(string city) => $"Weather in {city}: 72F";

// Pass as: Tools = [AIFunctionFactory.Create(GetWeather)]

Subscribing to Events

const unsubscribe = session.on("assistant.message", (event) => {
    console.log("Assistant:", event.data.content);
});
// Later: unsubscribe();
def handler(event):
    if event.type == "assistant.message":
        print(f"Assistant: {event.data.content}")

unsubscribe = session.on(handler)
# Later: unsubscribe()
unsubscribe := session.On(func(event copilot.SessionEvent) {
    if event.Type == copilot.AssistantMessage {
        fmt.Println("Assistant:", *event.Data.Content)
    }
})
// Later: unsubscribe()
using var subscription = session.On(evt =>
{
    if (evt is AssistantMessageEvent msg)
    {
        Console.WriteLine($"Assistant: {msg.Data?.Content}");
    }
});
// Auto-unsubscribed when disposed

Resource Cleanup

// Manual
await session.disconnect();
await client.stop();

// Auto-dispose
await using session = await client.createSession({ ... });
# Manual
await session.disconnect()
await client.stop()

# Context manager
async with CopilotClient() as client:
    session = await client.create_session({ ... })
// Always manual with defer
defer client.Stop()
defer session.Disconnect()
// Manual
await session.DisposeAsync();
await client.DisposeAsync();

// Auto-dispose
await using var client = new CopilotClient();
await using var session = await client.CreateSessionAsync(new() { ... });

Appendix: SDK-Specific Differences

FeatureTSPyGoC#
Tool schema sourceZod / raw JSON SchemaPydantic BaseModelStruct tags + jsonschema-goAIFunctionFactory (M.E.AI)
Async modelPromise / async/awaitasyncio / async/awaitcontext.Context / goroutinesTask / async/await
Event patternTyped discriminated unionEnum-based SessionEventTypeString-typed SessionEventTypeClass hierarchy + pattern matching
Typed subscribesession.on<K>(type, handler)N/AN/AC# pattern matching
Dispose patternSymbol.asyncDispose__aenter__/__aexit__defer session.Disconnect()IAsyncDisposable
Permission handlerapproveAll functionPermissionHandler.approve_allPermissionHandler.ApproveAll varPermissionHandler.ApproveAll static
Error handlingExceptionsExceptionGroup (stop)error return valuesExceptions + CancellationToken
Thread safetySingle-threaded (event loop)Locks + asynciosync.Mutex / sync.RWMutexConcurrentDictionary + SemaphoreSlim
Child process extjoinSession()N/AN/AN/A
Optional boolN/AN/ABool(v bool) *boolN/A (nullable)