How to Use the Copilot SDK to Build Custom Copilot Features: A Complete Guide
Yes, the GitHub Copilot SDK is specifically designed for extending Copilot with custom agents, skills, tools, and hooks, enabling you to build bespoke AI-driven features without writing orchestration code.
The github/copilot-sdk repository provides a multi-language toolkit that lets you programmatically control Copilot's behavior. By defining custom agents with specialized prompts and tool permissions, you can create domain-specific AI assistants that run inside your existing applications while the SDK handles all runtime delegation and lifecycle management.
Understanding the Copilot SDK Architecture
The SDK communicates with the Copilot CLI through JSON-RPC in server mode. When you initialize a CopilotClient, it manages a local Copilot CLI process and establishes a persistent connection for command execution.
According to the source architecture outlined in README.md, the runtime operates through a delegation pattern:
- Your application creates a session with a list of
customAgents - The runtime analyzes the user's intent against each agent's
descriptionfield - The best-fit sub-agent is automatically selected and executed in an isolated context
- Lifecycle events stream back to your application via the session callback
This architecture eliminates the need to write complex agent orchestration logic, as the Copilot runtime handles intent matching and sub-agent coordination automatically.
Defining Custom Agents for Specialized Tasks
Custom agents are configured during session creation through the customAgents array parameter. Each agent definition in docs/features/custom-agents.md requires specific fields that control its behavior and capabilities.
Key configuration properties:
name: Machine-readable identifier for the agentdisplayName: Human-readable label shown in UIdescription: Natural language description used by the runtime for intent matchingtools: Array of permitted tools (e.g.,["grep", "glob", "view"],["view", "edit", "bash"])prompt: System instructions defining the agent's personality and constraints
The runtime uses the description field (and optional infer flag) to determine which agent should handle a specific user request. You can also override the base model and reasoning effort on a per-agent basis, or attach dedicated MCP (Model Context Protocol) servers for specialized data sources.
Implementing Custom Copilot Features in Multiple Languages
The SDK supports Node.js/TypeScript, Python, Go, .NET, Java, and Rust, allowing you to implement custom features in your preferred language. Below are complete examples creating a research agent (read-only) and an editor agent (write-capable).
Node.js / TypeScript Implementation
import { CopilotClient } from "@github/copilot-sdk";
const client = new CopilotClient();
await client.start();
const session = await client.createSession({
model: "gpt-5.4",
customAgents: [
{
name: "researcher",
displayName: "Research Agent",
description: "Explores codebases and answers questions using read‑only tools",
tools: ["grep", "glob", "view"],
prompt: "You are a research assistant. Analyze code and answer questions. Do not modify any files."
},
{
name: "editor",
displayName: "Editor Agent",
description: "Makes targeted code changes",
tools: ["view", "edit", "bash"],
prompt: "You are a code editor. Make minimal, surgical changes to files as requested."
}
],
onPermissionRequest: async () => ({ kind: "approve-once" })
});
Python Implementation
from copilot import CopilotClient, PermissionDecisionApproveOnce
client = CopilotClient()
await client.start()
session = await client.create_session(
model="gpt-5.4",
custom_agents=[
{
"name": "researcher",
"display_name": "Research Agent",
"description": "Explores codebases and answers questions using read‑only tools",
"tools": ["grep", "glob", "view"],
"prompt": "You are a research assistant. Analyze code and answer questions. Do not modify any files."
},
{
"name": "editor",
"display_name": "Editor Agent",
"description": "Makes targeted code changes",
"tools": ["view", "edit", "bash"],
"prompt": "You are a code editor. Make minimal, surgical changes to files as requested."
}
],
on_permission_request=lambda req, inv: PermissionDecisionApproveOnce()
)
Go Implementation
ctx := context.Background()
client := copilot.NewClient(nil)
client.Start(ctx)
session, _ := client.CreateSession(ctx, &copilot.SessionConfig{
Model: "gpt-5.4",
CustomAgents: []copilot.CustomAgentConfig{
{
Name: "researcher",
DisplayName: "Research Agent",
Description: "Explores codebases and answers questions using read‑only tools",
Tools: []string{"grep", "glob", "view"},
Prompt: "You are a research assistant. Analyze code and answer questions. Do not modify any files.",
},
{
Name: "editor",
DisplayName: "Editor Agent",
Description: "Makes targeted code changes",
Tools: []string{"view", "edit", "bash"},
Prompt: "You are a code editor. Make minimal, surgical changes to files as requested.",
},
},
OnPermissionRequest: func(req copilot.PermissionRequest, inv copilot.PermissionInvocation) (rpc.PermissionDecision, error) {
return &rpc.PermissionDecisionApproveOnce{}, nil
},
})
.NET (C#) Implementation
await using var client = new CopilotClient();
await using var session = await client.CreateSessionAsync(new SessionConfig {
Model = "gpt-5.4",
CustomAgents = new List<CustomAgentConfig> {
new() {
Name = "researcher",
DisplayName = "Research Agent",
Description = "Explores codebases and answers questions using read‑only tools",
Tools = new List<string> { "grep", "glob", "view" },
Prompt = "You are a research assistant. Analyze code and answer questions. Do not modify any files."
},
new() {
Name = "editor",
DisplayName: "Editor Agent",
Description: "Makes targeted code changes",
Tools = new List<string> { "view", "edit", "bash" },
Prompt = "You are a code editor. Make minimal, surgical changes to files as requested."
}
},
OnPermissionRequest = (req, inv) => Task.FromResult(PermissionDecision.ApproveOnce())
});
Java Implementation
var session = client.createSession(
new SessionConfig()
.setModel("gpt-5.4")
.setCustomAgents(List.of(
new CustomAgentConfig()
.setName("researcher")
.setDisplayName("Research Agent")
.setDescription("Explores codebases and answers questions using read‑only tools")
.setTools(List.of("grep", "glob", "view"))
.setPrompt("You are a research assistant. Analyze code and answer questions. Do not modify any files."),
new CustomAgentConfig()
.setName("editor")
.setDisplayName("Editor Agent")
.setDescription("Makes targeted code changes")
.setTools(List.of("view", "edit", "bash"))
.setPrompt("You are a code editor. Make minimal, surgical changes to files as requested.")
))
.setOnPermissionRequest(PermissionHandler.APPROVE_ALL)
).get();
Handling Sub-Agent Lifecycle Events
The SDK streams real-time events during sub-agent execution, allowing your application to update UI or trigger side effects. As documented in docs/features/custom-agents.md, the session object emits events for every state transition.
Available event types:
subagent.started: Fired when a sub-agent begins executionsubagent.completed: Fired when a sub-agent finishes successfullysubagent.failed: Fired when execution encounters an errorsubagent.selected/deselected: Fired when the runtime changes active agents
Listen to these events using the session's event handler:
session.on(event => {
if (event.type === "subagent.started") {
console.log(`▶ Sub‑agent started: ${event.data.agentDisplayName}`);
}
// Handle completed, failed, selected, deselected similarly...
});
Advanced Customization Options
Beyond custom agents, the Copilot SDK provides additional extension points for sophisticated integrations:
- Hooks: Attach custom logic at
pre-tool-useorpost-tool-usephases by implementing handlers described indocs/hooks/README.md - Skills: Preload domain-specific knowledge into agent context using the patterns shown in
docs/features/skills.md - BYOK Authentication: Deploy custom features without requiring end-users to have GitHub Copilot subscriptions using the Bring-Your-Own-Key flow documented in
docs/auth/byok.md - MCP Servers: Attach specialized Model Context Protocol servers to individual agents for access to proprietary data sources
Summary
- The Copilot SDK enables building custom Copilot features through a JSON-RPC client architecture that manages the Copilot CLI process
- Custom agents are defined via the
customAgentsarray increateSession(), specifying permitted tools, prompts, and descriptions for runtime matching - The SDK automatically handles intent detection and delegates to the appropriate sub-agent based on natural language descriptions
- Lifecycle events (
subagent.started,subagent.completed, etc.) stream back to your application for real-time UI updates - Full support for Node.js/TypeScript, Python, Go, .NET, Java, and Rust with identical API patterns across languages
- Advanced features include hooks, skills, BYOK authentication, and per-agent MCP server attachment
Frequently Asked Questions
Can I use the Copilot SDK without a GitHub subscription?
Yes. The SDK supports Bring-Your-Own-Key (BYOK) authentication as documented in docs/auth/byok.md. This allows you to build and deploy custom Copilot features that use your own API keys rather than requiring end-users to have GitHub Copilot subscriptions.
What programming languages does the Copilot SDK support?
The SDK officially supports Node.js/TypeScript, Python, Go, .NET (C#), Java, and Rust. All language implementations provide the same core functionality including custom agent definition, session management, and event streaming, though naming conventions follow each language's idioms (e.g., custom_agents in Python vs CustomAgents in C#).
How does the runtime choose which custom agent to use?
The Copilot runtime analyzes the user's request against each agent's description field using natural language understanding. Agents can optionally set an infer flag to control matching behavior. The runtime selects the best-fit sub-agent automatically and executes it in isolation, streaming results back to the parent session.
Can I restrict which tools a custom agent can access?
Absolutely. Each custom agent configuration includes a tools array that explicitly whitelist which Copilot tools the agent may invoke. For example, a research agent might only receive ["grep", "glob", "view"] while an editor agent gets ["view", "edit", "bash"], creating security boundaries between different agent capabilities.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →