MentorAgent.Declarative 1.0.0-preview.5

This is a prerelease version of MentorAgent.Declarative.
dotnet add package MentorAgent.Declarative --version 1.0.0-preview.5
                    
NuGet\Install-Package MentorAgent.Declarative -Version 1.0.0-preview.5
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="MentorAgent.Declarative" Version="1.0.0-preview.5" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="MentorAgent.Declarative" Version="1.0.0-preview.5" />
                    
Directory.Packages.props
<PackageReference Include="MentorAgent.Declarative" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add MentorAgent.Declarative --version 1.0.0-preview.5
                    
#r "nuget: MentorAgent.Declarative, 1.0.0-preview.5"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package MentorAgent.Declarative@1.0.0-preview.5
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=MentorAgent.Declarative&version=1.0.0-preview.5&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=MentorAgent.Declarative&version=1.0.0-preview.5&prerelease
                    
Install as a Cake Tool

MentorAgent.Declarative

Preview Release — MentorAgent is currently in public preview. APIs may change before the stable release.

Optional package. Install it only if you want to define specialist agents in YAML files instead of C# classes. Everything MentorAgent does works without it.

Define a Level-2 specialist in a text file, drop it next to your application, and the assistant can hand off to it — no new class, no [MentorAgent] attribute, no recompile of the agent's behaviour.

Built on the Agent Framework's declarative agent factory (Microsoft.Agents.AI.Declarative).


Package Family

Package Install when
MentorAgent Blazor Server app
MentorAgent.Server Web API / headless backend, or Blazor Auto server-side project
MentorAgent.Blazor Blazor WASM / Blazor Auto client project
MentorAgent.Abstractions Never directly — it arrives with any of the above
MentorAgent.Declarative ← you are here You want YAML-defined agents. Add it alongside MentorAgent or MentorAgent.Server

Table of Contents


What it does

MentorAgent's three-level agent model has a coordinator (L1) that can hand off to specialists (L2). Normally a specialist is a C# class:

[MentorAgent("ShippingAgent", "Answers questions about deliveries")]
public class ShippingAgent
{
    [MentorAction("get_tracking", "Looks up a tracking number")]
    public string GetTracking(int orderId) => /* … */;
}

This package adds a second way to declare the agent — its name, its instructions, its model settings and which tools it may use — as a file:

kind: Prompt
name: ShippingAgent
description: Answers questions about deliveries and shipping costs
instructions: |
  You handle shipping questions only. Use the available tools to look up real orders;
  never invent a tracking number. If the question is not about shipping, say so and stop.
model:
  options:
    temperature: 0.2
tools:
  - kind: function
    name: get_order_status
  - kind: function
    name: get_all_orders

Both kinds end up in the same handoff graph, so route_to_specialist reaches them identically and the user cannot tell which is which.


Getting started

Installation

dotnet add package MentorAgent.Declarative

Registration

builder.Services.AddMentorAgentDeclarative(o => o.Directory = "Agents");

builder.Services.AddMentorAgent(o =>
{
    o.ChatClient     = chatClient;
    o.AppName        = "ShopFlow";
    o.ScanAssemblies = [typeof(Program).Assembly];
});

Order does not matter — MentorAgent asks every registered agent source while it builds the coordinator, which happens on the first message.

Make sure the files reach the output folder

A definition that is not copied is the most common way this feature appears not to work. In your .csproj:

<ItemGroup>
  <Content Include="Agents\**\*.agent.yaml" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

If the directory is missing at startup you get a warning naming the resolved path — that message exists because the failure is otherwise silent.


The YAML format

The schema comes from the Agent Framework, not from MentorAgent. The fields that matter in practice:

Field Meaning
kind Prompt for a prompt-based agent. Required
name The specialist's name. This is what appears in handoff logs — keep it stable
description What this specialist is for. The coordinator reads it to decide when to route here
instructions The agent's system prompt. Use a \| block for multiple lines
model.options temperature, topP, and other per-agent model settings
tools Names of tools this agent may call — each entry needs kind and name, see below
outputSchema Optional JSON-schema-style shape for a typed answer

description is worth care: it is the coordinator's only basis for choosing this agent over another. "Handles orders" competes badly with "Handles orders, shipping and returns for existing customers".

Two format details that cost an afternoon

Neither is in the Agent Framework guide, and both fail in a way that points somewhere else.

