Add autonomous Teams .NET sample synchronization - #726
Joel Mut (sw-joelmut) wants to merge 5 commits into
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved critical and moderate findings remain in validation, manifests, sample behavior, queue handling, and migration guidance.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds an autonomous workflow to synchronize seven Teams SDK .NET samples into Agents SDK samples, with Copilot-driven migration, validation, state tracking, manifests, and contract tests.
Changes:
- Added bounded plan, migrate, and publish workflow jobs.
- Added migration and manifest skills, validators, reporting, and tests.
- Added seven migrated samples and solution registrations.
Additional findings remain in migration guidance, validation, and sample implementations, including critical and moderate issues.
File summaries
| File | Summary |
|---|---|
samples/dotnet/teams/bot-task-modules/README.md |
Documents task-module usage. Nit (2 votes): prerequisite should reference .NET 10. Moderate (1 vote): remove or implement undocumented permissions. |
samples/dotnet/teams/bot-task-modules/Properties/launchSettings.json |
Adds local launch profile. |
samples/dotnet/teams/bot-task-modules/Program.cs |
Configures the Agents host. |
samples/dotnet/teams/bot-task-modules/pages/CustomForm/index.html |
Provides the custom task-module form. |
samples/dotnet/teams/bot-task-modules/BotTaskModules.csproj |
Defines project dependencies. |
samples/dotnet/teams/bot-task-modules/assets/sample.json |
Adds sample catalog metadata. |
samples/dotnet/teams/bot-task-modules/appsettings.json |
Adds runtime configuration. |
samples/dotnet/teams/bot-task-modules/appManifest/manifest.json |
Adds the Teams app manifest. Moderate (1 vote): align permission declarations with the README and behavior. |
samples/dotnet/teams/bot-message-extensions/README.md |
Documents message-extension usage. Nit (2 votes): prerequisite should reference .NET 10. |
samples/dotnet/teams/bot-message-extensions/Properties/launchSettings.json |
Adds local launch profile. |
samples/dotnet/teams/bot-message-extensions/Program.cs |
Configures the Agents host. |
samples/dotnet/teams/bot-message-extensions/BotMessageExtensionsAgent.cs |
Implements search and link-unfurling handlers. |
samples/dotnet/teams/bot-message-extensions/BotMessageExtensions.csproj |
Defines project dependencies. |
samples/dotnet/teams/bot-message-extensions/assets/sample.json |
Adds sample catalog metadata. |
samples/dotnet/teams/bot-message-extensions/appsettings.json |
Adds runtime configuration. |
samples/dotnet/teams/bot-message-extensions/appPackage/manifest.json |
Adds the messaging-extension manifest. Moderate (1 vote): narrow the link-handler domain and use the approved 1.22 schema baseline. |
samples/dotnet/teams/bot-meetings/README.md |
Documents meeting events and Graph setup. Nit (2 votes): prerequisite should reference .NET 10. |
samples/dotnet/teams/bot-meetings/Properties/launchSettings.json |
Adds local launch profile. |
samples/dotnet/teams/bot-meetings/Program.cs |
Configures the Agents host. |
samples/dotnet/teams/bot-meetings/BotMeetings.csproj |
Defines project dependencies. |
samples/dotnet/teams/bot-meetings/assets/sample.json |
Adds sample catalog metadata. |
samples/dotnet/teams/bot-meetings/appsettings.json |
Adds bot and Graph configuration. |
samples/dotnet/teams/bot-meetings/appManifest/manifest.json |
Adds the Teams app manifest. Moderate (1 vote): include the documented personal scope. |
samples/dotnet/teams/bot-cards/README.md |
Documents card behaviors. Nit (2 votes): prerequisite should reference .NET 10. |
samples/dotnet/teams/bot-cards/Properties/launchSettings.json |
Adds local launch profile. |
samples/dotnet/teams/bot-cards/Program.cs |
Configures the Agents host. |
samples/dotnet/teams/bot-cards/Cards/Cards.cs |
Builds adaptive cards. |
samples/dotnet/teams/bot-cards/BotCardsAgent.cs |
Implements card routes. |
samples/dotnet/teams/bot-cards/BotCards.csproj |
Defines project dependencies. |
samples/dotnet/teams/bot-cards/assets/sample.json |
Adds sample catalog metadata. |
samples/dotnet/teams/bot-cards/appsettings.json |
Adds runtime configuration. |
samples/dotnet/teams/bot-cards/appManifest/manifest.json |
Adds the Teams app manifest. |
samples/dotnet/teams/bot-attachments/Services/PendingUploadStore.cs |
Stores pending uploads. Moderate (1 vote): serialize capacity check and insertion. |
samples/dotnet/teams/bot-attachments/Services/FileUploadQueue.cs |
Processes background uploads. |
samples/dotnet/teams/bot-attachments/README.md |
Documents the file-consent flow. Nit (2 votes): prerequisite should reference .NET 10. |
samples/dotnet/teams/bot-attachments/Properties/launchSettings.json |
Adds local launch profile. |
samples/dotnet/teams/bot-attachments/Program.cs |
Configures services and host. |
samples/dotnet/teams/bot-attachments/Models/FileDownloadInfo.cs |
Models download metadata. |
samples/dotnet/teams/bot-attachments/BotAttachments.csproj |
Defines project dependencies. |
samples/dotnet/teams/bot-attachments/assets/sample.json |
Adds sample catalog metadata. |
samples/dotnet/teams/bot-attachments/appsettings.json |
Adds runtime configuration. |
samples/dotnet/teams/bot-attachments/appManifest/manifest.json |
Adds the Teams app manifest. |
samples/dotnet/teams/bot-ai-messages/README.md |
Documents AI message features. Nit (2 votes): prerequisite should reference .NET 10. |
samples/dotnet/teams/bot-ai-messages/Properties/launchSettings.json |
Adds local launch profile. |
samples/dotnet/teams/bot-ai-messages/Program.cs |
Configures the Agents host. |
samples/dotnet/teams/bot-ai-messages/BotAiMessagesAgent.cs |
Implements AI message routes. |
samples/dotnet/teams/bot-ai-messages/BotAiMessages.csproj |
Defines project dependencies. |
samples/dotnet/teams/bot-ai-messages/assets/sample.json |
Adds sample catalog metadata. |
samples/dotnet/teams/bot-ai-messages/appsettings.json |
Adds runtime configuration. |
samples/dotnet/teams/bot-ai-messages/appManifest/manifest.json |
Adds the Teams app manifest. |
samples/dotnet/teams/agent-targeted-messages/ReminderService.cs |
Schedules proactive reminders. |
samples/dotnet/teams/agent-targeted-messages/README.md |
Documents targeted messaging. Nit (2 votes): prerequisite should reference .NET 10. |
samples/dotnet/teams/agent-targeted-messages/Properties/launchSettings.json |
Adds local launch profile. |
samples/dotnet/teams/agent-targeted-messages/Program.cs |
Configures services and host. |
samples/dotnet/teams/agent-targeted-messages/assets/sample.json |
Adds sample catalog metadata. |
samples/dotnet/teams/agent-targeted-messages/appsettings.json |
Adds runtime configuration. |
samples/dotnet/teams/agent-targeted-messages/appManifest/manifest.json |
Adds the targeted-message manifest. Critical (2 votes): split command entries so trigger surfaces match the README. |
samples/dotnet/teams/agent-targeted-messages/AgentTargetedMessages.csproj |
Defines project dependencies. |
samples/dotnet/Samples.sln |
Registers migrated projects and contract tests. |
package.json |
Pins the root lint dependency. |
automation/teams-sample-sync/tsconfig.json |
Configures TypeScript checking. |
automation/teams-sample-sync/tsconfig.build.json |
Configures TypeScript builds. |
automation/teams-sample-sync/tests/unit/workflow-config.test.ts |
Tests workflow configuration. |
automation/teams-sample-sync/tests/unit/validation-path.test.ts |
Tests validation behavior. |
automation/teams-sample-sync/tests/unit/report.test.ts |
Tests reporting output. |
automation/teams-sample-sync/tests/unit/agent-runner.test.ts |
Tests Copilot session controls. |
automation/teams-sample-sync/tests/integration/sdk-smoke.test.ts |
Adds opt-in SDK smoke coverage. |
automation/teams-sample-sync/tests/contracts/TeamsSampleSync.ContractTests.csproj |
Defines the contract-test project. |
automation/teams-sample-sync/tests/contracts/TeamsSampleContracts.cs |
Tests card and AI contracts. |
automation/teams-sample-sync/tests/contracts/TaskModuleContracts.cs |
Tests task modules. |
automation/teams-sample-sync/tests/contracts/TargetedMessageContracts.cs |
Tests targeted messages. |
automation/teams-sample-sync/tests/contracts/MessageExtensionContracts.cs |
Tests message extensions. |
automation/teams-sample-sync/tests/contracts/MeetingContracts.cs |
Tests meeting behavior. |
automation/teams-sample-sync/tests/contracts/AttachmentContracts.cs |
Tests file-consent behavior. |
automation/teams-sample-sync/src/types.ts |
Defines synchronization contracts. |
automation/teams-sample-sync/src/sync-session.ts |
Implements frozen-plan sessions. |
automation/teams-sample-sync/src/state.ts |
Manages verified state. |
automation/teams-sample-sync/src/report.ts |
Generates workflow reports. |
automation/teams-sample-sync/src/plan.ts |
Creates migration plans. |
automation/teams-sample-sync/src/guard.ts |
Enforces repository confinement. |
automation/teams-sample-sync/src/git.ts |
Provides Git and digest utilities. |
automation/teams-sample-sync/src/context.ts |
Creates immutable source context. |
automation/teams-sample-sync/src/config.ts |
Loads synchronization policy. |
automation/teams-sample-sync/src/agent-tools.ts |
Defines trusted validation tools. |
automation/teams-sample-sync/src/agent-runner.ts |
Runs Copilot sessions. |
automation/teams-sample-sync/skills/sync-teams-dotnet-samples-to-agents-sdk/SKILL.md |
Adds synchronization guidance. |
automation/teams-sample-sync/README.md |
Documents local workflow usage. |
automation/teams-sample-sync/prompts/agent-prompt.md |
Defines the Copilot migration protocol. |
automation/teams-sample-sync/package.json |
Defines automation dependencies and scripts. |
automation/teams-sample-sync/config/targets.yml |
Configures selected samples. |
automation/teams-sample-sync/config/ownership.yml |
Defines protected paths. |
agent-plugins/agents-sdk-common/skills/teams-app-manifest/references/source-detection.md |
Documents capability detection. |
agent-plugins/agents-sdk-common/skills/teams-app-manifest/references/schema-validation.md |
Documents manifest validation. |
agent-plugins/agents-sdk-common/skills/teams-app-manifest/references/message-extensions.md |
Documents message extensions. |
agent-plugins/agents-sdk-common/skills/teams-app-manifest/references/meetings.md |
Documents meeting manifests. |
agent-plugins/agents-sdk-common/skills/teams-app-manifest/references/cards-and-dialogs.md |
Documents cards and dialogs. |
agent-plugins/agents-sdk-common/skills/teams-app-manifest/references/capability-ledger.md |
Defines capability evidence rules. |
agent-plugins/agents-sdk-common/skills/teams-app-manifest/references/bots.md |
Documents bot capabilities. |
agent-plugins/agents-sdk-common/skills/teams-app-manifest/references/authentication-and-permissions.md |
Documents permissions and domains. |
agent-plugins/agents-sdk-common/skills/teams-app-manifest/assets/manifest-evidence.template.md |
Adds the evidence template. |
agent-plugins/agents-sdk-common/skills/teams-app-manifest/assets/base-manifest.template.json |
Adds the manifest template. |
agent-plugins/agents-sdk-common/plugin.json |
Updates the common plugin version. |
agent-plugins/agents-for-net/plugin.json |
Updates the .NET plugin version. |
.gitignore |
Ignores synchronization artifacts. |
.github/workflows/sync-teams-dotnet-samples.yml |
Adds the synchronization workflow. |
.claude-plugin/marketplace.json |
Updates marketplace versions. |
Review details
Files not reviewed (1)
- automation/teams-sample-sync/package-lock.json: Generated file
Suppressed comments (10)
agent-plugins/agents-for-net/skills/teams-sdk-to-agents-sdk-dotnet-migration/SKILL.md:79
- The migration skill also requires
net8.0, but this synchronization policy validatesnet10.0and all seven migrated projects target it. An autonomous migration following this instruction will produce a candidate that fails the deterministic project check; make the framework rule use the configured policy.
**TargetFramework:** the Agents SDK targets `net8.0`. Set `<TargetFramework>net8.0</TargetFramework>`
(Teams SDK samples often target `net10.0`). Set `<ImplicitUsings>disable</ImplicitUsings>` and add
explicit `using` directives (matches Agents SDK sample convention).
agent-plugins/agents-for-net/skills/teams-sdk-to-agents-sdk-dotnet-migration/SKILL.md:38
- This newly added migration skill tells the agent to emit Agents SDK
1.7.*, while the synchronization policy and every migrated project require1.8.*. That contradiction can make the agent generate projects the validator rejects; align the skill with the configured1.8.*policy.
- **Use the latest release Agents SDK packages** The
base packages (`Microsoft.Agents.Hosting.AspNetCore`, `Microsoft.Agents.Authentication.Msal`, `Microsoft.Agents.Extensions.MSTeams`, and the
transitive `Microsoft.Agents.Core` / `Builder` / `Connector` / `Storage`) are on the **`1.7.x`** line —
use the repository's current shared version convention, currently `1.7.*` but use the latest non-beta version.
samples/dotnet/teams/agent-targeted-messages/AgentTargetedMessagesAgent.cs:520
- The
elseat line 523 binds only to this hour check, so valid seconds and minutes units fall through toreturn null. This rejects the documented30 seconds/minute reminders; use anelse ifchain or a separate unsupported-unit check so all three unit groups produce a multiplier.
samples/dotnet/teams/bot-attachments/BotAttachmentsAgent.cs:129 - When the bounded upload queue is full, the file has already been removed from the incoming turn but its bytes remain in
PendingUploadStore; no later path removes them. Repeated queue-full responses can therefore consume the 32-entry pending capacity for 10 minutes without any upload or user notification. Remove the pending item whenTryQueuefails (and report the rejection to the user).
samples/dotnet/teams/bot-attachments/Services/PendingUploadStore.cs:22 - The capacity check and insert are separate operations, so concurrent attachment requests can all observe a count below 32 and then exceed the configured capacity. Serialize the check-and-add (or reserve a slot atomically) before storing the bytes.
samples/dotnet/teams/bot-meetings/appManifest/manifest.json:9 - The README's meeting manifest example includes
personal, but this committed manifest only declaresteamandgroupChat. Users following the documented personal/team/group-chat setup cannot install this bot for personal scope; keep the manifest scopes aligned with the documented behavior.
samples/dotnet/teams/bot-message-extensions/appPackage/manifest.json:67 - The link handler accepts every
*.wikipedia.orgsubdomain, while the sample generates links only toen.wikipedia.org. This unnecessarily broadens link-unfurling coverage and conflicts with the manifest guidance to use controlled, narrowly scoped domains; use the exact host unless other subdomains are intentionally supported.
samples/dotnet/teams/bot-message-extensions/appPackage/manifest.json:3 - The new manifest skill establishes
1.22as the repository baseline for new Teams agent samples, and all other manifests in this PR use it. This sample instead pins1.19; use the approved baseline unless a documented capability requires the older schema.
samples/dotnet/teams/bot-task-modules/README.md:63 - The setup instructions require
identityandmessageTeamMembers, but this manifest does not declare them and the sample only replies to the current task-module conversation; those permissions are not needed for this behavior. Users following the README will grant unnecessary permissions and still receive a package that does not contain them. Remove the two permissions from the instructions or add a concrete feature that requires them and declare them in the manifest.
samples/dotnet/teams/bot-task-modules/appManifest/manifest.json:9 - The README instructs users that this app needs the root
identityandmessageTeamMemberspermissions, but the package manifest declares neither. An uploaded package therefore does not carry the permissions required by its own setup instructions; add the declarations or remove the requirement after confirming the behavior does not need them.
- Files reviewed: 122/149 changed files
- Comments generated: 10
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
🟡 Changes recommended
The synchronization boundary can be bypassed by executed candidate code, and several manifest and reliability defects remain.
Get a fresh assessment by requesting another Copilot review.
Review details
Files not reviewed (1)
- automation/teams-sample-sync/package-lock.json: Generated file
Suppressed comments (5)
Previously missed (5) — in code that hasn't changed since the last review.
automation/teams-sample-sync/src/plan.ts:87
- The weekly inventory reports every unconfigured upstream directory as a new candidate, so
bot-quickstartwill be surfaced on every periodic run even though it is explicitly excluded from periodic migration. Apply the default skip list before constructingnewSampleCandidatesand cover that exclusion in the planner tests.
automation/teams-sample-sync/src/sync-session.ts:60 - When the deadline expires during
options.validate(), only the Copilot session is aborted. The spawned build/test process remains inactiveProcessesuntil its own timeout, so the advertised per-sample deadline can be exceeded by up to another ten minutes. Invoke the existing validation-process cancellation path when this timer fires.
samples/dotnet/teams/agent-targeted-messages/ReminderService.cs:78 - The reminder is removed before delivery, and the exception path only logs. Any transient proactive-send failure therefore permanently loses the reminder while the user still expects it to fire. Keep the item until delivery succeeds, or requeue it with a bounded retry/backoff policy on transient failures.
samples/dotnet/teams/agent-targeted-messages/appManifest/manifest.json:59 - The sample does not retrieve or use Teams member profile fields such as UPN, email, or Entra object ID; it only routes with opaque account IDs. Declaring
identitytherefore requests a root Teams permission that this implementation does not need. Remove it and retain only the separately justified member-messaging permission.
samples/dotnet/teams/bot-attachments/Services/FileUploadQueue.cs:74 - A zero-byte attachment reaches this path with
Length == 0, making the range end-1;ContentRangeHeaderValuerejects that value before the PUT, so empty files can never be uploaded. Handle zero-length content explicitly (for example, use the service's supported empty-file upload shape or reject it before consent with a clear response).
- Files reviewed: 122/149 changed files
- Comments generated: 2
- Review effort level: Balanced
Fixes #691
Note
The workflow uses Copilot Auto with the known-working Copilot SDK 1.0.7 and CLI runtime 1.0.83.
Note
Copilot SDK Auto tier routing (
balance) requires SDK v1.0.13+ andmodel: "auto". This sample currently uses a turn-scoped, per-user GitHub OAuth token (GitHubToken), while Auto-tier configuration is not supported with that static-token session setup. Enabling it would require a separate token-provider design that can safely refresh each user’s OAuth credential outside the originating Teams turn. We are intentionally not making that authentication change in this PR.Description
Add an autonomous workflow that synchronizes selected Microsoft Teams SDK .NET samples with their Agents SDK counterparts.
The workflow creates a frozen migration plan, implements it through one persistent Copilot session, validates the result, and publishes only a verified patch. It limits Copilot write access to the selected sample and keeps repository credentials out of the migration job.
This PR also adds seven migrated Teams samples, reusable migration and manifest skills, deterministic validators, contract tests, and incremental synchronization state.
Changes
GitHub Actions workflow
plan,migrate, andpublishjobs.Autonomous migration
balanceauto tier.Migration and manifest skills
Validation and reporting
Migrated samples
agent-targeted-messages.bot-ai-messages.bot-attachments.bot-cards.bot-meetings.bot-message-extensions.bot-task-modules.Testing
npm test --prefix automation/teams-sample-sync.npm run build --prefix automation/teams-sample-sync.The following image shows the workflow working.
