SquadSquad

⚠️ PreviewSquad.Agents.AI is a preview package. APIs may change before stable release. Use --prerelease when installing and pin to a specific version in production builds.

Squad.Agents.AI exposes any Squad team as a Microsoft Agent Framework (MAF) AIAgent. Once registered, a SquadAgent participates in durable workflows alongside Azure OpenAI, Anthropic, and every other MAF provider — with DTS checkpointing, Aspire dashboard observability, and streaming out of the box.


How it works

SquadAgent is a sealed class SquadAgent : DelegatingAIAgent, IAsyncDisposable. It creates a CopilotClient from the GitHub.Copilot namespace, then calls client.AsAIAgent(sessionConfig, ...) to produce the inner MAF agent. All MAF sessions, runs, and streaming calls delegate to that inner agent.

SessionConfig.EnableConfigDiscovery = true is set automatically so the CLI discovers .squad/ charters, skills, and MCP servers at session start instead of per-turn file reads.

DTS checkpoint/restore operates through MAF’s base-class mechanisms — there are no Squad-specific serialize/deserialize methods.


Prerequisites

RequirementCheck
GitHub Copilot subscription (Individual, Business, or Enterprise)
GitHub Copilot CLI on PATHcopilot --version
.NET 8, 9, or 10 SDKdotnet --version
Initialized Squad team rootls .squad/ (or squad init to create one)

Authentication uses the signed-in GitHub Copilot CLI user by default. No separate API key is required for the minimal path. Run gh auth login or copilot auth login before your first run.


Install

dotnet add package Squad.Agents.AI --prerelease

Minimum version for Aspire dashboard observability: 0.5.1. Current version: 0.5.6-rc1.

GitHub.Copilot.SDK direct reference — active workaround

Squad.Agents.AI 0.5.6-rc1 ships a buildTransitive/Squad.Agents.AI.props that pins the correct GitHub.Copilot.SDK version for all consumers, so most users do not need to add a direct reference. If you are on an older version of Squad.Agents.AI and see:

InvalidOperationException: Copilot runtime not found

add the direct reference that was previously required:

<PackageReference Include="GitHub.Copilot.SDK" Version="*-*" />

The root cause is that without a direct PackageReference, the SDK’s MSBuild targets that copy copilot.exe into bin/ do not fire for transitive consumers. The upstream fix is tracked in microsoft/agent-framework#6457. Squad.Agents.AI 0.5.6-rc1 works around it independently via the generated buildTransitive bridge.


DI registration

Single team

using Microsoft.Extensions.Hosting;
using Squad.Agents.AI;

var builder = Host.CreateApplicationBuilder(args);

builder.Services.AddSquadAgent(o =>
{
    o.SquadFolderPath = "/path/to/your/team-root";
});

AddSquadAgent registers both SquadAgent and the base AIAgent with scoped lifetime. Inject either type.

Multiple teams (keyed DI, .NET 8+)

builder.Services.AddKeyedSquadAgent("research", o =>
{
    o.SquadFolderPath = "/teams/research";
});

builder.Services.AddKeyedSquadAgent("platform", o =>
{
    o.SquadFolderPath = "/teams/platform";
});

Keyed and non-keyed registrations coexist. Resolve keyed agents with [FromKeyedServices("research")] or provider.GetRequiredKeyedService<SquadAgent>("research").

Lifetime

The default lifetime is scoped. Pass a ServiceLifetime parameter to any overload to override:

builder.Services.AddSquadAgent(ServiceLifetime.Singleton, o => { ... });

Send a turn

using Microsoft.Agents.AI;

var squad = host.Services.GetRequiredService<AIAgent>();
var session = await squad.CreateSessionAsync();
var response = await squad.RunAsync("What can this team do?", session);
Console.WriteLine(response.Text);

Streaming

// Assumes host is the IHost built in the DI registration step above.
var squad = host.Services.GetRequiredService<SquadAgent>();
var session = await squad.CreateSessionAsync();

await foreach (var update in squad.RunStreamingAsync("Summarize the team.", session))
{
    Console.Write(update.Text);
}
Console.WriteLine();

Session and state behavior

MAF session objects are managed by the framework. Each CreateSessionAsync() call starts a fresh conversation context; passing the same session object across multiple RunAsync calls maintains conversational state for that session’s lifetime.

DTS checkpoint/restore — surviving process restarts between durable workflow steps — is provided by MAF’s base-class mechanisms, not by Squad-specific methods. See the MAF durable workflow docs for checkpoint configuration.


Aspire dashboard observability

Squad.Agents.AI emits one OpenTelemetry Activity per subagent dispatch. Each span is named squad.subagent {Name} and tagged with squad.subagent.name, squad.subagent.display_name, and squad.subagent.reply_preview. Timeline events mark every lifecycle transition (squad.subagent.start, squad.subagent.message, squad.subagent.completed, squad.subagent.failed).

Wire it up in two lines:

using OpenTelemetry.Trace;
using Squad.Agents.AI;

builder.Services.AddOpenTelemetry()
    .WithTracing(t => t.AddSource(SquadAgentDiagnostics.ActivitySourceName));

The Aspire dashboard then shows one squad.subagent span per specialist dispatch in the Traces view.

