m365-agents-dotnet
Build intelligent agents for the Microsoft 365 ecosystem using the official .NET SDK.
Install
mkdir -p .claude/skills/m365-agents-dotnet && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/4713" && unzip -o skill.zip -d .claude/skills/m365-agents-dotnet && rm skill.zipInstalls to .claude/skills/m365-agents-dotnet
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Microsoft 365 Agents SDK for .NET. Build multichannel agents for Teams/M365/Copilot Studio with ASP.NET Core hosting, AgentApplication routing, and MSAL-based auth. Triggers: "Microsoft 365 Agents SDK", "Microsoft.Agents", "AddAgentApplicationOptions", "AgentApplication", "AddAgentAspNetAuthentication", "Copilot Studio client", "IAgentHttpAdapter".Key capabilities
- →Route requests using AgentApplication
- →Implement MSAL-based authentication
- →Host agents with ASP.NET Core
- →Integrate with Copilot Studio client
- →Manage conversation state
How it works
The SDK provides an AgentApplication class to handle routing and an IAgentHttpAdapter to process incoming HTTP requests within an ASP.NET Core pipeline.
Inputs & outputs
When to use m365-agents-dotnet
- →Create Microsoft 365 agents
- →Implement MSAL-based authentication
- →Build multichannel Teams apps
- →Route requests in Copilot Studio
About this skill
Microsoft 365 Agents SDK (.NET)
Overview
Build 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.
Before implementation
- Use the microsoft-docs MCP to verify the latest APIs for AddAgent, AgentApplication, and authentication options.
- Confirm package versions in NuGet for the Microsoft.Agents.* packages you plan to use.
Installation
dotnet add package Microsoft.Agents.Hosting.AspNetCore
dotnet add package Microsoft.Agents.Authentication.Msal
dotnet add package Microsoft.Agents.Storage
dotnet add package Microsoft.Agents.CopilotStudio.Client
dotnet add package Microsoft.Identity.Client.Extensions.Msal
Configuration (appsettings.json)
{
"TokenValidation": {
"Enabled": true,
"Audiences": ["{{ClientId}}"],
"TenantId": "{{TenantId}}"
},
"AgentApplication": {
"StartTypingTimer": false,
"RemoveRecipientMention": false,
"NormalizeMentions": false
},
"Connections": {
"ServiceConnection": {
"Settings": {
"AuthType": "ClientSecret",
"ClientId": "{{ClientId}}",
"ClientSecret": "{{ClientSecret}}",
"AuthorityEndpoint": "https://login.microsoftonline.com/{{TenantId}}",
"Scopes": ["https://api.botframework.com/.default"]
}
}
},
"ConnectionsMap": [
{
"ServiceUrl": "*",
"Connection": "ServiceConnection"
}
],
"CopilotStudioClientSettings": {
"DirectConnectUrl": "",
"EnvironmentId": "",
"SchemaName": "",
"TenantId": "",
"AppClientId": "",
"AppClientSecret": ""
}
}
Core Workflow: ASP.NET Core agent host
using Microsoft.Agents.Builder;
using Microsoft.Agents.Hosting.AspNetCore;
using Microsoft.Agents.Storage;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpClient();
builder.AddAgentApplicationOptions();
builder.AddAgent<MyAgent>();
builder.Services.AddSingleton<IStorage, MemoryStorage>();
builder.Services.AddControllers();
builder.Services.AddAgentAspNetAuthentication(builder.Configuration);
WebApplication app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapGet("/", () => "Microsoft Agents SDK Sample");
var incomingRoute = app.MapPost("/api/messages",
async (HttpRequest request, HttpResponse response, IAgentHttpAdapter adapter, IAgent agent, CancellationToken ct) =>
{
await adapter.ProcessAsync(request, response, agent, ct);
});
if (!app.Environment.IsDevelopment())
{
incomingRoute.RequireAuthorization();
}
else
{
app.Urls.Add("http://localhost:3978");
}
app.Run();
AgentApplication routing
using Microsoft.Agents.Builder;
using Microsoft.Agents.Builder.App;
using Microsoft.Agents.Builder.State;
using Microsoft.Agents.Core.Models;
using System;
using System.Threading;
using System.Threading.Tasks;
public sealed class MyAgent : AgentApplication
{
public MyAgent(AgentApplicationOptions options) : base(options)
{
OnConversationUpdate(ConversationUpdateEvents.MembersAdded, WelcomeAsync);
OnActivity(ActivityTypes.Message, OnMessageAsync, rank: RouteRank.Last);
OnTurnError(OnTurnErrorAsync);
}
private static async Task WelcomeAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken ct)
{
foreach (ChannelAccount member in turnContext.Activity.MembersAdded)
{
if (member.Id != turnContext.Activity.Recipient.Id)
{
await turnContext.SendActivityAsync(
MessageFactory.Text("Welcome to the agent."),
ct);
}
}
}
private static async Task OnMessageAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken ct)
{
await turnContext.SendActivityAsync(
MessageFactory.Text($"You said: {turnContext.Activity.Text}"),
ct);
}
private static async Task OnTurnErrorAsync(
ITurnContext turnContext,
ITurnState turnState,
Exception exception,
CancellationToken ct)
{
await turnState.Conversation.DeleteStateAsync(turnContext, ct);
var endOfConversation = Activity.CreateEndOfConversationActivity();
endOfConversation.Code = EndOfConversationCodes.Error;
endOfConversation.Text = exception.Message;
await turnContext.SendActivityAsync(endOfConversation, ct);
}
}
Copilot Studio direct-to-engine client
DelegatingHandler for token acquisition (interactive flow)
using System.Net.Http.Headers;
using Microsoft.Agents.CopilotStudio.Client;
using Microsoft.Identity.Client;
internal sealed class AddTokenHandler : DelegatingHandler
{
private readonly SampleConnectionSettings _settings;
public AddTokenHandler(SampleConnectionSettings settings) : base(new HttpClientHandler())
{
_settings = settings;
}
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
if (request.Headers.Authorization is null)
{
string[] scopes = [CopilotClient.ScopeFromSettings(_settings)];
IPublicClientApplication app = PublicClientApplicationBuilder
.Create(_settings.AppClientId)
.WithAuthority(AadAuthorityAudience.AzureAdMyOrg)
.WithTenantId(_settings.TenantId)
.WithRedirectUri("http://localhost")
.Build();
AuthenticationResult authResponse;
try
{
var account = (await app.GetAccountsAsync()).FirstOrDefault();
authResponse = await app.AcquireTokenSilent(scopes, account).ExecuteAsync(cancellationToken);
}
catch (MsalUiRequiredException)
{
authResponse = await app.AcquireTokenInteractive(scopes).ExecuteAsync(cancellationToken);
}
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authResponse.AccessToken);
}
return await base.SendAsync(request, cancellationToken);
}
}
Console host with CopilotClient
using Microsoft.Agents.CopilotStudio.Client;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
var settings = new SampleConnectionSettings(
builder.Configuration.GetSection("CopilotStudioClientSettings"));
builder.Services.AddHttpClient("mcs").ConfigurePrimaryHttpMessageHandler(() =>
{
return new AddTokenHandler(settings);
});
builder.Services
.AddSingleton(settings)
.AddTransient<CopilotClient>(sp =>
{
var logger = sp.GetRequiredService<ILoggerFactory>().CreateLogger<CopilotClient>();
return new CopilotClient(settings, sp.GetRequiredService<IHttpClientFactory>(), logger, "mcs");
});
IHost host = builder.Build();
var client = host.Services.GetRequiredService<CopilotClient>();
await foreach (var activity in client.StartConversationAsync(emitStartConversationEvent: true))
{
Console.WriteLine(activity.Type);
}
await foreach (var activity in client.AskQuestionAsync("Hello!", null))
{
Console.WriteLine(activity.Type);
}
Best Practices
- Use AgentApplication subclasses to centralize routing and error handling.
- Use MemoryStorage only for development; use persisted storage in production.
- Enable TokenValidation in production and require authorization on /api/messages.
- Keep auth secrets in configuration providers (Key Vault, managed identity, env vars).
- Reuse HttpClient from IHttpClientFactory and cache MSAL tokens.
- Prefer async handlers and pass CancellationToken to SDK calls.
Reference Links
When not to use it
- →When using non-ASP.NET Core hosting environments
- →When requiring non-MSAL authentication methods
Prerequisites
Limitations
- →MemoryStorage is for development only
- →Requires explicit configuration for production token validation
How it compares
It provides a structured framework for multichannel agent routing and authentication compared to manual HTTP request handling.
Compared to similar skills
m365-agents-dotnet side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| m365-agents-dotnet (this skill) | 1 | 3mo | Review | Intermediate |
| dotnet-backend-patterns | 7 | 5mo | No flags | Advanced |
| azure-maps-search-dotnet | 2 | 3mo | Review | Intermediate |
| azure-servicebus-dotnet | 3 | 3mo | Review | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by microsoft
View all by microsoft →You might also like
dotnet-backend-patterns
wshobson
Master C#/.NET backend development patterns for building robust APIs, MCP servers, and enterprise applications. Covers async/await, dependency injection, Entity Framework Core, Dapper, configuration, caching, and testing with xUnit. Use when developing .NET backends, reviewing C# code, or designing API architectures.
azure-maps-search-dotnet
microsoft
Azure Maps SDK for .NET. Location-based services including geocoding, routing, rendering, geolocation, and weather. Use for address search, directions, map tiles, IP geolocation, and weather data. Triggers: "Azure Maps", "MapsSearchClient", "MapsRoutingClient", "MapsRenderingClient", "geocoding .NET", "route directions", "map tiles", "geolocation".
azure-servicebus-dotnet
microsoft
Azure Service Bus SDK for .NET. Enterprise messaging with queues, topics, subscriptions, and sessions. Use for reliable message delivery, pub/sub patterns, dead letter handling, and background processing. Triggers: "Service Bus", "ServiceBusClient", "ServiceBusSender", "ServiceBusReceiver", "ServiceBusProcessor", "message queue", "pub/sub .NET", "dead letter queue".
azure-eventgrid-dotnet
microsoft
Azure Event Grid SDK for .NET. Client library for publishing and consuming events with Azure Event Grid. Use for event-driven architectures, pub/sub messaging, CloudEvents, and EventGridEvents. Triggers: "Event Grid", "EventGridPublisherClient", "CloudEvent", "EventGridEvent", "publish events .NET", "event-driven", "pub/sub".
azure-mgmt-mongodbatlas-dotnet
microsoft
Manage MongoDB Atlas Organizations as Azure ARM resources using Azure.ResourceManager.MongoDBAtlas SDK. Use when creating, updating, listing, or deleting MongoDB Atlas organizations through Azure Marketplace integration. This SDK manages the Azure-side organization resource, not Atlas clusters/databases directly.
websocket-integration
sunyonghuan
通过 WebSocket 连接 Cortana AI 对话服务。编写 C# 客户端代码,实现发送消息、接收流式回复、附件传输、系统事件监听。触发关键词:WebSocket、WS 连接、远程对话、流式回复、AI 接入、实时通信。