Skip to content

feat: Squad.Agents.AI - Microsoft Agent Framework adapter for the Squad CLI#1207

Open
tamirdresher wants to merge 19 commits into
bradygaster:devfrom
tamirdresher:feature/squad-agents-ai
Open

feat: Squad.Agents.AI - Microsoft Agent Framework adapter for the Squad CLI#1207
tamirdresher wants to merge 19 commits into
bradygaster:devfrom
tamirdresher:feature/squad-agents-ai

Conversation

@tamirdresher

Copy link
Copy Markdown
Collaborator

Closes #1205


What

This PR adds Squad.Agents.AI, a community .NET package that exposes a Squad agent team as a Microsoft Agent Framework AIAgent. Applications using the Microsoft Agents library can now integrate Squad's capabilities via standard RunAsync and RunStreamingAsync patterns.

Why

Teams adopting the Microsoft Agent Framework need a way to invoke Squad agent teams directly from their AIAgent workloads. This package provides a thin, secure integration layer that composes the Squad CLI through the GitHub Copilot SDK, allowing DI-based registration and streaming support without reimplementing Squad's agent orchestration.

How

Public API surface:

  • services.AddSquadAgent(options => ...) — Single agent registration via DI
  • services.AddKeyedSquadAgent("name", options => ...) — Keyed services for multiple agents (.NET 8+)
  • options.ConfigureCopilotClient = client => ... — Bring-your-own-client delegate for custom Copilot SDK configuration
  • agent.RunAsync(thread, options, ct) — Synchronous invocation returning structured response
  • agent.RunStreamingAsync(thread, options, ct) — Token-by-token streaming

Security posture:

  • Authentication flows through the Squad CLI process; no tokens stored in-package
  • Environment option redacted in ToString() to prevent credential leaks in logs
  • Routing-affecting options (Cwd, CliPath, CliArgs) are snapshotted before and restored after any ConfigureCopilotClient delegate to prevent SDK customizers from pivoting the agent to a different CLI binary; deviations are logged as warnings

Testing:

  • 43 tests (all passing) across net8.0, net9.0, and net10.0
  • CI runs on ubuntu-latest and windows-latest to verify cross-platform compatibility

Sample application:
The repository includes a runnable .NET console app demonstrating all four core patterns:

  1. Basic DI: AddSquadAgent + RunAsync
  2. Keyed DI: Multiple agents via AddKeyedSquadAgent with GetRequiredKeyedService<AIAgent>
  3. Bring-Your-Own-Client (BYOK): ConfigureCopilotClient delegate for token injection and environment customization
  4. Streaming: RunStreamingAsync for token-by-token output

Run the sample:

dotnet run --project src/Squad.Agents.AI/samples/Squad.Agents.AI.Sample/

To execute a specific flow:

dotnet run --project src/Squad.Agents.AI/samples/Squad.Agents.AI.Sample/ -- --flow=1

Documentation:
README at src/Squad.Agents.AI/README.md covers:

  • Installation via dotnet add package Squad.Agents.AI --prerelease
  • All four DI registration shapes
  • BYOK and streaming usage
  • Security design rationale
  • Complete sample walkthrough with location at src/Squad.Agents.AI/samples/Squad.Agents.AI.Sample/

Breaking changes: None.


Quick Check

  • Squad.Agents.AI is a new .NET package (not part of bradygaster/squad). No changeset required.
  • All tests passing: dotnet test test/Squad.Agents.AI.Tests/ -c Release — 43/43 green
  • Build verified: dotnet build src/Squad.Agents.AI/Squad.Agents.AI.csproj -c Release
  • CI passing on ubuntu-latest and windows-latest
  • Sample runs cleanly with helpful error messaging (Copilot CLI not found scenario)
  • No user-visible breaking changes
  • Documentation (README) updated with ## Sample section