Every tools entry needs kind. Accepted values are codeInterpreter, fileSearch, function, webSearch and mcp; function is the one that binds to a tool of your application. Omit it and loading fails with NotSupportedException — not a validation message naming the line.

Folded scalars (>) are not supported by this reader. Use |, or a single line. With > the parse error reports the end of the file, so you will look everywhere except at the block that caused it:

description: >                     # ✗ parse error, blamed on the last line of the file
  Handles shipping and delivery.

description: |                     # ✓
  Handles shipping and delivery.

description: Handles shipping.     # ✓

Tools: named, not defined

A tools: entry names a tool; it does not create one. The name must match a tool your application already exposes — a [MentorAction] method, or any other Level-1 tool.

tools:
  - kind: function              # required — see below
    name: get_order_status      # must exist; a typo simply means the agent never gets that tool

The tool name is the snake_case of the C# member, with a trailing Async dropped: GetOrderStatusAsync()get_order_status. Get it wrong and nothing tells you — the agent simply starts without that tool and then improvises an answer it has no data for.

This is the design point of the whole package. MentorAgent hands the factory the application's real tool list, already wrapped in its gate, so a YAML agent calling create_order still hits:

  • RequiredRoles — the role check, exactly as a C# specialist does
  • human approval — the confirmation banner, if the tool requires one
  • action feedback, per-tool metrics and tracing

An agent defined in a file therefore has no capability your application did not already have, and no shortcut around the controls on it.


Security — a definition file is code

Read this before pointing Directory anywhere.

A definition chooses the model, writes the system instructions, and names the tools the agent may call. Anyone who can write that file can rewrite the assistant's persona and widen which tools it reaches for. That makes it code, whatever its file extension says.

  • Load only from deploy-time locations. An application directory or an embedded resource. Never an upload folder, never a user-writable path, never a path built from request input.
  • Review definitions like source. Put them in version control and through the same review as a .cs file.
  • The gate still holds. A file cannot invent a tool or bypass a role check — that is enforced, not advisory. But it can instruct the agent to try things, so the controls on your tools remain the thing that actually stops it.

The second point is the one people skip: YAML feels like configuration, and configuration feels safe to let more people edit.


When to use YAML and when to use C#

YAML C# [MentorAgent]
Change an agent's instructions Edit a file Recompile
New tool / new logic Not possible — tools stay in C# Where it belongs
Compile-time checking None; a bad tool name is silent Full
Who can author it Anyone who can edit a reviewed file Developers
Fits when Wording and routing get tuned often The agent has real behaviour

A good rule: behaviour in C#, phrasing in YAML. If you find yourself wanting a loop or a branch in a definition file, that agent wants to be a class.

You can mix freely — both kinds coexist in the same handoff graph.


Loading definitions from somewhere else

Definitions do not have to be files. Pass them as strings for agents stored in a database, a configuration service, or a test:

builder.Services.AddMentorAgentDeclarative(o =>
{
    o.Definitions.Add("""
        kind: Prompt
        name: FaqAgent
        description: Answers frequently asked questions about the shop
        instructions: Answer briefly, in the user's language. Say so when you do not know.
        """);
});

For a fully custom source — one that hits your own store, or refreshes on a schedule — implement IMentorAgentSource from the MentorAgent package directly and register it. AddMentorAgentDeclarative is one implementation of that interface, not a privileged path:

public sealed class DatabaseAgentSource : IMentorAgentSource
{
    public async Task<IReadOnlyList<AIAgent>> GetAgentsAsync(
        MentorAgentSourceContext context, CancellationToken ct = default)
    {
        // context.ChatClient — the coordinator's client, so usage lands in the metrics
        // context.Tools      — the Level-1 tools, already gated
        …
    }
}

builder.Services.AddSingleton<IMentorAgentSource, DatabaseAgentSource>();

Configuration options

Option Type Default Description
Directory string? null Folder to scan, absolute or relative to the app base directory. Deploy-time paths only
SearchPattern string "*.agent.yaml" File pattern inside Directory
Recursive bool false Scan subdirectories too
Definitions IList<string> empty YAML supplied inline, loaded in addition to Directory
ConfigurationSection string? null Name of the configuration section the YAML may reference. null exposes nothing

ConfigurationSection — exposing configuration to a definition

Default null: no configuration reaches the YAML at all, and the definitions are self-contained. Set it to expose one section, so a definition can reference values instead of hardcoding them:

