January 27th, 2026
0 reactions

Build AI Agents with GitHub Copilot SDK and Microsoft Agent Framework

Dmytro Struk
Senior Software Engineer

Microsoft Agent Framework now integrates with the GitHub Copilot SDK, enabling you to build AI agents powered by GitHub Copilot. This integration brings together the Agent Framework’s consistent agent abstraction with GitHub Copilot’s capabilities, including function calling, streaming responses, multi-turn conversations, shell command execution, file operations, URL fetching, and Model Context Protocol (MCP) server integration — all available in both .NET and Python.

Why Use Agent Framework with GitHub Copilot SDK?

You can use the GitHub Copilot SDK on its own to build agents. So why use it through Agent Framework? Here are the key reasons:

  • Consistent agent abstraction — GitHub Copilot agents implement the same AIAgent (.NET) / BaseAgent (Python) interface as every other agent type in the framework. You can swap providers or combine them without restructuring your code.
  • Multi-agent workflows — Compose GitHub Copilot agents with other agents (Azure OpenAI, OpenAI, Anthropic, and more) in sequential, concurrent, handoff, and group chat workflows using built-in orchestrators.
  • Ecosystem integration — Access the full Agent Framework ecosystem: declarative agent definitions, A2A protocol support, and consistent patterns for function tools, sessions, and streaming across all providers.

In short, Agent Framework lets you treat GitHub Copilot as one building block in a larger agentic system rather than a standalone tool.

Install the GitHub Copilot Integration

.NET

dotnet add package Microsoft.Agents.AI.GithubCopilot --prerelease

Python

pip install agent-framework-github-copilot --pre

Create a GitHub Copilot Agent

Getting started is straightforward. Create a CopilotClient (in .NET) or a GithubCopilotAgent (in Python) and start interacting with the agent.

.NET

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

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)

Add Function Tools

Extend your agent with custom function tools to give it domain-specific capabilities.

.NET

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

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:
    """Get the weather for a given location."""
    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)

Stream Responses

For a better user experience, you can stream responses as they are generated instead of waiting for the complete result.

.NET

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

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()

Multi-Turn Conversations

Maintain conversation context across multiple interactions using sessions (.NET) or threads (Python).

.NET

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();

// First turn
await agent.RunAsync("My name is Alice.", session);

// Second turn - agent remembers the context
AgentResponse response = await agent.RunAsync("What is my name?", session);
Console.WriteLine(response); // Should mention "Alice"

Python

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()

        # First interaction
        result1 = await agent.run("My name is Alice.", thread=thread)
        print(f"Agent: {result1}")

        # Second interaction - agent remembers the context
        result2 = await agent.run("What's my name?", thread=thread)
        print(f"Agent: {result2}")  # Should remember "Alice"

Enable Permissions

By default, the agent cannot execute shell commands, read/write files, or fetch URLs. To enable these capabilities, provide a permission handler that approves or denies requests.

.NET

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

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)

Connect MCP Servers

GitHub Copilot agents support connecting to local (stdio) and remote (HTTP) MCP servers, giving the agent access to external tools and data sources.

.NET

await using CopilotClient copilotClient = new();
await copilotClient.StartAsync();

SessionConfig sessionConfig = new()
{
    OnPermissionRequest = PromptPermission,
    McpServers = new Dictionary<string, object>
    {
        // Local stdio server
        ["filesystem"] = new McpLocalServerConfig
        {
            Type = "stdio",
            Command = "npx",
            Args = ["-y", "@modelcontextprotocol/server-filesystem", "."],
            Tools = ["*"],
        },
        // Remote HTTP server
        ["microsoft-learn"] = new McpRemoteServerConfig
        {
            Type = "http",
            Url = "https://learn.microsoft.com/api/mcp",
            Tools = ["*"],
        },
    },
};

AIAgent agent = copilotClient.AsAIAgent(sessionConfig);

Console.WriteLine(await agent.RunAsync("Search Microsoft Learn for 'Azure Functions' and summarize the top result"));

Python

from agent_framework.github import GithubCopilotAgent
from copilot.types import MCPServerConfig

async def main():
    mcp_servers: dict[str, MCPServerConfig] = {
        # Local stdio server
        "filesystem": {
            "type": "stdio",
            "command": "npx",
            "args": ["-y", "@modelcontextprotocol/server-filesystem", "."],
            "tools": ["*"],
        },
        # Remote HTTP server
        "microsoft-learn": {
            "type": "http",
            "url": "https://learn.microsoft.com/api/mcp",
            "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)

Use GitHub Copilot in a Multi-Agent Workflow

One of the key benefits of using Agent Framework is the ability to combine GitHub Copilot with other agents in a multi-agent workflow. In this example, an Azure OpenAI agent drafts a marketing tagline and a GitHub Copilot agent reviews it — all orchestrated as a sequential pipeline.

.NET

using Azure.AI.OpenAI;
using Azure.Identity;
using GitHub.Copilot.SDK;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.GithubCopilot;
using Microsoft.Agents.AI.Workflows;
using Microsoft.Extensions.AI;

// Create an Azure OpenAI agent as a copywriter
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");

// Create a GitHub Copilot agent as a reviewer
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.");

// Build a sequential workflow: writer -> reviewer
Workflow workflow = AgentWorkflowBuilder.BuildSequential([writer, reviewer]);

// Run the workflow
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

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():
    # Create an Azure OpenAI agent as a copywriter
    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",
    )

    # Create a GitHub Copilot agent as a reviewer
    reviewer = GithubCopilotAgent(
        default_options={"instructions": "You are a thoughtful reviewer. Give brief feedback on the previous assistant message."},
        name="reviewer",
    )

    # Build a sequential workflow: writer -> reviewer
    workflow = SequentialBuilder().participants([writer, reviewer]).build()

    # Run the workflow
    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())

This example shows how a single workflow can combine agents from different providers. You can extend this pattern to concurrent, handoff, and group chat workflows as well.

More Information

Summary

The GitHub Copilot SDK integration for Microsoft Agent Framework makes it easy to build AI agents that leverage GitHub Copilot’s capabilities. With support for function tools, streaming, multi-turn conversations, permissions, and MCP servers in both .NET and Python, you can build powerful agentic applications that interact with code, files, shell commands, and external services.

We’re always interested in hearing from you. If you have feedback, questions or want to discuss further, feel free to reach out to us and the community on the discussion boards on GitHub! We would also love your support, if you’ve enjoyed using Agent Framework, give us a star on GitHub.

Author

Dmytro Struk
Senior Software Engineer

0 comments