PR Readiness Checklist

  • Branch up to date with target remote
  • Build: dotnet build passes
  • Tests: dotnet test passes (43/43 green)
  • Type check: no errors
  • No merge conflicts
  • Commit history clean
  • Documentation updated
  • No unintended file changes
  • Sample co-located in src/Squad.Agents.AI/samples/Squad.Agents.AI.Sample/
  • README stub at sample location for discoverability
  • Cross-platform compatibility verified
  • Security review complete (no token leaks, routing snapshot isolation)
  • External contributor best practices applied
  • N/A — Changeset (this is a new .NET package, not npm monorepo)

Copilot AI review requested due to automatic review settings June 2, 2026 18:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new src/Squad.Agents.AI .NET package that wraps the Squad CLI (via GitHub Copilot SDK) as a Microsoft Agent Framework AIAgent, plus tests, a runnable sample, and CI/release automation for publishing to NuGet.

Changes:

  • Introduces SquadAgent + DI registration extensions (including keyed DI) and connection-string parsing/binding.
  • Adds a comprehensive test suite and a console sample demonstrating basic DI, keyed DI, BYOK (ConfigureCopilotClient), and streaming.
  • Adds GitHub Actions workflows for CI and NuGet publishing, plus Dependabot config for NuGet/GitHub Actions updates.

Reviewed changes

Copilot reviewed 22 out of 23 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
src/Squad.Agents.AI/SquadAgent.cs AIAgent wrapper over Copilot SDK + BYOK routing guard + streaming delegation.
src/Squad.Agents.AI/SquadAgentOptions.cs Options model with redaction + JSON ignore for sensitive fields.
src/Squad.Agents.AI/SquadAgentOptionsConfigurator.cs Binds/merges options from ConnectionStrings:* before user configuration.
src/Squad.Agents.AI/SquadConnectionFactory.cs Parses PATH/URI connection strings into SquadAgentOptions.
src/Squad.Agents.AI/SquadServiceCollectionExtensions.cs DI registration APIs (scoped/lifetime overloads + keyed DI).
src/Squad.Agents.AI/Squad.Agents.AI.csproj NuGet packaging metadata + dependencies for the new library.
src/Squad.Agents.AI/README.md Package documentation (usage, DI shapes, BYOK, streaming, sample instructions).
src/Squad.Agents.AI/samples/Squad.Agents.AI.Sample/Program.cs Sample app demonstrating 4 integration flows + error handling.
src/Squad.Agents.AI/samples/Squad.Agents.AI.Sample/Squad.Agents.AI.Sample.csproj Sample project definition and dependencies.
src/Squad.Agents.AI/samples/Squad.Agents.AI.Sample/README.md Pointer README for sample discoverability.
test/Squad.Agents.AI.Tests/SquadServiceCollectionExtensionsTests.cs Tests DI registration + config/connection-string binding behavior.
test/Squad.Agents.AI.Tests/SquadKeyedDITests.cs Tests keyed DI registration/resolution semantics.
test/Squad.Agents.AI.Tests/SquadConnectionFactoryTests.cs Tests connection-string parsing for PATH/URI forms.
test/Squad.Agents.AI.Tests/SquadBYOKTests.cs Tests ConfigureCopilotClient behavior + routing guard expectations.
test/Squad.Agents.AI.Tests/SquadAgentRoutingTests.cs Tests agent naming/instructions and routing through Copilot options.
test/Squad.Agents.AI.Tests/SquadAgentOptionsSecurityTests.cs Tests redaction/JSON serialization behavior for sensitive fields.
test/Squad.Agents.AI.Tests/Squad.Agents.AI.Tests.csproj Test project configuration and dependencies.
.github/workflows/squad-agents-ai-ci.yml CI build/test/pack on Ubuntu + Windows for the new package.
.github/workflows/squad-agents-ai-release.yml Branch-driven NuGet publish workflow (dev prerelease, main stable).
.github/dependabot.yml Enables Dependabot updates for NuGet and GitHub Actions for this package.
README.md Adds a top-level callout to the new .NET package docs.
CHANGELOG.md Adds an entry describing the new Squad.Agents.AI preview.
.gitignore Ignores common .NET build artifacts (bin/, obj/, artifacts/).