// appsettings.json
{
  "AgentSettings": {
    "SupportEmail": "help@contoso.com",
    "MaxRefund": "250"
  }
}
builder.Services.AddMentorAgentDeclarative(o =>
{
    o.Directory            = "Agents";
    o.ConfigurationSection = "AgentSettings";   // only AgentSettings:* reaches the YAML
});

The values arrive as Power Fx variables named after the keys — SupportEmail, MaxRefund. How a definition references them is part of the Agent Framework's declarative schema, not something MentorAgent defines, so check the framework's documentation for the expression syntax before relying on it.

Name a section. Never hand over the whole IConfiguration. The factory loads whatever configuration it is given into the Power Fx engine as variables — one per key, in its constructor. Every key must therefore be a valid Power Fx identifier, and a single one that is not takes the entire factory down before any definition is read. This is not hypothetical: a key literally named ${name}, contributed by an unrelated configuration provider, produced

ArgumentException: Invalid name: ${name}

and no agents loaded at all. Naming one section bounds the blast radius to keys you control.

MentorAgent catches that failure and logs the cause rather than letting it surface as a generic startup error, then returns no agents:

[MentorAgent:Declarative] The agent factory rejected the configuration exposed to YAML
(AgentSettings). Every key in it becomes a Power Fx variable and must be a valid identifier.
Narrow MentorDeclarativeOptions.ConfigurationSection, or leave it null.

If you see it, the fix is a narrower section — or null, which is the right setting unless you actually need substitution.


How to test it

  1. Put shipping.agent.yaml in an Agents folder, with CopyToOutputDirectory.
  2. Start the app. The log should show, at Information level:
    [MentorAgent:Declarative] Agent 'ShippingAgent' loaded from shipping.agent.yaml (12 tool(s) available to it).
    [MentorAgent] Handoff: declarative agent 'ShippingAgent' added to workflow.
    
  3. Ask something in that agent's area — "where is order 1001?". The answer should come back through it.
  4. Negative check — a bad file does not take the app down. Break the YAML deliberately: you get 'shipping.agent.yaml' could not be loaded — skipped, and everything else still starts.
  5. Negative check — the gate holds. Name a tool carrying RequiredRoles in the YAML and ask the agent to use it while unauthenticated. It must be refused, the same way a C# specialist is, and no action taken.

Why a separate package

Microsoft.Agents.AI.Declarative brings the Power Fx interpreter (YAML expressions are Power Fx), the Agents object model in three assemblies, Microsoft.ML.Tokenizers and several more.

That is a fair price for file-based authoring and pure overhead for everyone else, so it stays out of the MentorAgent core package. Installing this one is an explicit decision to pay it.

The reference is pinned to the 1.6.1 line, matching Microsoft.Agents.AI in the core package, so adding it does not move the rest of the library onto a different Agent Framework version.


Requirements

  • .NET 10
  • MentorAgent (or MentorAgent.Server) configured with a ChatClient — declarative agents need one, and are skipped with a warning without it
  • A provider supporting the model options you use in the definitions

Package Purpose
MentorAgent Blazor Server — full AI assistant
MentorAgent.Server Any ASP.NET Core app — headless AI backend
MentorAgent.Blazor Blazor WASM — SignalR client
MentorAgent.Abstractions Shared contracts and UI components

License

MIT — the full text ships in the repository's LICENSE file.

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0-preview.5 34 8/12/2026

1.0.0-preview.5

=== First release ===========================================================
- NEW — MentorAgent.Declarative: define a Level-2 specialist in a YAML file instead of a C# class. AddMentorAgentDeclarative() loads *.agent.yaml from a directory (or inline strings) and the agents join the same handoff graph as [MentorAgent] classes, so route_to_specialist reaches them exactly the same way.
- The YAML names tools; it does not define them. Every tool a declarative agent may call is resolved from the Level-1 tools your application already registers, and is handed over already wrapped in MentorAgent's gate — so RequiredRoles, human approval, action feedback and per-tool metrics keep working. A YAML file cannot grant itself a capability the application does not already have.
- Definitions are loaded from paths you configure at deploy time. Treat them as code: an agent file chooses the model, writes the system instructions and names the callable tools.
- A malformed or unloadable definition is logged and skipped; it never prevents the assistant from starting.

=== Why a separate package ==================================================
- The Agent Framework's declarative stack brings the Power Fx interpreter, the Agents object model and several other dependencies. They are worth it if you want file-based authoring and pure overhead if you do not, so they stay out of the MentorAgent core package.