Skip to main content

C# SDK Cookbook

Short, practical recipes for using the GitHub Copilot SDK with .NET and C#. Each recipe is concise, copy-pasteable, and points to complete runnable examples.

Setup

All C# examples use the GitHub.Copilot.SDK NuGet package:
dotnet add package GitHub.Copilot.SDK

Error Handling

Handle errors gracefully including connection failures, timeouts, and cleanup.

Basic try-catch Pattern

using GitHub.Copilot.SDK;

var client = new CopilotClient();

try
{
    await client.StartAsync();
    var session = await client.CreateSessionAsync(new SessionConfig
    {
        Model = "gpt-5"
    });

    var done = new TaskCompletionSource<string>();
    session.On(evt =>
    {
        if (evt is AssistantMessageEvent msg)
        {
            done.SetResult(msg.Data.Content);
        }
    });

    await session.SendAsync(new MessageOptions { Prompt = "Hello!" });
    var response = await done.Task;
    Console.WriteLine(response);

    await session.DisposeAsync();
}
catch (Exception ex)
{
    Console.WriteLine($"Error: {ex.Message}");
}
finally
{
    await client.StopAsync();
}

Timeout Handling

var session = await client.CreateSessionAsync(new SessionConfig { Model = "gpt-5" });

try
{
    var done = new TaskCompletionSource<string>();
    session.On(evt =>
    {
        if (evt is AssistantMessageEvent msg)
        {
            done.SetResult(msg.Data.Content);
        }
    });

    await session.SendAsync(new MessageOptions { Prompt = "Complex question..." });

    // Wait with timeout (30 seconds)
    using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
    var response = await done.Task.WaitAsync(cts.Token);

    Console.WriteLine(response);
}
catch (OperationCanceledException)
{
    Console.WriteLine("Request timed out");
}

Automatic Disposal Pattern

await using var client = new CopilotClient();
await client.StartAsync();

var session = await client.CreateSessionAsync(new SessionConfig { Model = "gpt-5" });

// ... do work ...

// client.StopAsync() is automatically called when exiting scope
Use the await using pattern for automatic cleanup. This ensures StopAsync() is called even if exceptions occur.

Multiple Sessions

Manage multiple independent conversations simultaneously.
using GitHub.Copilot.SDK;

var client = new CopilotClient();
await client.StartAsync();

// Create multiple independent sessions
var session1 = await client.CreateSessionAsync(new SessionConfig { Model = "gpt-5" });
var session2 = await client.CreateSessionAsync(new SessionConfig { Model = "gpt-5" });
var session3 = await client.CreateSessionAsync(new SessionConfig { Model = "claude-sonnet-4.5" });

// Each session maintains its own conversation history
await session1.SendAsync(new MessageOptions { Prompt = "You are helping with a Python project" });
await session2.SendAsync(new MessageOptions { Prompt = "You are helping with a TypeScript project" });
await session3.SendAsync(new MessageOptions { Prompt = "You are helping with a Go project" });

// Follow-up messages stay in their respective contexts
await session1.SendAsync(new MessageOptions { Prompt = "How do I create a virtual environment?" });
await session2.SendAsync(new MessageOptions { Prompt = "How do I set up tsconfig?" });
await session3.SendAsync(new MessageOptions { Prompt = "How do I initialize a module?" });

// Clean up
await session1.DisposeAsync();
await session2.DisposeAsync();
await session3.DisposeAsync();
await client.StopAsync();

Use Cases

Multi-User Apps

One session per user in web applications

Multi-Task Workflows

Separate sessions for different tasks

A/B Testing

Compare responses from different models

Session Persistence

Save and resume sessions across application restarts.
using GitHub.Copilot.SDK;
using System.Text.Json;

// Save session state
var client = new CopilotClient();
await client.StartAsync();

var session = await client.CreateSessionAsync(new SessionConfig { Model = "gpt-5" });
await session.SendAsync(new MessageOptions { Prompt = "Remember: my name is Alice" });

var sessionState = session.GetState();
await File.WriteAllTextAsync("session.json", JsonSerializer.Serialize(sessionState));

await session.DisposeAsync();
await client.StopAsync();

// Later: restore session state
var client2 = new CopilotClient();
await client2.StartAsync();

var savedState = await File.ReadAllTextAsync("session.json");
var state = JsonSerializer.Deserialize<SessionState>(savedState);

var restoredSession = await client2.CreateSessionAsync(new SessionConfig 
{ 
    Model = "gpt-5",
    State = state 
});

// Session remembers previous context
await restoredSession.SendAsync(new MessageOptions { Prompt = "What's my name?" });
// Response: "Your name is Alice"
Session persistence allows you to maintain conversation context across application restarts, perfect for long-running projects or user sessions.

Managing Local Files

Organize files by metadata using AI-powered grouping strategies.
using GitHub.Copilot.SDK;

var client = new CopilotClient();
await client.StartAsync();

var session = await client.CreateSessionAsync(new SessionConfig { Model = "gpt-5" });

// Ask AI to organize files
var done = new TaskCompletionSource<string>();
session.On(evt =>
{
    if (evt is AssistantMessageEvent msg)
    {
        done.SetResult(msg.Data.Content);
    }
});

await session.SendAsync(new MessageOptions 
{ 
    Prompt = @"
        I have these files in a directory:
        - report.pdf
        - meeting-notes.txt
        - photo.jpg
        - invoice.xlsx
        - presentation.pptx
        
        Please organize them into folders by type.
        Return JSON with the structure.
    "
});

var organizationPlan = await done.Task;
Console.WriteLine(organizationPlan);

// Parse and execute the organization plan
// ...

Running Examples

All complete, runnable examples are available in the cookbook/copilot-sdk/dotnet/recipe directory.
1

Navigate to the recipe directory

cd cookbook/copilot-sdk/dotnet/recipe
2

Run any example

dotnet run error-handling.cs
dotnet run multiple-sessions.cs
dotnet run persisting-sessions.cs

Best Practices

Use try-finally or await using to ensure StopAsync() is called, even when exceptions occur.
await using var client = new CopilotClient();
// Resources automatically cleaned up
The Copilot CLI might not be installed or running. Always catch and handle connection exceptions.
catch (FileNotFoundException)
{
    Console.WriteLine("Please install GitHub Copilot CLI");
}
Use CancellationToken for long-running requests to prevent indefinite waits.
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
await task.WaitAsync(cts.Token);
Capture error details to help diagnose issues in production.
catch (Exception ex)
{
    _logger.LogError(ex, "Copilot request failed");
}

Additional Recipes

Explore more advanced recipes in the source repository:

Resources

Build docs developers (and LLMs) love