D4S.Agent
1.1.0
dotnet add package D4S.Agent --version 1.1.0
NuGet\Install-Package D4S.Agent -Version 1.1.0
<PackageReference Include="D4S.Agent" Version="1.1.0" />
<PackageVersion Include="D4S.Agent" Version="1.1.0" />
<PackageReference Include="D4S.Agent" />
paket add D4S.Agent --version 1.1.0
#r "nuget: D4S.Agent, 1.1.0"
#:package D4S.Agent@1.1.0
#addin nuget:?package=D4S.Agent&version=1.1.0
#tool nuget:?package=D4S.Agent&version=1.1.0
D4S.Agent
Reusable Microsoft Agent Framework implementation for Microsoft 365 / Teams bots. Add one DI
call, depend on IMafAgent, and the package owns the agent turn, guardrail, middlewares, tools, and
prompt composition — your host keeps only auth, storage, and bot wiring.
Features
- Single-call setup —
AddMafAgent(configuration)wires chat clients, middlewares, plugins, guardrail, and MCP tools. - Agent turn —
InvokeAgentAsyncwith session persistence; returns text or an Adaptive Card. - Topic guardrail — off-topic messages get a polite redirect, no main-model call.
- Middlewares — thinking-UX labels, audit logging, loop cap, Teams keep-alive heartbeat.
- Citations — retrieval sources are captured from tool results and appended as a short source list.
- Tools — built-in Adaptive Card tool, host-contributed tools, and MCP server tools.
- Prompt composer — one folder per customer under
Prompts/<customer>(basealways-on generic +specificalways-on customer prompts and on-demand tool/MCP instructions files), selected viaBot:PromptsFolder.
Install
dotnet add package D4S.Agent
Quick start
Register everything the agent needs in one call:
builder.Services.AddMafAgent(builder.Configuration);
Depend on IMafAgent from your bot and render its response:
var response = await _agent.InvokeAgentAsync(turnContext, turnState, cancellationToken);
// response.ContentType ∈ { Text, AdaptiveCard }; response.Content is the payload.
Your host must:
- provide the
MicrosoftFoundryconfig — a validEndpointis required at startup; - set
Bot:PromptsFolderto a customer folder name underPrompts/(e.g.Customer1); - copy that customer's
Prompts/<customer>/base/*.mdandPrompts/<customer>/specific/*.mdto its output directory — the composer reads them fromAppContext.BaseDirectory(plusSkills/whenBot:AgentSkillsEnabledis on).
Configuration
| Section | Purpose |
|---|---|
MicrosoftFoundry |
Azure OpenAI Endpoint / ApiKey / Deployment for the main chat client. |
MicrosoftFoundryGuardrail |
Smaller deployment for the guardrail (falls back to MicrosoftFoundry). Required when Bot:TopicGuardEnabled. |
Bot |
Feature toggles + tuning (topic guard, Adaptive Cards, skills, heartbeat, loop cap…). |
Mcp |
MCP servers whose tools are exposed to the agent. |
Citations |
Source-list settings: Enabled, ToolNames (default ["search"]), Header (default Sources), MaxCitations (0 = unlimited). |
Architecture
MafAgent is a thin orchestrator. Each turn it delegates to three focused services, every one behind
an interface and registered as a replaceable default:
| Interface | Default | Responsibility |
|---|---|---|
IAgentBuilder |
AgentBuilderService |
Composes the instructions, tools, and middleware pipeline into the AIAgent. |
IMcpToolkit |
McpToolkitService |
Discovers MCP server tools (per turn) and disposes their clients. |
ITopicGuard |
TopicGuardService |
Off-topic classification, redirect generation, and guard history. |
The whole turn loop itself is IMafAgent (default MafAgent).
Extending
AddMafAgent returns a MafAgentBuilder, so overrides chain off it. Each WithCustomXxx replaces
the matching default registration, so call order doesn't matter and your implementation always wins.
Add a tool (code):
AddMafAgent(config, o => o.AdditionalTools.Add(new AgentTool(sp => AIFunctionFactory.Create(...), InstructionsFile: "my-tool.md"))). The optional.md(shipped in the customer'sPrompts/<customer>/specificfolder) is appended to the instructions on demand.Add MCP servers (config): list them under
Mcp:Servers(HttporStdio). An optionalToolsallow-list selects a subset; unreachable servers are logged and skipped (fail-soft).Replace a single concern: chain the matching builder method, passing your implementation of that seam's interface:
builder.Services .AddMafAgent(builder.Configuration) .WithCustomAgentBuilder<MyAgentBuilder>() // IAgentBuilder — instruction/tool/middleware composition .WithCustomMcpToolkit<MyMcpToolkit>() // IMcpToolkit — MCP discovery + disposal .WithCustomTopicGuard<MyTopicGuard>(); // ITopicGuard — classification, redirect, historyReplace the whole turn loop:
.WithCustomAgent<MyAgent>()with your ownIMafAgent— the heaviest seam; use only for a fundamentally different flow.
Requirements
net10.0- Key dependencies:
Microsoft.Agents.AI,Microsoft.Extensions.AI(.OpenAI),Microsoft.Agents.Builder,Azure.AI.OpenAI,ModelContextProtocol.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Azure.AI.OpenAI (>= 2.1.0)
- Azure.Identity (>= 1.17.1)
- Microsoft.Agents.AI (>= 1.10.0)
- Microsoft.Agents.Builder (>= 1.6.150)
- Microsoft.Extensions.AI (>= 10.7.0)
- Microsoft.Extensions.AI.OpenAI (>= 10.7.0)
- ModelContextProtocol (>= 1.4.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.