copilot-sdk-go
Expert guidance for using the GitHub Copilot CLI SDK with Go, including API reference, best practices, and common usage patterns.
Best use case
copilot-sdk-go is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Expert guidance for using the GitHub Copilot CLI SDK with Go, including API reference, best practices, and common usage patterns.
Teams using copilot-sdk-go should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/copilot-sdk-go/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How copilot-sdk-go Compares
| Feature / Agent | copilot-sdk-go | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Expert guidance for using the GitHub Copilot CLI SDK with Go, including API reference, best practices, and common usage patterns.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# GitHub Copilot SDK for Go - Skill Guide
This skill provides comprehensive guidance for using the GitHub Copilot CLI SDK with Go programming language.
## Reference Documentation Locations
When working with the Copilot SDK for Go, always refer to these documentation sources:
### Core SDK Documentation
- **Main README**: [./reference/go/README.md](./reference/go/README.md) - Complete API reference, installation, and quick start
- **Type Definitions**: [./reference/go/types.go](./reference/go/types.go) - All type definitions and interfaces
- **Client Implementation**: [./reference/go/client.go](./reference/go/client.go) - Client implementation details
- **Session Management**: [./reference/go/session.go](./reference/go/session.go) - Session handling code
### Cookbook & Examples
- **Cookbook Index**: [./reference/cookbook/README.md](./reference/cookbook/README.md) - Overview of all cookbooks
- **Go Cookbook**: [./reference/cookbook/go/README.md](./reference/cookbook/go/README.md) - Go-specific recipes index
#### Go Recipes (with runnable examples)
- **Error Handling**: [./reference/cookbook/go/error-handling.md](./reference/cookbook/go/error-handling.md)
- Example code: [./reference/cookbook/go/recipe/error-handling.go](./reference/cookbook/go/recipe/error-handling.go)
- **Multiple Sessions**: [./reference/cookbook/go/multiple-sessions.md](./reference/cookbook/go/multiple-sessions.md)
- Example code: [./reference/cookbook/go/recipe/multiple-sessions.go](./reference/cookbook/go/recipe/multiple-sessions.go)
- **Managing Local Files**: [./reference/cookbook/go/managing-local-files.md](./reference/cookbook/go/managing-local-files.md)
- Example code: [./reference/cookbook/go/recipe/managing-local-files.go](./reference/cookbook/go/recipe/managing-local-files.go)
- **PR Visualization**: [./reference/cookbook/go/pr-visualization.md](./reference/cookbook/go/pr-visualization.md)
- Example code: [./reference/cookbook/go/recipe/pr-visualization.go](./reference/cookbook/go/recipe/pr-visualization.go)
- **Persisting Sessions**: [./reference/cookbook/go/persisting-sessions.md](./reference/cookbook/go/persisting-sessions.md)
- Example code: [./reference/cookbook/go/recipe/persisting-sessions.go](./reference/cookbook/go/recipe/persisting-sessions.go)
### Test Examples
- **E2E Tests**: [./reference/go/e2e/](./reference/go/e2e/) - Comprehensive end-to-end test examples
## Installation
```bash
go get github.com/github/copilot-sdk/go
```
## Core Concepts
### 1. Client Creation and Lifecycle
```go
import copilot "github.com/github/copilot-sdk/go"
// Create client with default options
client := copilot.NewClient(nil)
// Or with custom options
client := copilot.NewClient(&copilot.ClientOptions{
LogLevel: "error",
UseStdio: true,
AutoStart: copilot.Bool(true),
AutoRestart: copilot.Bool(true),
})
// Always start the client
if err := client.Start(); err != nil {
log.Fatal(err)
}
defer client.Stop()
```
**Client Options:**
- `CLIPath`: Path to CLI executable (default: "copilot")
- `CLIUrl`: Connect to existing server (format: "localhost:8080" or just "8080")
- `UseStdio`: Use stdio transport (default: true)
- `Port`: Server port for TCP mode
- `LogLevel`: Log level (default: "info")
- `AutoStart`: Auto-start server (default: true, use `Bool(false)` to disable)
- `AutoRestart`: Auto-restart on crash (default: true)
- `GithubToken`: GitHub token for auth
- `UseLoggedInUser`: Use logged-in user auth (default: true)
### 2. Session Management
```go
// Create a new session
session, err := client.CreateSession(&copilot.SessionConfig{
Model: "gpt-5", // Required when using custom provider
SessionID: "my-custom-id", // Optional custom ID
Streaming: true, // Enable streaming responses
})
if err != nil {
log.Fatal(err)
}
defer session.Destroy()
// Resume an existing session
session, err := client.ResumeSession("session-id")
// List all sessions
sessions, err := client.ListSessions()
// Delete a session
err := client.DeleteSession("session-id")
```
**SessionConfig Options:**
- `Model`: Model to use ("gpt-5", "claude-sonnet-4.5", etc.) - Required with custom provider
- `SessionID`: Custom session ID
- `Tools`: Custom tools ([]Tool)
- `SystemMessage`: System message config
- `Provider`: Custom API provider (BYOK)
- `Streaming`: Enable streaming deltas
- `InfiniteSessions`: Auto-compaction config
- `OnUserInputRequest`: Handler for ask_user tool
- `Hooks`: Session lifecycle hooks
- `MCPServers`: MCP server configurations
- `CustomAgents`: Custom agent configs
### 3. Sending Messages and Handling Events
```go
// Set up event handler
done := make(chan bool)
session.On(func(event copilot.SessionEvent) {
switch event.Type {
case "assistant.message":
if event.Data.Content != nil {
fmt.Println(*event.Data.Content)
}
case "assistant.message_delta":
// Streaming chunk
if event.Data.DeltaContent != nil {
fmt.Print(*event.Data.DeltaContent)
}
case "session.idle":
close(done)
}
})
// Send a message
_, err = session.Send(copilot.MessageOptions{
Prompt: "What is 2+2?",
Attachments: []copilot.Attachment{
{Type: "file", Path: "/path/to/file.txt"},
},
})
<-done // Wait for completion
```
### 4. Custom Tools
Using `DefineTool` (recommended - type-safe with auto schema):
```go
type LookupParams struct {
ID string `json:"id" jsonschema:"Issue identifier"`
}
lookupTool := copilot.DefineTool("lookup_issue",
"Fetch issue details",
func(params LookupParams, inv copilot.ToolInvocation) (any, error) {
// params is automatically unmarshaled
return fetchIssue(params.ID)
})
session, _ := client.CreateSession(&copilot.SessionConfig{
Model: "gpt-5",
Tools: []copilot.Tool{lookupTool},
})
```
Using Tool struct directly (more control):
```go
tool := copilot.Tool{
Name: "my_tool",
Description: "Tool description",
Parameters: map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"param": map[string]interface{}{
"type": "string",
"description": "Parameter description",
},
},
"required": []string{"param"},
},
Handler: func(inv copilot.ToolInvocation) (copilot.ToolResult, error) {
args := inv.Arguments.(map[string]interface{})
// Process args
return copilot.ToolResult{
TextResultForLLM: "result",
ResultType: "success",
}, nil
},
}
```
### 5. Custom Providers (BYOK)
**Ollama (local):**
```go
session, err := client.CreateSession(&copilot.SessionConfig{
Model: "deepseek-coder-v2:16b", // Required!
Provider: &copilot.ProviderConfig{
Type: "openai",
BaseURL: "http://localhost:11434/v1",
// APIKey not needed for Ollama
},
})
```
**Azure OpenAI:**
```go
session, err := client.CreateSession(&copilot.SessionConfig{
Model: "gpt-4",
Provider: &copilot.ProviderConfig{
Type: "azure", // Must be "azure", not "openai"!
BaseURL: "https://my-resource.openai.azure.com",
APIKey: os.Getenv("AZURE_OPENAI_KEY"),
Azure: &copilot.AzureProviderOptions{
APIVersion: "2024-10-21",
},
},
})
```
**Custom OpenAI-compatible:**
```go
Provider: &copilot.ProviderConfig{
Type: "openai",
BaseURL: "https://my-api.example.com/v1",
APIKey: os.Getenv("MY_API_KEY"),
}
```
### 6. Streaming Responses
```go
session, err := client.CreateSession(&copilot.SessionConfig{
Model: "gpt-5",
Streaming: true, // Enable streaming
})
session.On(func(event copilot.SessionEvent) {
if event.Type == "assistant.message_delta" {
// Incremental chunks
if event.Data.DeltaContent != nil {
fmt.Print(*event.Data.DeltaContent)
}
} else if event.Type == "assistant.message" {
// Final complete message
fmt.Println("\nComplete!")
}
})
```
### 7. Infinite Sessions (Auto-compaction)
```go
// Default: enabled with default thresholds
session, _ := client.CreateSession(&copilot.SessionConfig{
Model: "gpt-5",
})
// Custom thresholds
session, _ := client.CreateSession(&copilot.SessionConfig{
Model: "gpt-5",
InfiniteSessions: &copilot.InfiniteSessionConfig{
Enabled: copilot.Bool(true),
BackgroundCompactionThreshold: copilot.Float64(0.80), // 80%
BufferExhaustionThreshold: copilot.Float64(0.95), // 95%
},
})
// Disable
InfiniteSessions: &copilot.InfiniteSessionConfig{
Enabled: copilot.Bool(false),
}
// Access workspace path
fmt.Println(session.WorkspacePath())
// => ~/.copilot/session-state/{sessionId}/
```
### 8. User Input Requests (ask_user tool)
```go
session, err := client.CreateSession(&copilot.SessionConfig{
Model: "gpt-5",
OnUserInputRequest: func(req copilot.UserInputRequest, inv copilot.UserInputInvocation) (copilot.UserInputResponse, error) {
fmt.Printf("Question: %s\n", req.Question)
if len(req.Choices) > 0 {
fmt.Printf("Choices: %v\n", req.Choices)
}
// Get user input (implement your UI logic here)
answer := getUserInput()
return copilot.UserInputResponse{
Answer: answer,
WasFreeform: len(req.Choices) == 0,
}, nil
},
})
```
### 9. Session Hooks
```go
session, err := client.CreateSession(&copilot.SessionConfig{
Model: "gpt-5",
Hooks: &copilot.SessionHooks{
OnPreToolUse: func(input copilot.PreToolUseHookInput, inv copilot.HookInvocation) (*copilot.PreToolUseHookOutput, error) {
fmt.Printf("About to run: %s\n", input.ToolName)
return &copilot.PreToolUseHookOutput{
PermissionDecision: "allow", // "allow", "deny", "ask"
ModifiedArgs: input.ToolArgs,
AdditionalContext: "Extra context",
}, nil
},
OnPostToolUse: func(input copilot.PostToolUseHookInput, inv copilot.HookInvocation) (*copilot.PostToolUseHookOutput, error) {
fmt.Printf("Tool completed: %s\n", input.ToolName)
return &copilot.PostToolUseHookOutput{
AdditionalContext: "Post-execution notes",
}, nil
},
OnSessionStart: func(input copilot.SessionStartHookInput, inv copilot.HookInvocation) (*copilot.SessionStartHookOutput, error) {
fmt.Printf("Session started: %s\n", input.Source) // "startup", "resume", "new"
return nil, nil
},
OnSessionEnd: func(input copilot.SessionEndHookInput, inv copilot.HookInvocation) (*copilot.SessionEndHookOutput, error) {
fmt.Printf("Session ended: %s\n", input.Reason)
return nil, nil
},
OnErrorOccurred: func(input copilot.ErrorOccurredHookInput, inv copilot.HookInvocation) (*copilot.ErrorOccurredHookOutput, error) {
return &copilot.ErrorOccurredHookOutput{
ErrorHandling: "retry", // "retry", "skip", "abort"
}, nil
},
},
})
```
## Best Practices
### Error Handling
1. Always use `defer client.Stop()` and `defer session.Destroy()`
2. Handle connection errors (CLI might not be installed)
3. Set appropriate timeouts for long-running requests
4. Use context for cancellation
5. Wrap errors with `fmt.Errorf` and `%w` for error chains
**Example:**
```go
func doWork() error {
client := copilot.NewClient(nil)
if err := client.Start(); err != nil {
return fmt.Errorf("failed to start: %w", err)
}
defer client.Stop()
session, err := client.CreateSession(&copilot.SessionConfig{Model: "gpt-5"})
if err != nil {
return fmt.Errorf("failed to create session: %w", err)
}
defer session.Destroy()
// Work with session...
return nil
}
```
### Multiple Sessions
- One session per user in multi-user apps
- Separate sessions for different tasks
- Use custom session IDs for easy tracking
- Clean up sessions with `DeleteSession()` when done
### Streaming
- Enable `Streaming: true` for real-time responses
- Handle `assistant.message_delta` for incremental updates
- Handle `assistant.reasoning_delta` for model reasoning (if supported)
- Final `assistant.message` always contains complete content
### Image Support
```go
_, err = session.Send(copilot.MessageOptions{
Prompt: "What's in this image?",
Attachments: []copilot.Attachment{
{Type: "file", Path: "/path/to/image.jpg"},
},
})
```
## Common Patterns
### Pattern 1: Simple Question-Answer
```go
client := copilot.NewClient(nil)
client.Start()
defer client.Stop()
session, _ := client.CreateSession(&copilot.SessionConfig{Model: "gpt-5"})
defer session.Destroy()
done := make(chan string)
session.On(func(event copilot.SessionEvent) {
if event.Type == "assistant.message" && event.Data.Content != nil {
done <- *event.Data.Content
}
})
session.Send(copilot.MessageOptions{Prompt: "What is 2+2?"})
fmt.Println(<-done)
```
### Pattern 2: Multiple Sessions
```go
session1, _ := client.CreateSession(&copilot.SessionConfig{
SessionID: "python-help",
Model: "gpt-5",
})
session2, _ := client.CreateSession(&copilot.SessionConfig{
SessionID: "go-help",
Model: "gpt-5",
})
session1.Send(copilot.MessageOptions{Prompt: "Python question"})
session2.Send(copilot.MessageOptions{Prompt: "Go question"})
```
### Pattern 3: Custom Tool with Type Safety
```go
type GitStatusParams struct {
Repo string `json:"repo" jsonschema:"Repository path"`
}
gitStatus := copilot.DefineTool("git_status", "Get git status",
func(params GitStatusParams, inv copilot.ToolInvocation) (any, error) {
output, err := exec.Command("git", "-C", params.Repo, "status").Output()
return string(output), err
})
```
### Pattern 4: Graceful Shutdown
```go
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
go func() {
<-sigChan
fmt.Println("\nShutting down...")
client.Stop()
os.Exit(0)
}()
```
## Helper Functions
- `Bool(v bool) *bool` - Create bool pointers for options
- `Float64(v float64) *float64` - Create float64 pointers for thresholds
```go
AutoStart: copilot.Bool(false)
BackgroundCompactionThreshold: copilot.Float64(0.80)
```
## Transport Modes
- **stdio (default)**: Stdin/stdout pipes - recommended for most cases
- **TCP**: Socket communication - useful for distributed scenarios
```go
// stdio (default)
client := copilot.NewClient(nil)
// TCP with custom port
client := copilot.NewClient(&copilot.ClientOptions{
UseStdio: false,
Port: 8080,
})
// Connect to existing server
client := copilot.NewClient(&copilot.ClientOptions{
CLIUrl: "localhost:8080",
})
```
## Environment Variables
- `COPILOT_CLI_PATH`: Path to Copilot CLI executable
## Troubleshooting
### CLI not found
```go
if err := client.Start(); err != nil {
var execErr *exec.Error
if errors.As(err, &execErr) {
log.Fatal("Copilot CLI not found. Please install it.")
}
}
```
### Connection timeout
Use context with timeout when sending messages.
### Custom provider not working
- Ensure `Model` is specified (required with custom providers)
- For Azure, use `Type: "azure"`, not `"openai"`
- BaseURL should be just the host, no `/v1` path for Azure
## When to Use What
| Use Case | Solution |
|----------|----------|
| Simple chat | Basic session with default config |
| Real-time responses | `Streaming: true` |
| Long conversations | Infinite sessions (default) |
| Custom functionality | Define tools with `DefineTool` |
| Local models | Custom provider with Ollama |
| Multi-user app | Multiple sessions with custom IDs |
| Permission control | Session hooks with `OnPreToolUse` |
| User interaction | `OnUserInputRequest` handler |
| Different models | Multiple sessions with different configs |
## Additional Resources
- Full E2E test examples: `./reference/go/e2e/`
- All type definitions: `./reference/go/types.go`
- Client internals: `./reference/go/client.go`
- Session internals: `./reference/go/session.go`
## Quick Reference
```go
// Essential imports
import copilot "github.com/github/copilot-sdk/go"
// Client lifecycle
client := copilot.NewClient(nil)
client.Start()
defer client.Stop()
// Session lifecycle
session, _ := client.CreateSession(&copilot.SessionConfig{Model: "gpt-5"})
defer session.Destroy()
// Event handling
session.On(func(event copilot.SessionEvent) { /* ... */ })
// Send message
session.Send(copilot.MessageOptions{Prompt: "Hello"})
// Custom tool
copilot.DefineTool("name", "desc", func(params Type, inv copilot.ToolInvocation) (any, error) { /* ... */ })
```Related Skills
copilotkit
Build AI copilots, chatbots, and agentic UIs in React and Next.js using CopilotKit. Use this skill when the user wants to add an AI assistant, copilot, chat interface, AI-powered textarea, or agentic UI to their app. Covers setup, hooks (useCopilotAction, useCopilotReadable, useCoAgent, useAgent), chat components (CopilotPopup, CopilotSidebar, CopilotChat), generative UI, human-in-the-loop, CoAgents with LangGraph, AG-UI protocol, MCP Apps, and Python SDK integration. Triggers on CopilotKit, copilotkit, useCopilotAction, useCopilotReadable, useCoAgent, useAgent, CopilotRuntime, CopilotChat, CopilotSidebar, CopilotPopup, CopilotTextarea, AG-UI, agentic frontend, in-app AI copilot, AI assistant React, chatbot React, useFrontendTool, useRenderToolCall, useDefaultTool, useCoAgentStateRender, useLangGraphInterrupt, useCopilotChat, useCopilotAdditionalInstructions, useCopilotChatSuggestions, useHumanInTheLoop, CopilotTask, copilot runtime, LangGraphAgent, BasicAgent, BuiltInAgent, CopilotKitRemoteEndpoint, A2UI, MCP Apps, AI textarea, AI form completion, add AI to React app.
copilotkit-pitch-deck
Production-ready CopilotKit pitch deck wizard in main application. Use when enhancing AI conversation features, optimizing Edge Function integration, debugging chat interface, or improving pitch deck generation flow. System is PRODUCTION READY (98/100).
copilot-tui-harness
Expert in the Copilot SDK TUI Harness project. Use for development tasks including architecture, event system, plugins, OpenTUI components, and Copilot SDK integration. Triggers on TUI development, harness events, streaming UI, plugin system, event-driven architecture.
copilot-search
Search the web using Claude Code's WebSearch/WebFetch tools combined with GitHub Copilot CLI to find current documentation, best practices, solutions, and technical information. Use when the user needs to research libraries, find API documentation, troubleshoot errors, or learn about new technologies. Requires Copilot CLI installed.
copilot-sdk
Build agentic applications with GitHub Copilot SDK. Use when embedding AI agents in apps, creating custom tools, implementing streaming responses, managing sessions, connecting to MCP servers, or creating custom agents. Triggers on Copilot SDK, GitHub SDK, agentic app, embed Copilot, programmable agent, MCP server, custom agent.
copilot-sdk-dotnet
Build applications with GitHub Copilot CLI SDKs for .NET. Use for direct CopilotClient integration or Microsoft Agent Framework. Covers sessions, streaming, tools, MCP, permissions, and multi-agent workflows.
copilot-sdk-copilot-sdk
Build agentic applications with GitHub Copilot SDK. Use when embedding AI agents in apps, creating custom tools, implementing streaming responses, managing sessions, connecting to MCP servers, or creating custom agents. Triggers on Copilot SDK, GitHub SDK, agentic app, embed Copilot, programmable agent, MCP server, custom agent. Use when: the task directly matches copilot sdk responsibilities within plugin copilot-sdk. Do not use when: a more specific framework or task-focused skill is clearly a better match.
copilot-mcp-server
Direct access to GitHub Copilot MCP server tools for AI-powered development assistance
copilot-instructions-blueprint-generator
Technology-agnostic blueprint generator for creating comprehensive copilot-instructions.md files that guide GitHub Copilot to produce code consistent with project standards, architecture patterns, and exact technology versions by analyzing existing codebase patterns and avoiding assumptions.
awesome-copilot-root-typescript-mcp-expert
Expert assistant for developing Model Context Protocol (MCP) servers in TypeScript Use when: the task directly matches typescript mcp expert responsibilities within plugin awesome-copilot-root. Do not use when: a more specific framework or task-focused skill is clearly a better match.
awesome-copilot-root-rust-mcp-expert
Expert assistant for Rust MCP server development using the rmcp SDK with tokio async runtime Use when: the task directly matches rust mcp expert responsibilities within plugin awesome-copilot-root. Do not use when: a more specific framework or task-focused skill is clearly a better match.
awesome-copilot-root-remember
Transforms lessons learned into domain-organized memory instructions (global or workspace). Syntax: `/remember [>domain [scope]] lesson clue` where scope is `global` (default), `user`, `workspace`, or `ws`. Use when: the task directly matches remember responsibilities within plugin awesome-copilot-root. Do not use when: a more specific framework or task-focused skill is clearly a better match.