For full AppHost integration (embedding a Squad team as an Aspire resource), see Using Squad with the Aspire Dashboard.

To disable Squad’s built-in spans and drive observability yourself:

builder.Services.AddSquadAgent(o =>
{
    o.SquadFolderPath = "/teams/main";
    o.EmitSubagentActivities = false;
    o.OnSubagentTrace = trace =>
    {
        if (trace.Kind == SquadAgentTraceEventKind.SubagentStarted)
            MyMetrics.IncrementSpawn(trace.SubagentName!);
    };
});

Cross-reference: open issue #1144 tracks additional telemetry from embedded hosts.


Security

⚠️ PermissionHandler.ApproveAll is for local dev and fully-trusted automated pipelines only.

SquadAgent sets OnPermissionRequest = PermissionHandler.ApproveAll on the SessionConfig by default. This silently approves every permission request — shell access, file reads, URL fetches — without review. Do not use this in public-facing or multi-tenant server deployments.

For production, supply a scoped handler via SquadAgentOptions.ConfigureSession. Set sessionConfig.OnPermissionRequest to a delegate that inspects the incoming permission request and returns a PermissionDecision — for example, rejecting shell or file requests while approving others. The full PermissionDecision API surface (including ApproveOnce, Reject, and session-scoped variants) is documented in the GitHub Copilot SDK permission handler reference.

Additional security notes:

  • GitHubToken and Environment values matching secret-pattern keys are redacted in ToString() output.
  • GitHubToken, GitHubTokenProvider, Environment, and ConfigureCopilotClient are [JsonIgnore] — they will not appear in JSON serialization.
  • The ConfigureCopilotClient delegate cannot change Cwd, CliPath, or CliArgs — Squad restores those values to prevent routing to an unintended CLI process.
  • Never embed tokens in source code. Use GitHubTokenProvider or managed identity for production token retrieval.

Hosting and container considerations

The Copilot CLI runs as a subprocess. It must be present in the deployment environment.

  • Local dev / CI: GitHub.Copilot.SDK’s MSBuild targets copy the correct RID binary into bin/{cfg}/{tfm}/runtimes/{rid}/native/ at build time.

  • Container images: Verify the {rid} artefact matches the container OS/arch. For Linux containers built on Windows, use --runtime linux-x64 or equivalent.

  • Azure Container Apps / AKS: Install the CLI in the container image (npm install -g @github/copilot, requires Node.js in the base image), then set SquadAgentOptions.CliPath at DI registration time to the absolute binary path. CliPath is a property on SquadAgentOptions — set it in your AddSquadAgent callback and Squad passes it to the SDK’s RuntimeConnection.ForStdio at startup:

    builder.Services.AddSquadAgent(o =>
    {
        o.SquadFolderPath = "/teams/main";
        o.CliPath = "/usr/local/bin/copilot"; // absolute path inside the container
    });
  • GitHub Actions: Install the CLI in a workflow step and authenticate via a Copilot-enabled PAT or GITHUB_TOKEN.


Decision matrix

ScenarioRecommended approach
Interactive CLI workflow, local dev, prompt scriptingSquad CLI (squad, squad aspire)
TypeScript / JavaScript integration, Copilot SDK extensions@bradygaster/squad-sdk (TypeScript SDK)
.NET durable workflows, multi-model composition, Aspire AppHostSquad.Agents.AI (this guide)
Embedding multiple teams in one .NET appAddKeyedSquadAgent with per-team keys

Troubleshooting

ErrorCauseFix
InvalidOperationException: Copilot runtime not foundNative CLI binary not in output; old package versionUpgrade to Squad.Agents.AI version 0.5.6-rc1 or later; if still failing, add direct GitHub.Copilot.SDK reference
GitHub Copilot CLI was not found on PATHcopilot binary missingInstall from github.com/github/copilot-cli and verify with copilot --version
Authentication failed / 401CLI not signed inRun gh auth login or copilot auth login
SquadFolderPath does not existPath does not point to an initialized team rootRun squad init in the target directory
Package Squad.Agents.AI not foundPackage not yet published; using local buildPack locally: dotnet pack src/Squad.Agents.AI/ -c Release -o nupkgs and add --source ./nupkgs

References

ResourceLink
MS Learn — GitHub Copilot agent providerlearn.microsoft.com/en-us/agent-framework/agents/providers/github-copilot
GitHub Docs — MAF integrationdocs.github.com/en/copilot/how-tos/copilot-sdk/integrations/microsoft-agent-framework
Tamir Dresher — “Deterministic meets Squads”tamirdresher.com/blog/2026/05/21/deterministic-meets-squads
10-minute tutorial gist (Tamir Dresher)gist.github.com/tamirdresher/d0e38cbadd962de18e8373706eccad97
Squad + MAF demo repogithub.com/tamirdresher/squad-agent-framework-demo
Microsoft devblogs postdevblogs.microsoft.com/agent-framework/building-agent-teams-with-agent-framework-github-copilot-cli-and-squad/
Squad.Agents.AI package sourcesrc/Squad.Agents.AI/
microsoft/agent-framework#6457Upstream buildTransitive fix (merged 2026-06-10; not yet in NuGet preview)

Credit: The integration pattern and companion demo were co-authored with Tamir Dresher. The tutorial gist and blog post are the original source of record for this guide.