Comment on lines +134 to +138
// Snapshot routing properties before the delegate runs
var snapshotCwd = clientOptions.Cwd;
var snapshotCliPath = clientOptions.CliPath;
var snapshotCliArgs = clientOptions.CliArgs;

Comment thread src/Squad.Agents.AI/SquadAgent.cs Outdated
Comment on lines +163 to +170
if (!ReferenceEquals(clientOptions.CliArgs, snapshotCliArgs))
{
logger?.LogWarning(
"ConfigureCopilotClient delegate replaced CliArgs; " +
"restoring original value to preserve Squad routing.");
clientOptions.CliArgs = snapshotCliArgs;
restored = true;
}
Comment on lines +39 to +43
public static IServiceCollection AddSquadAgent(
this IServiceCollection services,
string name,
Action<SquadAgentOptions>? configure = null)
=> AddSquadAgentCore(services, name, ServiceLifetime.Scoped, configure);
Comment on lines +66 to +71
public static IServiceCollection AddSquadAgent(
this IServiceCollection services,
string name,
ServiceLifetime lifetime,
Action<SquadAgentOptions>? configure = null)
=> AddSquadAgentCore(services, name, lifetime, configure);
Comment on lines +107 to +112
public static IServiceCollection AddKeyedSquadAgent(
this IServiceCollection services,
string serviceKey,
string name,
Action<SquadAgentOptions>? configure = null)
=> AddKeyedSquadAgentCore(services, serviceKey, name, ServiceLifetime.Scoped, configure);
Comment thread CHANGELOG.md Outdated
Comment on lines +10 to +13
- Added `Squad.Agents.AI`, a `net10.0` Microsoft Agent Framework package that exposes a Squad team as an `AIAgent`.
- Public surface: `SquadAgent`, `SquadAgentOptions`, `SquadConnectionFactory`, and `SquadServiceCollectionExtensions`.
- Added DI registration, PATH/URI connection-string parsing, GitHub token/provider options, and XML documentation for the public preview surface.
- Documented PR #3 lineage for the v0.1-preview package in `src/Squad.Agents.AI/README.md`.
Comment on lines +196 to +200
| [.NET 10 SDK](https://dotnet.microsoft.com/download/dotnet/10.0) | `dotnet --version` should print `10.x.x` |
| GitHub Copilot CLI on `PATH` | Install from [github.com/github/copilot-cli](https://github.com/github/copilot-cli); verify with `copilot --version` |
| Squad CLI installed | Follow the install guide in the [Squad repository README](https://github.com/tamirdresher/squad#readme) |
| Initialized Squad team root | Run `squad init` in a directory; this becomes your team root |
| GitHub Copilot authentication | Run `gh auth login` or `copilot auth login` once before running the sample |
Comment on lines +12 to +15
<PackageTags>squad;agents;ai;copilot;maf;multi-agent</PackageTags>
<PackageProjectUrl>https://github.com/tamirdresher/squad</PackageProjectUrl>
<RepositoryUrl>https://github.com/tamirdresher/squad.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
Comment on lines +147 to +150
// Simulate a token from a credential store (never hardcode real tokens).
// In production replace this with Key Vault, managed identity, etc.
const string simulatedToken = "ghp_EXAMPLE_REPLACE_WITH_REAL_TOKEN";

Comment on lines +2 to +4
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
Reno (Copilot) and others added 18 commits June 2, 2026 22:21
Squad CLI as Microsoft.Extensions.AI IChatClient, composing
GitHub.Copilot.SDK via AsAIAgent() from Microsoft.Agents.AI.GitHub.Copilot 1.7.0-preview.

Closes Track A of the Q1-Q7 design lock (see tamresearch1 .squad/decisions.md
Decisions 441, 443, 444, 447).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- SquadAgent now properly inherits from Microsoft.Agents.AI.AIAgent
- Removed (IChatClient)(object)agent force-cast
- Overrides all AIAgent abstract members (CreateSessionCoreAsync, RunCoreAsync, etc.)
- DI registration now registers AIAgent (not IChatClient)
- README updated to use AIAgent.RunAsync API
- No more abstraction inversion; AIAgent is the correct layer

Fixes the architectural error identified by Tamir.
…eshooting, preview callout

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds async token provider pattern for production scenarios (KeyVault/MSI integration).

- GitHubTokenProvider property takes precedence over GitHubToken
- GitHubToken marked [JsonIgnore] to prevent serialization leaks
- SquadAgentOptions.ToString() redacts GitHubToken field
- Updated CreateCopilotClient to resolve token from provider first

Mitigates P0 #3: token leakage via ILogger structured-log calls, IOptions snapshots, and serializers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…n token management

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…+ add smoke tests

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
WithTeamRoot was deleted in commit 35767c90 in favor of mandatory positional
teamRoot constructor argument on AddSquad. The Aspire example in the
Squad.Agents.AI README still showed the old fluent API, which would now
fail at compile time for anyone copy-pasting.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Closes the routing-verification gap identified during
squad-squad onboarding: the API surface existed but
routing semantics weren't functionally tested. New tests
verify persona pass-through, boundary-instruction injection
on first turn, WorkingDirectory isolation (Decision 452a),
and CopilotClientOptions-based routing (Decision 447).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
PR #3 CI was Node/docs-only — adding the .NET gate so green
actually reflects the package code. Matrix on ubuntu + windows,
restore/build/test/pack, uploads TestResults and nupkg artifacts.

Closes the build-verification gap identified during squad-squad
onboarding (see .squad/decisions.md adoption record, 2026-06-02).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- .github/workflows/squad-agents-ai-release.yml: workflow_dispatch
  and tag-driven publish to nuget.org with --skip-duplicate idempotency,
  fail-fast on missing NUGET_API_KEY secret, optional GitHub Release on tag
- .github/dependabot.yml: nuget (src + test) + github-actions, weekly,
  M.A.AI major allowed, OpenTelemetry major deferred (per Decision 602)

Closes the release-pipeline + supply-chain-tracking gaps identified
during squad-squad onboarding.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- README updates / XML docs on public surface
- CHANGELOG.md with [0.1.0-preview] - 2026-06-02 entry
- .csproj: Description, RepositoryUrl, Authors, PackageTags, PackageReadmeFile
- Verified via dotnet pack — .nupkg contains README, LICENSE, xml-docs

Closes the docs-readiness gap for v0.1-preview publish.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Per Tamir's release-strategy directive (decisions.md 2026-06-02):
- dev merges  → prerelease publish (suffix scheme mirrors Squad CLI)
- main merges → stable publish
- workflow_dispatch retained as manual escape hatch
- tag-driven trigger removed (branches are the source of truth)

Version derivation pattern adapted from the Squad CLI's existing
release workflow. --skip-duplicate retained for idempotent reruns.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… connections

- Rewrite the package README and PR validation flow around the AIAgent surface and ambient Copilot authentication.
- Keep public docs free of internal process references and remove obsolete deferral language.
- Preserve connection-string cliArgs through CopilotClientOptions and cover the behavior with a routing test.
- Add named connection-string lookup via AddSquadAgent("name") using ConnectionStrings:squad-{name}.
- Document the new public overloads and verify the package builds without warnings.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ning

- Add ConfigureCopilotClient delegate on SquadAgentOptions for BYOK
- Add routing gate: snapshot/restore Cwd/CliPath/CliArgs after delegate (Picard C1)
- Add 4 AddKeyedSquadAgent overloads with .NET 8+ keyed DI
- Fix Environment credential leak: [JsonIgnore] on Environment, GitHubTokenProvider, ConfigureCopilotClient
- ToString() redacts token-pattern keys (TOKEN/KEY/SECRET/HMAC/PASSWORD/CREDENTIAL)
- Add 21 new tests (43 total): security redaction, keyed DI, BYOK routing gate
- Update README: streaming, keyed DI, BYOK, security sections

Complies with: Picard C1-C4, Worf SC-1 through SC-8.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…, and streaming

- samples/squad-agents-ai-sample/Program.cs: four runnable flows
  Flow 1 -- AddSquadAgent + RunAsync (basic DI)
  Flow 2 -- AddKeyedSquadAgent x2 + GetRequiredKeyedService<SquadAgent>
  Flow 3 -- ConfigureCopilotClient delegate (BYOK token + env var injection)
  Flow 4 -- RunStreamingAsync with await foreach token-by-token output
- samples/squad-agents-ai-sample/Squad.Agents.AI.Sample.csproj: net10.0,
  project reference to src/Squad.Agents.AI, Microsoft.Extensions.Hosting 10.0.0
- samples/squad-agents-ai-sample/README.md: prerequisites, run commands,
  per-flow walkthrough, troubleshooting table
- .github/workflows/squad-agents-ai-ci.yml: adds paths trigger and
  restore + build steps for the sample (no run step -- requires live CLI)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…e README

- Moves the sample app from samples/squad-agents-ai-sample/ to
  src/Squad.Agents.AI/samples/Squad.Agents.AI.Sample/ so it lives
  alongside the package it demonstrates.
- Folds the sample's standalone README into the package README, giving
  consumers one canonical doc for both the API and the runnable demo.
- Adds <Compile Remove="samples/**/*.cs" /> to Squad.Agents.AI.csproj
  so the library's wildcard glob does not pick up Program.cs in the
  co-located samples subdirectory.
- Updates the .csproj project reference, and CI workflow paths to match
  the new layout.
- Verified end-to-end: dotnet build, dotnet test (43/43 passing), and a
  sample sanity-check run (clear CLI-not-found error, no stack trace).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The standalone pr-body.md was an early draft authored before the live PR description took its final shape. The PR body on GitHub is the canonical source; this file is dead weight and would confuse maintainers reviewing the diff.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…12 items)

- Snapshot CliArgs by value, not reference, so in-place mutation by SDK consumers
  is also caught by the routing guard.
- Validate name/connectionName/serviceKey is non-empty in all DI registration
  overloads; previously null/whitespace produced invalid connection-string keys.
- Replace ghp_-prefixed placeholder in the sample with a clearly-fake token to
  avoid tripping secret-scanning and to remove a real-token lookalike.
- Remove brittle 'PR #3' references from README and CHANGELOG; describe the
  feature without tying to a specific PR thread.
- Update NuGet metadata and README links to point to bradygaster/squad (canonical
  repo) instead of the tamirdresher fork.
- Multi-target the test project to match the package's target framework set so
  CI exercises every framework the package ships against.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
/// </code>
/// </example>
/// </remarks>
public sealed class SquadAgent : AIAgent, IAsyncDisposable

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/// </summary>
/// <param name="options">Options that describe the Squad team root, CLI process, authentication, logging, and instructions.</param>
/// <param name="loggerFactory">Optional logger factory used for wrapper logs and SDK trace logging when enabled.</param>
public SquadAgent(SquadAgentOptions options, ILoggerFactory? loggerFactory = null)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how closely you want to follow MAF, but a pattern we follow is that required settings are on the constructor and optional are in options, with options itself being optional. loggerFactory, while optional, is an exception, since you may typically want it to be injected via DI, so it stays on the constructor, including anything else that similarly may need to be injected via DI.

E.g. (string requiredParam, OptionsClass? options = null, ILoggerFactory? loggerFactory = null)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Community contribution: Squad.Agents.AI - .NET adapter for Microsoft Agent Framework

3 participants