[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6FDC0M2XMJXPQ42294G4M3R":3,"skill-same:01M6FDC0M2XMJXPQ42294G4M3R":53},{"skillNo":4,"name":5,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":22,"publishedAt":26,"linkOnly":27,"markdownContent":28,"markdownBody":28,"frontMatter":29,"refName":30,"commitSha":31,"skillDirectory":32,"forksCount":33,"repositoryHtmlUrl":34,"repositoryHomepageUrl":35,"ownerHtmlUrl":36,"ownerBlogUrl":6,"ownerDescription":37,"updatedAt":38,"install":39,"resources":52},"01M6FDC0M2XMJXPQ42294G4M3R","m365-agents-dotnet",null,"ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",67,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fmicrosoft\u002Fskills\u002Fm365-agents-dotnet\u002FSKILL.md",[17],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[23,24,25],"dotnet","m365 agents dotnet","m365","2026-11-10 10:12:30",false,"# Microsoft 365 Agents SDK (.NET)\n\n## Overview\nBuild enterprise agents for Microsoft 365, Teams, and Copilot Studio using the Microsoft.Agents SDK with ASP.NET Core hosting, agent routing, and MSAL-based authentication.\n\n## Before implementation\n- Use the microsoft-docs MCP to verify the latest APIs for AddAgent, AgentApplication, and authentication options.\n- Confirm package versions in NuGet for the Microsoft.Agents.* packages you plan to use.\n\n## Installation\n\n```bash\ndotnet add package Microsoft.Agents.Hosting.AspNetCore\ndotnet add package Microsoft.Agents.Authentication.Msal\ndotnet add package Microsoft.Agents.Storage\ndotnet add package Microsoft.Agents.CopilotStudio.Client\ndotnet add package Microsoft.Identity.Client.Extensions.Msal\n```\n\n## Configuration (appsettings.json)\n\n```json\n{\n  \"TokenValidation\": {\n    \"Enabled\": true,\n    \"Audiences\": [\n      \"{{ClientId}}\"\n    ],\n    \"TenantId\": \"{{TenantId}}\"\n  },\n  \"AgentApplication\": {\n    \"StartTypingTimer\": false,\n    \"RemoveRecipientMention\": false,\n    \"NormalizeMentions\": false\n  },\n  \"Connections\": {\n    \"ServiceConnection\": {\n      \"Settings\": {\n        \"AuthType\": \"ClientSecret\",\n        \"ClientId\": \"{{ClientId}}\",\n        \"ClientSecret\": \"{{ClientSecret}}\",\n        \"AuthorityEndpoint\": \"https:\u002F\u002Flogin.microsoftonline.com\u002F{{TenantId}}\",\n        \"Scopes\": [\n          \"https:\u002F\u002Fapi.botframework.com\u002F.default\"\n        ]\n      }\n    }\n  },\n  \"ConnectionsMap\": [\n    {\n      \"ServiceUrl\": \"*\",\n      \"Connection\": \"ServiceConnection\"\n    }\n  ],\n  \"CopilotStudioClientSettings\": {\n    \"DirectConnectUrl\": \"\",\n    \"EnvironmentId\": \"\",\n    \"SchemaName\": \"\",\n    \"TenantId\": \"\",\n    \"AppClientId\": \"\",\n    \"AppClientSecret\": \"\"\n  }\n}\n```\n\n## Core Workflow: ASP.NET Core agent host\n\n```csharp\nusing Microsoft.Agents.Builder;\nusing Microsoft.Agents.Hosting.AspNetCore;\nusing Microsoft.Agents.Storage;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nvar builder = WebApplication.CreateBuilder(args);\n\nbuilder.Services.AddHttpClient();\nbuilder.AddAgentApplicationOptions();\nbuilder.AddAgent\u003CMyAgent>();\nbuilder.Services.AddSingleton\u003CIStorage, MemoryStorage>();\n\nbuilder.Services.AddControllers();\nbuilder.Services.AddAgentAspNetAuthentication(builder.Configuration);\n\nWebApplication app = builder.Build();\n\napp.UseAuthentication();\napp.UseAuthorization();\n\napp.MapGet(\"\u002F\", () => \"Microsoft Agents SDK Sample\");\n\nvar incomingRoute = app.MapPost(\"\u002Fapi\u002Fmessages\",\n    async (HttpRequest request, HttpResponse response, IAgentHttpAdapter adapter, IAgent agent, CancellationToken ct) =>\n    {\n        await adapter.ProcessAsync(request, response, agent, ct);\n    });\n\nif (!app.Environment.IsDevelopment())\n{\n    incomingRoute.RequireAuthorization();\n}\nelse\n{\n    app.Urls.Add(\"http:\u002F\u002Flocalhost:3978\");\n}\n\napp.Run();\n```\n\n## AgentApplication routing\n\n```csharp\nusing Microsoft.Agents.Builder;\nusing Microsoft.Agents.Builder.App;\nusing Microsoft.Agents.Builder.State;\nusing Microsoft.Agents.Core.Models;\nusing System;\nusing System.Threading;\nusing System.Threading.Tasks;\n\npublic sealed class MyAgent : AgentApplication\n{\n    public MyAgent(AgentApplicationOptions options) : base(options)\n    {\n        OnConversationUpdate(ConversationUpdateEvents.MembersAdded, WelcomeAsync);\n        OnActivity(ActivityTypes.Message, OnMessageAsync, rank: RouteRank.Last);\n        OnTurnError(OnTurnErrorAsync);\n    }\n\n    private static async Task WelcomeAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken ct)\n    {\n        foreach (ChannelAccount member in turnContext.Activity.MembersAdded)\n        {\n            if (member.Id != turnContext.Activity.Recipient.Id)\n            {\n                await turnContext.SendActivityAsync(\n                    MessageFactory.Text(\"Welcome to the agent.\"),\n                    ct);\n            }\n        }\n    }\n\n    private static async Task OnMessageAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken ct)\n    {\n        await turnContext.SendActivityAsync(\n            MessageFactory.Text($\"You said: {turnContext.Activity.Text}\"),\n            ct);\n    }\n\n    private static async Task OnTurnErrorAsync(\n        ITurnContext turnContext,\n        ITurnState turnState,\n        Exception exception,\n        CancellationToken ct)\n    {\n        await turnState.Conversation.DeleteStateAsync(turnContext, ct);\n\n        var endOfConversation = Activity.CreateEndOfConversationActivity();\n        endOfConversation.Code = EndOfConversationCodes.Error;\n        endOfConversation.Text = exception.Message;\n        await turnContext.SendActivityAsync(endOfConversation, ct);\n    }\n}\n```\n\n## Copilot Studio direct-to-engine client\n\n### DelegatingHandler for token acquisition (interactive flow)\n\n```csharp\nusing System.Net.Http.Headers;\nusing Microsoft.Agents.CopilotStudio.Client;\nusing Microsoft.Identity.Client;\n\ninternal sealed class AddTokenHandler : DelegatingHandler\n{\n    private readonly SampleConnectionSettings _settings;\n\n    public AddTokenHandler(SampleConnectionSettings settings) : base(new HttpClientHandler())\n    {\n        _settings = settings;\n    }\n\n    protected override async Task\u003CHttpResponseMessage> SendAsync(\n        HttpRequestMessage request,\n        CancellationToken cancellationToken)\n    {\n        if (request.Headers.Authorization is null)\n        {\n            string[] scopes = [CopilotClient.ScopeFromSettings(_settings)];\n\n            IPublicClientApplication app = PublicClientApplicationBuilder\n                .Create(_settings.AppClientId)\n                .WithAuthority(AadAuthorityAudience.AzureAdMyOrg)\n                .WithTenantId(_settings.TenantId)\n                .WithRedirectUri(\"http:\u002F\u002Flocalhost\")\n                .Build();\n\n            AuthenticationResult authResponse;\n            try\n            {\n                var account = (await app.GetAccountsAsync()).FirstOrDefault();\n                authResponse = await app.AcquireTokenSilent(scopes, account).ExecuteAsync(cancellationToken);\n            }\n            catch (MsalUiRequiredException)\n            {\n                authResponse = await app.AcquireTokenInteractive(scopes).ExecuteAsync(cancellationToken);\n            }\n\n            request.Headers.Authorization = new AuthenticationHeaderValue(\"Bearer\", authResponse.AccessToken);\n        }\n\n        return await base.SendAsync(request, cancellationToken);\n    }\n}\n```\n\n### Console host with CopilotClient\n\n```csharp\nusing Microsoft.Agents.CopilotStudio.Client;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nHostApplicationBuilder builder = Host.CreateApplicationBuilder(args);\n\nvar settings = new SampleConnectionSettings(\n    builder.Configuration.GetSection(\"CopilotStudioClientSettings\"));\n\nbuilder.Services.AddHttpClient(\"mcs\").ConfigurePrimaryHttpMessageHandler(() =>\n{\n    return new AddTokenHandler(settings);\n});\n\nbuilder.Services\n    .AddSingleton(settings)\n    .AddTransient\u003CCopilotClient>(sp =>\n    {\n        var logger = sp.GetRequiredService\u003CILoggerFactory>().CreateLogger\u003CCopilotClient>();\n        return new CopilotClient(settings, sp.GetRequiredService\u003CIHttpClientFactory>(), logger, \"mcs\");\n    });\n\nIHost host = builder.Build();\nvar client = host.Services.GetRequiredService\u003CCopilotClient>();\n\nawait foreach (var activity in client.StartConversationAsync(emitStartConversationEvent: true))\n{\n    Console.WriteLine(activity.Type);\n}\n\nawait foreach (var activity in client.AskQuestionAsync(\"Hello!\", null))\n{\n    Console.WriteLine(activity.Type);\n}\n```\n\n## Best Practices\n\n1. Use AgentApplication subclasses to centralize routing and error handling.\n2. Use MemoryStorage only for development; use persisted storage in production.\n3. Enable TokenValidation in production and require authorization on \u002Fapi\u002Fmessages.\n4. Keep auth secrets in configuration providers (Key Vault, managed identity, env vars).\n5. Reuse HttpClient from IHttpClientFactory and cache MSAL tokens.\n6. Prefer async handlers and pass CancellationToken to SDK calls.\n\n## Reference Files\n\n| File | Contents |\n| --- | --- |\n| [references\u002Facceptance-criteria.md](references\u002Facceptance-criteria.md) | Import paths, hosting pipeline, Copilot Studio client patterns, anti-patterns |\n\n## Reference Links\n\n| Resource | URL |\n| --- | --- |\n| Microsoft 365 Agents SDK | https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fmicrosoft-365\u002Fagents-sdk\u002F |\n| AddAgent API | https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fdotnet\u002Fapi\u002Fmicrosoft.agents.hosting.aspnetcore.servicecollectionextensions.addagent?view=m365-agents-sdk |\n| AgentApplication API | https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fdotnet\u002Fapi\u002Fmicrosoft.agents.builder.app.agentapplication?view=m365-agents-sdk |\n| Auth configuration options | https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fmicrosoft-365\u002Fagents-sdk\u002Fmicrosoft-authentication-library-configuration-options |\n| Copilot Studio integration | https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fmicrosoft-365\u002Fagents-sdk\u002Fintegrate-with-mcs |\n| GitHub samples | https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fagents |\n",{},"main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002Fmicrosoft\u002Fskills\u002Fm365-agents-dotnet",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":7,"skillName":5,"commands":40,"prompt":50,"zipAvailable":51},[41,44,47],{"tool":42,"command":43},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill m365-agents-dotnet",{"tool":45,"command":46},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill m365-agents-dotnet",{"tool":48,"command":49},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill m365-agents-dotnet","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fmicrosoft\u002Fskills\u002Fm365-agents-dotnet\u002FSKILL.md",true,[],[54,64,74,83,89,96],{"skillNo":55,"name":56,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":57,"categories":58,"keywords":60,"publishedAt":26},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[59],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},[61,62,63],"model","model hierarchy","model hierarchy skill",{"skillNo":65,"name":66,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":67,"categories":68,"keywords":70,"publishedAt":26},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[69],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},[71,72,73],"MCP","zoom","zoom mcp",{"skillNo":75,"name":76,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":77,"categories":78,"keywords":79,"publishedAt":26},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[80,81,82,72],"sdk","zoom apps sdk","apps",{"skillNo":84,"name":85,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":86,"categories":87,"keywords":88,"publishedAt":26},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[85],{"skillNo":90,"name":91,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":92,"categories":93,"keywords":95,"publishedAt":26},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[94],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},[91],{"skillNo":97,"name":98,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":99,"categories":100,"keywords":101,"publishedAt":26},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[98]]