关于 copilot-sdk
GitHub Copilot SDK 让应用可通过 Python、TypeScript、Go 或 .NET 调用 Copilot 的 Agent 运行时,适合需要嵌入编码与自动化工作流的开发者。它支持自定义工具、Agent、会话和 MCP 服务连接。
主要功能
- 01支持四种语言嵌入 Copilot
- 02流式会话与事件处理
- 03定义自定义工具和 Agent
- 04会话保存、恢复与管理
- 05自定义系统提示词及工具权限
适用场景
- 01在应用中构建交互式 AI 助手
- 02为 Agent 添加应用专属工具
- 03连接 MCP 服务提供预置工具
- 04跨程序重启恢复对话
MCP 相关
可在会话配置中连接 MCP 服务,并将其预置工具用于 Copilot 工作流。也可连接到独立运行的 Copilot CLI 服务端。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ github/ awesome-copilot --skill copilot-sdk安装后在 Claude Code 中输入/copilot-sdk确认已加载。
详细介绍
GitHub Copilot SDK
使用 Python、TypeScript、Go 或 .NET 将 Copilot 的 Agent 工作流嵌入任何应用。
概述
GitHub Copilot SDK 暴露了 Copilot CLI 背后的同一引擎:一个经过生产环境验证的 Agent 运行时,你可以通过编程方式调用它。无需构建自己的编排逻辑——你定义 Agent 的行为,Copilot 负责规划、工具调用、文件编辑等。
前置条件
- GitHub Copilot 访问权限以及一个已认证的环境
- 语言运行时:Node.js ^20.19.0 或 >=22.12.0、Python 3.11+、Go 1.24+,或兼容 .NET Standard 2.0 的实现
- Go:已安装并认证 GitHub Copilot CLI(安装指南)
TypeScript、Python 和 .NET 包默认使用捆绑的 Copilot 运行时,因此无需单独安装 CLI。
安装
Node.js/TypeScript
mkdir copilot-demo && cd copilot-demo
npm init -y --init-type module
npm install @github/copilot-sdk tsx
Python
pip install github-copilot-sdk
# Optional: pre-download the bundled runtime instead of downloading it on first use
python -m copilot download-runtime
已发布的 Python wheel 包含固定版本的运行时。预下载命令会将该运行时缓存到本地;如果跳过,SDK 会在首次使用时尝试自动下载它。
Go
mkdir copilot-demo && cd copilot-demo
go mod init copilot-demo
go get github.com/github/copilot-sdk/go
.NET
dotnet new console -n CopilotDemo && cd CopilotDemo
dotnet add package GitHub.Copilot.SDK
快速开始
TypeScript
import { CopilotClient, approveAll } from "@github/copilot-sdk";
const client = new CopilotClient();
const session = await client.createSession({
onPermissionRequest: approveAll,
model: "gpt-4.1",
});
const response = await session.sendAndWait({ prompt: "What is 2 + 2?" });
console.log(response?.data.content);
await client.stop();
process.exit(0);
运行:npx tsx index.ts
Python
import asyncio
from copilot import CopilotClient, PermissionHandler
async def main():
async with CopilotClient() as client:
async with await client.create_session(
on_permission_request=PermissionHandler.approve_all,
model="gpt-4.1",
) as session:
response = await session.send_and_wait("What is 2 + 2?")
print(response.data.content)
asyncio.run(main())
Go
package main
import (
"fmt"
"log"
"os"
copilot "github.com/github/copilot-sdk/go"
)
func main() {
client := copilot.NewClient(nil)
if err := client.Start(); err != nil {
log.Fatal(err)
}
defer client.Stop()
session, err := client.CreateSession(&copilot.SessionConfig{
OnPermissionRequest: copilot.PermissionHandler.ApproveAll,
Model: "gpt-4.1",
})
if err != nil {
log.Fatal(err)
}
response, err := session.SendAndWait(copilot.MessageOptions{Prompt: "What is 2 + 2?"}, 0)
if err != nil {
log.Fatal(err)
}
fmt.Println(*response.Data.Content)
os.Exit(0)
}
.NET (C#)
using GitHub.Copilot.SDK;
await using var client = new CopilotClient();
await using var session = await client.CreateSessionAsync(new SessionConfig
{
OnPermissionRequest = PermissionHandler.ApproveAll,
Model = "gpt-4.1",
});
var response = await session.SendAndWaitAsync(new MessageOptions { Prompt = "What is 2 + 2?" });
Console.WriteLine(response?.Data.Content);
运行:dotnet run
流式响应
启用实时输出以获得更好的用户体验:
TypeScript
import { CopilotClient, approveAll, SessionEvent } from "@github/copilot-sdk";
const client = new CopilotClient();
const session = await client.createSession({
onPermissionRequest: approveAll,
model: "gpt-4.1",
streaming: true,
});
session.on((event: SessionEvent) => {
if (event.type === "assistant.message_delta") {
process.stdout.write(event.data.deltaContent);
}
if (event.type === "session.idle") {
console.log(); // New line when done
}
});
await session.sendAndWait({ prompt: "Tell me a short joke" });
await client.stop();
process.exit(0);
Python
import asyncio
import sys
from copilot import CopilotClient, PermissionHandler
from copilot.generated.session_events import SessionEventType
async def main():
async with CopilotClient() as client:
async with await client.create_session(
on_permission_request=PermissionHandler.approve_all,
model="gpt-4.1",
streaming=True,
) as session:
def handle_event(event):
if event.type == SessionEventType.ASSISTANT_MESSAGE_DELTA:
sys.stdout.write(event.data.delta_content)
sys.stdout.flush()
if event.type == SessionEventType.SESSION_IDLE:
print()
session.on(handle_event)
await session.send_and_wait("Tell me a short joke")
asyncio.run(main())
Go
session, err := client.CreateSession(&copilot.SessionConfig{
OnPermissionRequest: copilot.PermissionHandler.ApproveAll,
Model: "gpt-4.1",
Streaming: true,
})
session.On(func(event copilot.SessionEvent) {
if event.Type == "assistant.message_delta" {
fmt.Print(*event.Data.DeltaContent)
}
if event.Type == "session.idle" {
fmt.Println()
}
})
_, err = session.SendAndWait(copilot.MessageOptions{Prompt: "Tell me a short joke"}, 0)
.NET
await using var session = await client.CreateSessionAsync(new SessionConfig
{
OnPermissionRequest = PermissionHandler.ApproveAll,
Model = "gpt-4.1",
Streaming = true,
});
session.On(ev =>
{
if (ev is AssistantMessageDeltaEvent deltaEvent)
Console.Write(deltaEvent.Data.DeltaContent);
if (ev is SessionIdleEvent)
Console.WriteLine();
});
await session.SendAndWaitAsync(new MessageOptions { Prompt = "Tell me a short joke" });
自定义工具
定义 Copilot 在推理过程中可以调用的工具。当你定义一个工具时,你告诉 Copilot:
- 该工具做什么(描述)
- 它需要什么参数(schema)
- 要运行什么代码(处理函数)
TypeScript (JSON Schema)
import { CopilotClient, approveAll, defineTool, SessionEvent } from "@github/copilot-sdk";
const getWeather = defineTool("get_weather", {
description: "Get the current weather for a city",
parameters: {
type: "object",
properties: {
city: { type: "string", description: "The city name" },
},
required: ["city"],
},
handler: async (args: { city: string }) => {
const { city } = args;
// In a real app, call a weather API here
const conditions = ["sunny", "cloudy", "rainy", "partly cloudy"];
const temp = Math.floor(Math.random() * 30) + 50;
const condition = conditions[Math.floor(Math.random() * conditions.length)];
return { city, temperature: `${temp}°F`, condition };
},
});
const client = new CopilotClient();
const session = await client.createSession({
onPermissionRequest: approveAll,
model: "gpt-4.1",
streaming: true,
tools: [getWeather],
});
session.on((event: SessionEvent) => {
if (event.type === "assistant.message_delta") {
process.stdout.write(event.data.deltaContent);
}
});
await session.sendAndWait({
prompt: "What's the weather like in Seattle and Tokyo?",
});
await client.stop();
process.exit(0);
Python (Pydantic)
import asyncio
import random
import sys
from copilot import CopilotClient, PermissionHandler
from copilot.tools import define_tool
from copilot.generated.session_events import SessionEventType
from pydantic import BaseModel, Field
class GetWeatherParams(BaseModel):
city: str = Field(description="The name of the city to get weather for")
@define_tool(description="Get the current weather for a city")
async def get_weather(params: GetWeatherParams) -> dict:
city = params.city
conditions = ["sunny", "cloudy", "rainy", "partly cloudy"]
temp = random.randint(50, 80)
condition = random.choice(conditions)
return {"city": city, "temperature": f"{temp}°F", "condition": condition}
async def main():
async with CopilotClient() as client:
async with await client.create_session(
on_permission_request=PermissionHandler.approve_all,
model="gpt-4.1",
streaming=True,
tools=[get_weather],
) as session:
def handle_event(event):
if event.type == SessionEventType.ASSISTANT_MESSAGE_DELTA:
sys.stdout.write(event.data.delta_content)
sys.stdout.flush()
session.on(handle_event)
await session.send_and_wait(
"What's the weather like in Seattle and Tokyo?"
)
asyncio.run(main())
Go
type WeatherParams struct {
City string `json:"city" jsonschema:"The city name"`
}
type WeatherResult struct {
City string `json:"city"`
Temperature string `json:"temperature"`
Condition string `json:"condition"`
}
getWeather := copilot.DefineTool(
"get_weather",
"Get the current weather for a city",
func(params WeatherParams, inv copilot.ToolInvocation) (WeatherResult, error) {
conditions := []string{"sunny", "cloudy", "rainy", "partly cloudy"}
temp := rand.Intn(30) + 50
condition := conditions[rand.Intn(len(conditions))]
return WeatherResult{
City: params.City,
Temperature: fmt.Sprintf("%d°F", temp),
Condition: condition,
}, nil
},
)
session, _ := client.CreateSession(&copilot.SessionConfig{
OnPermissionRequest: copilot.PermissionHandler.ApproveAll,
Model: "gpt-4.1",
Streaming: true,
Tools: []copilot.Tool{getWeather},
})
.NET (Microsoft.Extensions.AI)
using GitHub.Copilot.SDK;
using Microsoft.Extensions.AI;
using System.ComponentModel;
var getWeather = AIFunctionFactory.Create(
([Description("The city name")] string city) =>
{
var conditions = new[] { "sunny", "cloudy", "rainy", "partly cloudy" };
var temp = Random.Shared.Next(50, 80);
var condition = conditions[Random.Shared.Next(conditions.Length)];
return new { city, temperature = $"{temp}°F", condition };
},
"get_weather",
"Get the current weather for a city"
);
await using var session = await client.CreateSessionAsync(new SessionConfig
{
OnPermissionRequest = PermissionHandler.ApproveAll,
Model = "gpt-4.1",
Streaming = true,
Tools = [getWeather],
});
工具如何工作
当 Copilot 决定调用你的工具时:
- Copilot 发送带有参数的工具调用请求
- SDK 运行你的处理函数
- 结果被发送回 Copilot
- Copilot 将结果纳入其响应中
Copilot 根据用户的问题和你的工具描述来决定何时调用你的工具。
交互式命令行助手
构建一个完整的交互式助手:
TypeScript
import { CopilotClient, approveAll, defineTool, SessionEvent } from "@github/copilot-sdk";
import * as readline from "readline";
const getWeather = defineTool("get_weather", {
description: "Get the current weather for a city",
parameters: {
type: "object",
properties: {
city: { type: "string", description: "The city name" },
},
required: ["city"],
},
handler: async ({ city }) => {
const conditions = ["sunny", "cloudy", "rainy", "partly cloudy"];
const temp = Math.floor(Math.random() * 30) + 50;
const condition = conditions[Math.floor(Math.random() * conditions.length)];
return { city, temperature: `${temp}°F`, condition };
},
});
const client = new CopilotClient();
const session = await client.createSession({
onPermissionRequest: approveAll,
model: "gpt-4.1",
streaming: true,
tools: [getWeather],
});
session.on((event: SessionEvent) => {
if (event.type === "assistant.message_delta") {
process.stdout.write(event.data.deltaContent);
}
});
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
console.log("Weather Assistant (type 'exit' to quit)");
console.log("Try: 'What's the weather in Paris?'\n");
const prompt = () => {
rl.question("You: ", async (input) => {
if (input.toLowerCase() === "exit") {
await client.stop();
rl.close();
return;
}
process.stdout.write("Assistant: ");
await session.sendAndWait({ prompt: input });
console.log("\n");
prompt();
});
};
prompt();
Python
import asyncio
import random
import sys
from copilot import CopilotClient, PermissionHandler
from copilot.tools import define_tool
from copilot.generated.session_events import SessionEventType
from pydantic import BaseModel, Field
class GetWeatherParams(BaseModel):
city: str = Field(description="The name of the city to get weather for")
@define_tool(description="Get the current weather for a city")
async def get_weather(params: GetWeatherParams) -> dict:
conditions = ["sunny", "cloudy", "rainy", "partly cloudy"]
temp = random.randint(50, 80)
condition = random.choice(conditions)
return {"city": params.city, "temperature": f"{temp}°F", "condition": condition}
async def main():
async with CopilotClient() as client:
async with await client.create_session(
on_permission_request=PermissionHandler.approve_all,
model="gpt-4.1",
streaming=True,
tools=[get_weather],
) as session:
def handle_event(event):
if event.type == SessionEventType.ASSISTANT_MESSAGE_DELTA:
sys.stdout.write(event.data.delta_content)
sys.stdout.flush()
session.on(handle_event)
print("Weather Assistant (type 'exit' to quit)")
print("Try: 'What's the weather in Paris?'\n")
while True:
try:
user_input = input("You: ")
except EOFError:
break
if user_input.lower() == "exit":
break
sys.stdout.write("Assistant: ")
await session.send_and_wait(user_input)
print("\n")
asyncio.run(main())
MCP 服务集成
连接到 MCP(Model Context Protocol)服务以使用预制工具。连接到 GitHub 的 MCP 服务以访问仓库、issue 和 PR:
TypeScript
const session = await client.createSession({
onPermissionRequest: approveAll,
model: "gpt-4.1",
mcpServers: {
github: {
type: "http",
url: "https://api.githubcopilot.com/mcp/",
},
},
});
Python
async with await client.create_session(
on_permission_request=PermissionHandler.approve_all,
model="gpt-4.1",
mcp_servers={
"github": {
"type": "http",
"url": "https://api.githubcopilot.com/mcp/",
},
},
) as session:
...
Go
session, _ := client.CreateSession(&copilot.SessionConfig{
OnPermissionRequest: copilot.PermissionHandler.ApproveAll,
Model: "gpt-4.1",
MCPServers: map[string]copilot.MCPServerConfig{
"github": {
"type": "http",
"url": "https://api.githubcopilot.com/mcp/",
},
},
})
.NET
await using var session = await client.CreateSessionAsync(new SessionConfig
{
OnPermissionRequest = PermissionHandler.ApproveAll,
Model = "gpt-4.1",
McpServers = new Dictionary<string, McpServerConfig>
{
["github"] = new McpServerConfig
{
Type = "http",
Url = "https://api.githubcopilot.com/mcp/",
},
},
});
自定义 Agent
为特定任务定义专门的 AI 角色:
TypeScript
const session = await client.createSession({
onPermissionRequest: approveAll,
model: "gpt-4.1",
customAgents: [{
name: "pr-reviewer",
displayName: "PR Reviewer",
description: "Reviews pull requests for best practices",
prompt: "You are an expert code reviewer. Focus on security, performance, and maintainability.",
}],
});
Python
async with await client.create_session(
on_permission_request=PermissionHandler.approve_all,
model="gpt-4.1",
custom_agents=[{
"name": "pr-reviewer",
"display_name": "PR Reviewer",
"description": "Reviews pull requests for best practices",
"prompt": "You are an expert code reviewer. Focus on security, performance, and maintainability.",
}],
) as session:
...
系统消息
自定义 AI 的行为和个性:
TypeScript
const session = await client.createSession({
onPermissionRequest: approveAll,
model: "gpt-4.1",
systemMessage: {
content: "You are a helpful assistant for our engineering team. Always be concise.",
},
});
Python
async with await client.create_session(
on_permission_request=PermissionHandler.approve_all,
model="gpt-4.1",
system_message={
"content": "You are a helpful assistant for our engineering team. Always be concise.",
},
) as session:
...
外部 CLI 服务
以服务模式单独运行 CLI,并让 SDK 连接到它。适用于调试、资源共享或自定义环境。
以服务模式启动 CLI
copilot --server --port 4321
将 SDK 连接到外部服务
TypeScript
const client = new CopilotClient({
cliUrl: "localhost:4321"
});
const session = await client.createSession({
onPermissionRequest: approveAll,
model: "gpt-4.1",
});
Python
from copilot import CopilotClient, PermissionHandler, RuntimeConnection
async with CopilotClient(
connection=RuntimeConnection.for_uri("localhost:4321")
) as client:
async with await client.create_session(
on_permission_request=PermissionHandler.approve_all,
model="gpt-4.1",
) as session:
...
Go
client := copilot.NewClient(&copilot.ClientOptions{
CLIUrl: "localhost:4321",
})
if err := client.Start(); err != nil {
log.Fatal(err)
}
session, _ := client.CreateSession(&copilot.SessionConfig{
OnPermissionRequest: copilot.PermissionHandler.ApproveAll,
Model: "gpt-4.1",
})
.NET
using var client = new CopilotClient(new CopilotClientOptions
{
CliUrl = "localhost:4321"
});
await using var session = await client.CreateSessionAsync(new SessionConfig
{
OnPermissionRequest = PermissionHandler.ApproveAll,
Model = "gpt-4.1",
});
注意: 当配置为使用外部服务时,SDK 仅管理其连接,不管理外部进程。
事件类型
| 事件 | 描述 |
|---|---|
user.message | 添加了用户输入 |
assistant.message | 完整的模型响应 |
assistant.message_delta | 流式响应块 |
assistant.reasoning | 模型推理(取决于模型) |
assistant.reasoning_delta | 流式推理块 |
tool.execution_start | 工具调用已开始 |
tool.execution_complete | 工具执行已完成 |
session.idle | 没有活动处理 |
session.error | 发生了错误 |
客户端配置
| 选项 | 描述 | 默认值 |
|---|---|---|
cliPath | Copilot CLI 可执行文件的路径 | 系统 PATH |
cliUrl | 连接到已有服务(例如 "localhost:4321") | 无 |
port | 服务通信端口 | 随机 |
useStdio | 使用 stdio 传输而不是 TCP | true |
logLevel | 日志详细程度 | "info" |
autoStart | 自动启动服务 | true |
autoRestart | 崩溃后重启 | true |
cwd | CLI 进程的工作目录 | 继承 |
会话配置
| 选项 | 描述 |
|---|---|
model | 要使用的大模型("gpt-4.1"、"claude-sonnet-4.5" 等) |
sessionId | 自定义会话标识符 |
tools | 自定义工具定义 |
mcpServers | MCP 服务连接 |
customAgents | 自定义 Agent 角色 |
systemMessage | 覆盖默认系统提示词 |
streaming | 启用增量响应块 |
availableTools | 允许的工具白名单 |
excludedTools | 禁用的工具黑名单 |
会话持久化
跨重启保存并恢复对话:
使用自定义 ID 创建
const session = await client.createSession({
onPermissionRequest: approveAll,
sessionId: "user-123-conversation",
model: "gpt-4.1"
});
恢复会话
const session = await client.resumeSession("user-123-conversation", { onPermissionRequest: approveAll });
await session.send({ prompt: "What did we discuss earlier?" });
列出和删除会话
const sessions = await client.listSessions();
await client.deleteSession("old-session-id");
错误处理
try {
const client = new CopilotClient();
const session = await client.createSession({
onPermissionRequest: approveAll,
model: "gpt-4.1",
});
const response = await session.sendAndWait(
{ prompt: "Hello!" },
30000 // timeout in ms
);
} catch (error) {
if (error.code === "ENOENT") {
console.error("Copilot CLI not installed");
} else if (error.code === "ECONNREFUSED") {
console.error("Cannot connect to Copilot server");
} else {
console.error("Error:", error.message);
}
} finally {
await client.stop();
}
优雅关闭
process.on("SIGINT", async () => {
console.log("Shutting down...");
await client.stop();
process.exit(0);
});
常见模式
多轮对话
const session = await client.createSession({
onPermissionRequest: approveAll,
model: "gpt-4.1",
});
await session.sendAndWait({ prompt: "My name is Alice" });
await session.sendAndWait({ prompt: "What's my name?" });
// Response: "Your name is Alice"
文件附件
await session.send({
prompt: "Analyze this file",
attachments: [{
type: "file",
path: "./data.csv",
displayName: "Sales Data"
}]
});
中止长时间操作
const timeoutId = setTimeout(() => {
session.abort();
}, 60000);
session.on((event) => {
if (event.type === "session.idle") {
clearTimeout(timeoutId);
}
});
可用模型
在运行时查询可用模型:
const models = await client.getModels();
// Returns: ["gpt-4.1", "gpt-4o", "claude-sonnet-4.5", ...]
最佳实践
- 始终清理:使用语言原生的上下文管理器或释放机制,或显式断开会话并停止客户端
- 设置超时:对长时间操作使用带超时的
sendAndWait - 处理事件:订阅错误事件以实现健壮的错误处理
- 使用流式传输:对长响应启用流式传输以改善用户体验
- 持久化会话:对多轮对话使用自定义会话 ID
- 定义清晰的工具:编写描述性的工具名称和描述
架构
Your Application
|
SDK Client
| JSON-RPC
Copilot CLI (server mode)
|
GitHub (models, auth)
SDK 自动管理 CLI 进程的生命周期。所有通信都通过 stdio 或 TCP 上的 JSON-RPC 进行。
资源
- GitHub 仓库:https://github.com/github/copilot-sdk
- 入门教程:https://github.com/github/copilot-sdk/blob/main/docs/tutorials/first-app.md
- GitHub MCP 服务:https://github.com/github/github-mcp-server
- MCP 服务目录:https://github.com/modelcontextprotocol/servers
- Cookbook:https://github.com/github/copilot-sdk/tree/main/cookbook
- 示例:https://github.com/github/copilot-sdk/tree/main/samples
状态
此 SDK 处于 技术预览 阶段,可能会有破坏性变更。目前尚不建议用于生产环境。