我发现 Microsoft Agent Framework 现在与 GitHub Copilot SDK 集成,让我们能够构建由 GitHub Copilot 驱动的 AI 代理。这个集成将 Agent Framework 一致的代理抽象与 GitHub Copilot 的强大功能结合在一起,包括函数调用、流式响应、多轮对话、Shell 命令执行、文件操作、URL 获取以及 Model Context Protocol (MCP) 服务器集成 —— 所有这些功能在 .NET 和 Python 中都可用。
为什么将 Agent Framework 与 GitHub Copilot SDK 结合使用?
你可以单独使用 GitHub Copilot SDK 来构建代理。那么为什么要通过 Agent Framework 来使用它呢?以下是几个关键原因:
- 一致的代理抽象 — GitHub Copilot 代理实现了与框架中其他代理类型相同的
AIAgent (.NET) / BaseAgent (Python) 接口。你可以交换提供者或组合它们,而无需重构代码。
- 多代理工作流 — 使用内置编排器,在顺序、并发、切换和群组聊天工作流中,将 GitHub Copilot 代理与其他代理(Azure OpenAI、OpenAI、Anthropic 等)组合起来。
- 生态系统集成 — 访问完整的 Agent Framework 生态系统:声明式代理定义、A2A 协议支持,以及跨所有提供者的函数工具、会话和流式处理的一致模式。
简而言之,Agent Framework 让我们能够将 GitHub Copilot 视为更大代理系统中的一个构建块,而不是一个独立工具。
安装 GitHub Copilot 集成
.NET
dotnet add package Microsoft.Agents.AI.GitHub.Copilot --prerelease
Python
pip install agent-framework-github-copilot --pre
创建 GitHub Copilot 代理
入门非常简单。创建一个 CopilotClient (在 .NET 中) 或 GitHubCopilotAgent (在 Python 中),然后开始与代理交互。
.NET
1
2
3
4
5
6
7
8
9
|
using GitHub.Copilot.SDK;
using Microsoft.Agents.AI;
await using CopilotClient copilotClient = new();
await copilotClient.StartAsync();
AIAgent agent = copilotClient.AsAIAgent();
Console.WriteLine(await agent.RunAsync("What is Microsoft Agent Framework?"));
|
Python
1
2
3
4
5
6
7
8
9
10
|
from agent_framework.github import GitHubCopilotAgent
async def main():
agent = GitHubCopilotAgent(
default_options={"instructions": "You are a helpful assistant."},
)
async with agent:
result = await agent.run("What is Microsoft Agent Framework?")
print(result)
|
添加函数工具
通过自定义函数工具扩展代理,为其提供特定领域的能力。
.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
using GitHub.Copilot.SDK;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
AIFunction weatherTool = AIFunctionFactory.Create((string location) =>
{
return $"The weather in {location} is sunny with a high of 25C.";
}, "GetWeather", "Get the weather for a given location.");
await using CopilotClient copilotClient = new();
await copilotClient.StartAsync();
AIAgent agent = copilotClient.AsAIAgent(
tools: [weatherTool],
instructions: "You are a helpful weather agent.");
Console.WriteLine(await agent.RunAsync("What's the weather like in Seattle?"));
|
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
from typing import Annotated
from pydantic import Field
from agent_framework.github import GitHubCopilotAgent
def get_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
return f"The weather in {location} is sunny with a high of 25C."
async def main():
agent = GitHubCopilotAgent(
default_options={"instructions": "You are a helpful weather agent."},
tools=[get_weather],
)
async with agent:
result = await agent.run("What's the weather like in Seattle?")
print(result)
|
流式响应
为了获得更好的用户体验,我们可以在生成响应时进行流式传输,而不是等待完整结果。
.NET
1
2
3
4
5
6
7
8
9
10
11
|
await using CopilotClient copilotClient = new();
await copilotClient.StartAsync();
AIAgent agent = copilotClient.AsAIAgent();
await foreach (AgentResponseUpdate update in agent.RunStreamingAsync("Tell me a short story."))
{
Console.Write(update);
}
Console.WriteLine();
|
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
|
from agent_framework.github import GitHubCopilotAgent
async def main():
agent = GitHubCopilotAgent(
default_options={"instructions": "You are a helpful assistant."},
)
async with agent:
print("Agent: ", end="", flush=True)
async for chunk in agent.run_stream("Tell me a short story."):
if chunk.text:
print(chunk.text, end="", flush=True)
print()
|
多轮对话
使用会话 (.NET) 或线程 (Python) 在多次交互中维护对话上下文。
.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
await using CopilotClient copilotClient = new();
await copilotClient.StartAsync();
await using GitHubCopilotAgent agent = new(
copilotClient,
instructions: "You are a helpful assistant. Keep your answers short.");
AgentSession session = await agent.GetNewSessionAsync();
// 第一轮
await agent.RunAsync("My name is Alice.", session);
// 第二轮 - 代理记住上下文
AgentResponse response = await agent.RunAsync("What is my name?", session);
Console.WriteLine(response); // 应该提到 "Alice"
|
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
from agent_framework.github import GitHubCopilotAgent
async def main():
agent = GitHubCopilotAgent(
default_options={"instructions": "You are a helpful assistant."},
)
async with agent:
thread = agent.get_new_thread()
# 第一次交互
result1 = await agent.run("My name is Alice.", thread=thread)
print(f"Agent: {result1}")
# 第二次交互 - 代理记住上下文
result2 = await agent.run("What's my name?", thread=thread)
print(f"Agent: {result2}") # 应该记住 "Alice"
|
启用权限
默认情况下,代理无法执行 Shell 命令、读写文件或获取 URL。要启用这些功能,需要提供一个权限处理程序来批准或拒绝请求。
.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
static Task<PermissionRequestResult> PromptPermission(
PermissionRequest request, PermissionInvocation invocation)
{
Console.WriteLine($"\n[Permission Request: {request.Kind}]");
Console.Write("Approve? (y/n): ");
string? input = Console.ReadLine()?.Trim().ToUpperInvariant();
string kind = input is "Y" or "YES" ? "approved" : "denied-interactively-by-user";
return Task.FromResult(new PermissionRequestResult { Kind = kind });
}
await using CopilotClient copilotClient = new();
await copilotClient.StartAsync();
SessionConfig sessionConfig = new()
{
OnPermissionRequest = PromptPermission,
};
AIAgent agent = copilotClient.AsAIAgent(sessionConfig);
Console.WriteLine(await agent.RunAsync("List all files in the current directory"));
|
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
from agent_framework.github import GitHubCopilotAgent
from copilot.types import PermissionRequest, PermissionRequestResult
def prompt_permission(
request: PermissionRequest, context: dict[str, str]
) -> PermissionRequestResult:
kind = request.get("kind", "unknown")
print(f"\n[Permission Request: {kind}]")
response = input("Approve? (y/n): ").strip().lower()
if response in ("y", "yes"):
return PermissionRequestResult(kind="approved")
return PermissionRequestResult(kind="denied-interactively-by-user")
async def main():
agent = GitHubCopilotAgent(
default_options={
"instructions": "You are a helpful assistant that can execute shell commands.",
"on_permission_request": prompt_permission,
},
)
async with agent:
result = await agent.run("List the Python files in the current directory")
print(result)
|
连接 MCP 服务器
GitHub Copilot 代理支持连接到本地 (stdio) 和远程 (HTTP) MCP 服务器,使代理能够访问外部工具和数据源。
.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
await using CopilotClient copilotClient = new();
await copilotClient.StartAsync();
SessionConfig sessionConfig = new()
{
OnPermissionRequest = PromptPermission,
McpServers = new Dictionary<string, object>
{
// 本地 stdio 服务器
["filesystem"] = new McpLocalServerConfig
{
Type = "stdio",
Command = "npx",
Args = ["-y", "@modelcontextprotocol/server-filesystem", "."],
Tools = ["*"],
},
// 远程 HTTP 服务器
["microsoft-learn"] = new McpRemoteServerConfig
{
Type = "http",
Url = "https://learn.microsoft.com/api/mcp?WT.mc_id=AI-MVP-5003172",
Tools = ["*"],
},
},
};
AIAgent agent = copilotClient.AsAIAgent(sessionConfig);
Console.WriteLine(await agent.RunAsync("Search Microsoft Learn for 'Azure Functions' and summarize the top result"));
|
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
from agent_framework.github import GitHubCopilotAgent
from copilot.types import MCPServerConfig
async def main():
mcp_servers: dict[str, MCPServerConfig] = {
# 本地 stdio 服务器
"filesystem": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "."],
"tools": ["*"],
},
# 远程 HTTP 服务器
"microsoft-learn": {
"type": "http",
"url": "https://learn.microsoft.com/api/mcp?WT.mc_id=AI-MVP-5003172",
"tools": ["*"],
},
}
agent = GitHubCopilotAgent(
default_options={
"instructions": "You are a helpful assistant with access to the filesystem and Microsoft Learn.",
"on_permission_request": prompt_permission,
"mcp_servers": mcp_servers,
},
)
async with agent:
result = await agent.run("Search Microsoft Learn for 'Azure Functions' and summarize the top result")
print(result)
|
在多代理工作流中使用 GitHub Copilot
使用 Agent Framework 的一个关键优势是能够在多代理工作流中将 GitHub Copilot 与其他代理结合使用。在这个示例中,一个 Azure OpenAI 代理起草营销标语,而一个 GitHub Copilot 代理进行审查 —— 所有这些都被编排为顺序管道。
.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
using Azure.AI.OpenAI;
using Azure.Identity;
using GitHub.Copilot.SDK;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.GitHub.Copilot;
using Microsoft.Agents.AI.Workflows;
using Microsoft.Extensions.AI;
// 创建一个 Azure OpenAI 代理作为文案撰写者
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")!;
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
var chatClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
.GetChatClient(deploymentName)
.AsIChatClient();
ChatClientAgent writer = new(chatClient,
"You are a concise copywriter. Provide a single, punchy marketing sentence based on the prompt.",
"writer");
// 创建一个 GitHub Copilot 代理作为审稿人
await using CopilotClient copilotClient = new();
await copilotClient.StartAsync();
GitHubCopilotAgent reviewer = new(copilotClient,
instructions: "You are a thoughtful reviewer. Give brief feedback on the previous assistant message.");
// 构建顺序工作流: writer -> reviewer
Workflow workflow = AgentWorkflowBuilder.BuildSequential([writer, reviewer]);
// 运行工作流
await using StreamingRun run = await InProcessExecution.StreamAsync(workflow, input: prompt);
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
await foreach (WorkflowEvent evt in run.WatchStreamAsync())
{
if (evt is AgentResponseUpdateEvent e)
{
Console.Write(e.Update.Text);
}
}
|
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
import asyncio
from typing import cast
from agent_framework import ChatMessage, Role, SequentialBuilder, WorkflowOutputEvent
from agent_framework.azure import AzureOpenAIChatClient
from agent_framework.github import GitHubCopilotAgent
from azure.identity import AzureCliCredential
async def main():
# 创建一个 Azure OpenAI 代理作为文案撰写者
chat_client = AzureOpenAIChatClient(credential=AzureCliCredential())
writer = chat_client.as_agent(
instructions="You are a concise copywriter. Provide a single, punchy marketing sentence based on the prompt.",
name="writer",
)
# 创建一个 GitHub Copilot 代理作为审稿人
reviewer = GitHubCopilotAgent(
default_options={"instructions": "You are a thoughtful reviewer. Give brief feedback on the previous assistant message."},
name="reviewer",
)
# 构建顺序工作流: writer -> reviewer
workflow = SequentialBuilder().participants([writer, reviewer]).build()
# 运行工作流
async for event in workflow.run_stream("Write a tagline for a budget-friendly electric bike."):
if isinstance(event, WorkflowOutputEvent):
messages = cast(list[ChatMessage], event.data)
for msg in messages:
name = msg.author_name or ("assistant" if msg.role == Role.ASSISTANT else "user")
print(f"[{name}]: {msg.text}\n")
asyncio.run(main())
|
这个示例展示了单个工作流如何组合来自不同提供者的代理。我们也可以将这种模式扩展到并发、切换和群组聊天工作流。
更多信息
总结
Microsoft Agent Framework 的 GitHub Copilot SDK 集成让我能够轻松构建利用 GitHub Copilot 功能的 AI 代理。通过在 .NET 和 Python 中支持函数工具、流式处理、多轮对话、权限管理和 MCP 服务器,我们可以构建强大的代理应用程序,与代码、文件、Shell 命令和外部服务进行交互。
原文链接: Build AI Agents with GitHub Copilot SDK and Microsoft Agent Framework