Skip to main content

Multi-agent patterns with the GitHub Copilot SDK (continued)

This final post continues on the multi-agent path: instead of one agent doing more things, we compose multiple agents doing the right things.

Yesterday I demonstrated how to do this inside the Copilot SDK itself, today we look the broader ecosystem and I’ll show you how to integrate your Copilot SDK agent in the Microsoft Agent Framework.

Microsoft Agent Framework

The Microsoft Agent Framework(MAF) is the unified successor to Semantic Kernel and AutoGen. It provides a standard interface for building, orchestrating, and deploying AI agents. Dedicated integration packages let you wrap a Copilot SDK client as a first-class MAF agent — interchangeable with any other agent provider in the framework.

The key distinction from Part 1: custom agents inside the SDK work within a single Copilot session, with the Copilot runtime as orchestrator. MAF operates at a higher level — it can compose a Copilot SDK agent with agents backed by Azure OpenAI, Anthropic, or any other provider, using structured orchestration patterns that MAF controls.

Microsoft Agent Framework serves as the orchestration backbone while calling the GitHub Copilot SDK for the agent harness layer. Any agent in the workflow can delegate to a Copilot SDK-powered agent — leveraging its native Model Context Protocol support, skills integration, shell execution, and file operations — then pass results to the next agent in the pipeline.

Setup: Adding the MAF integration package

dotnet add package Microsoft.Agents.AI.GitHub.Copilot --prerelease

This adds the integration that lets you convert a CopilotClient into a standard MAF AIAgent.

The Core Conversion: AsAIAgent()

Create a CopilotClient and use the AsAIAgent extension method to create an agent. The Copilot agent is a standard MAF agent, so it supports tools, instructions, streaming, sessions, MCP servers, and built-in OpenTelemetry observability.

using GitHub.Copilot;
using Microsoft.Agents.AI;

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

AIAgent reviewAgent = copilotClient.AsAIAgent(
sessionConfig: new SessionConfig
{
    OnPermissionRequest=PermissionHandler.ApproveAll,
    Streaming=true,
Tools = [AIFunctionFactory.Create(GetProjectConventions)] }, ownsClient: true, name: "Code Reviewer", description: "You are a thorough code reviewer. Focus on correctness, clarity, and edge cases."
);

// Run standalone, just like any other MAF agent
Console.WriteLine(await copilotAgent.RunAsync("What changed in the last three commits?"));

Once wrapped as an AIAgent, the Copilot SDK agent is interchangeable with any other MAF agent. The orchestration layer doesn't know or care what's backing it.

Remark: At the moment of writing this blog post, there is a problem with the AsAIAgent extension method as there is a namespace conflict between the latest (preview) version of the package and the GitHub Copilot SDK NuGet package.

Advanced orchestration - An example

Multi-agent systems often start as a router that forwards to a specialist and sometimes break the first time an agent needs a follow-up question, more context from a peer, or realizes mid-turn that the request belongs elsewhere. Handoff orchestration is built for exactly that: you declare the agents and the directed edges between them, and the framework injects the handoff tools each agent uses to transfer control. Topology and guardrails stay with the developer; routing decisions stay with the agents.

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

AIAgent triage = copilotClient.AsAIAgent(new SessionConfig
        {
            OnPermissionRequest = PermissionHandler.ApproveAll,
        },
        name:"Triage Agent", 
        description: """
        You are a triage agent. Classify incoming requests:
        - If it's a bug report, hand off to 'bug-investigator'
        - If it's a feature request, hand off to 'feature-planner'
        - If it's unclear, ask the user to clarify before handing off
        """);

AIAgent bugInvestigator = copilotClient.AsAIAgent(new SessionConfig
        {
            OnPermissionRequest = PermissionHandler.ApproveAll,
        },
        name:"Bug Investigator", 
        description: """
        You investigate bug reports. Read code, trace execution, identify root causes.
        """);

// Azure OpenAI agent for structured planning output
var openAIClient = new OpenAI.OpenAIClient("<apikey>");
var featurePlanner=openAIClient.GetChatClient("gpt-4.1").AsAIAgent();

// Define the topology: triage can hand off to either specialist
HandoffWorkflowBuilder handoffBuilder = AgentWorkflowBuilder
    .CreateHandoffBuilderWith(featurePlanner)
        .WithHandoff(triage, bugInvestigator)
        .WithHandoff(triage, featurePlanner);

var workflow = handoffBuilder.Build();

await using StreamingRun run = await InProcessExecution.OpenStreamingAsync(workflow)
                                                          .ConfigureAwait(false);

await run.TrySendMessageAsync("Users are reporting that the export function produces empty CSV files when the date filter is active");

Triage receives every request. It decides which specialist is appropriate and hands off. The agents decide the routing; the developer controls which handoffs are allowed in the topology. Invalid routes (an agent trying to hand off to a destination not in the graph) are rejected by the framework.

Choosing between SDK custom agents and MAF orchestration

Both approaches produce multi-agent behaviour. The choice comes down to what you need:

  Copilot SDK Custom Agents Microsoft Agent Framework
Shared session context Yes — agents share conversation history No — agents have independent contexts
Orchestrator Copilot runtime (inference-based) MAF (deterministic graph topology)
Cross-provider No — all agents run on Copilot Yes — mix any MAF provider
Routing control Agent descriptions (semantic matching) You declare the topology and edges
Setup complexity Low — one SessionConfig Higher — MAF orchestrator + packages
Best for Mixed-intent interactive sessions Structured, repeatable pipelines

The two approaches are also composable. A Copilot SDK agent wrapped with AsAIAgent() can itself use custom agents internally — the MAF orchestrator sees only a single AIAgent, while internally the Copilot runtime delegates to its sub-agents. You can layer both patterns where it makes sense.

More information

MAF integration

Popular posts from this blog

Podman– Command execution failed with exit code 125

After updating WSL on one of the developer machines, Podman failed to work. When we took a look through Podman Desktop, we noticed that Podman had stopped running and returned the following error message: Error: Command execution failed with exit code 125 Here are the steps we tried to fix the issue: We started by running podman info to get some extra details on what could be wrong: >podman info OS: windows/amd64 provider: wsl version: 5.3.1 Cannot connect to Podman. Please verify your connection to the Linux system using `podman system connection list`, or try `podman machine init` and `podman machine start` to manage a new Linux VM Error: unable to connect to Podman socket: failed to connect: dial tcp 127.0.0.1:2655: connectex: No connection could be made because the target machine actively refused it. That makes sense as the podman VM was not running. Let’s check the VM: >podman machine list NAME         ...

Azure DevOps/ GitHub emoji

I’m really bad at remembering emoji’s. So here is cheat sheet with all emoji’s that can be used in tools that support the github emoji markdown markup: All credits go to rcaviers who created this list.

VS Code Planning mode

After the introduction of Plan mode in Visual Studio , it now also found its way into VS Code. Planning mode, or as I like to call it 'Hannibal mode', extends GitHub Copilot's Agent Mode capabilities to handle larger, multi-step coding tasks with a structured approach. Instead of jumping straight into code generation, Planning mode creates a detailed execution plan. If you want more details, have a look at my previous post . Putting plan mode into action VS Code takes a different approach compared to Visual Studio when using plan mode. Instead of a configuration setting that you can activate but have limited control over, planning is available as a separate chat mode/agent: I like this approach better than how Visual Studio does it as you have explicit control when plan mode is activated. Instead of immediately diving into execution, the plan agent creates a plan and asks some follow up questions: You can further edit the plan by clicking on ‘Open in Editor’: ...