我发现 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