D4S.Agent
1.1.4
dotnet add package D4S.Agent --version 1.1.4
NuGet\Install-Package D4S.Agent -Version 1.1.4
<PackageReference Include="D4S.Agent" Version="1.1.4" />
<PackageVersion Include="D4S.Agent" Version="1.1.4" />
<PackageReference Include="D4S.Agent" />
paket add D4S.Agent --version 1.1.4
#r "nuget: D4S.Agent, 1.1.4"
#:package D4S.Agent@1.1.4
#addin nuget:?package=D4S.Agent&version=1.1.4
#tool nuget:?package=D4S.Agent&version=1.1.4
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", "ask"]), Header (default Sources), MaxCitations (0 = unlimited). |
Citation tool contract
For each tool listed in Citations:ToolNames, the citation middleware reads a citations collection
from the result root or from the MCP structuredContent object. Every item can contain title,
sourceUrl, and score; at least title or sourceUrl must be present. A #page=N fragment in
sourceUrl is displayed as the source page, and score controls source ordering.
The D4S Knowledge Retrieval MCP conforms to this contract for both search and ask. Its search
response still contains passages for grounding and compatibility, but the Agent reads citations
only from the common citations collection.
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.9.0-beta.1)
- Azure.Identity (>= 1.21.0)
- Azure.Storage.Blobs (>= 12.29.1)
- Microsoft.Agents.AI (>= 1.13.0)
- Microsoft.Agents.Builder (>= 1.6.150)
- Microsoft.Extensions.AI (>= 10.8.0)
- Microsoft.Extensions.AI.OpenAI (>= 10.8.0)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.10)
- ModelContextProtocol (>= 1.4.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.