Changelog
Every MentorAgent version published on NuGet, newest first: its date, what it added, changed, removed and fixed, and the issues known at the time.
On this page
This page lists every MentorAgent version published on NuGet, newest first. The five packages, Novior.MentorAgent, Novior.MentorAgent.Abstractions, Novior.MentorAgent.Blazor, Novior.MentorAgent.Declarative and Novior.MentorAgent.Server, are released together and share one version number. For the current version, what to do when you upgrade and the defects still open, see What's new.
Up to 1.0.0-rc.15 the packages were published as MentorAgent, MentorAgent.Abstractions, MentorAgent.Blazor, MentorAgent.Declarative and MentorAgent.Server. From 1.0.0 their IDs start with Novior.. The entries of each version use the names of their time. Move to the Novior.MentorAgent packages explains the change.
The entries are those of the library's CHANGELOG.md, in the same order within each section. Since 1.0.0-rc.13 every package contains CHANGELOG.md, and its release notes on NuGet are the section of that version.
Version numbers follow Semantic Versioning 2.0.0: see Versioning and support. The changelog follows the Keep a Changelog 1.1.0 format. Under each version, the changes are grouped as Added, Changed, Deprecated, Removed, Fixed and Security. Known issues lists the defects still open in that version. An entry that concerns one package only starts with the name of that package.
BUG-nnn identifiers are stable references to the maintainers' defect log. The tag next to one, from S1 to S4, is its severity:
- S1: data loss, a security hole or a crash.
- S2: a documented feature that does not work, or documentation that leads to a broken result.
- S3: wrong behavior in an edge case, or documentation that contradicts the code.
- S4: cosmetic.
The date under each version is the day it was published on NuGet, in UTC. The date in CHANGELOG.md can differ by one day.
MentorAgent succeeds the BlazorMentor (external site) package, published from 0.1.0-preview.1 to 0.5.0-preview and now deprecated on NuGet in favor of MentorAgent. This page does not cover it: 1.0.0-preview is the first version under the MentorAgent name.
Published on NuGet on 13 October 2026 (UTC): Novior.MentorAgent 1.0.0 (external site).
Changed
Section titled “Changed”- Breaking — all packages: the packages are now
Novior.MentorAgent,Novior.MentorAgent.Abstractions,Novior.MentorAgent.Blazor,Novior.MentorAgent.DeclarativeandNovior.MentorAgent.Server. TheMentorAgent.*IDs end with 1.0.0-rc.15. The namespaces follow (using Novior.MentorAgent.Extensions;), the widget's static files are served from_content/Novior.MentorAgent.Abstractions/, and the log categories start withNovior.MentorAgent, so a"MentorAgent"filter underLogging:LogLevelno longer matches. The five packages depend on each other at their exact version. These do not change: the types and extension methods (AddMentorAgent,MentorOptionsand the others), the routes, the names of the telemetry source, meter and metrics, the format of session snapshots, theMentorAgentMcpCORS policy,MentorAgent.css,MentorAgent.jsandwindow.MentorAgent.- Migration. See Move to the Novior.MentorAgent packages.
- Novior.MentorAgent: four warnings outside the tool gate still carried a whole exception, whose text comes from the host's code: a UI action that threw, with a
ChatClientor a prebuiltAgent, and anOnToolResultor aMcpCallerPrincipalthat threw on the MCP server. As in the gate, they now name the type of the exception, and the whole exception is logged at Debug (BUG-152, S3). - Breaking — Novior.MentorAgent.Server:
AddMentorAgentMcp()orAddMentorAgentA2A()registered nothing and said nothing in two cases: called beforeAddMentorAgent(), or withMcpServerEnabledorA2AServerEnabledturned on afterAddMentorAgent()had read them, with aConfigureorPostConfigureofMentorOptions. The map call failed later, in the second case naming a call the host had made. The host now stops at startup with the reason and the fix. A host that ran without the server because of it no longer starts (BUG-153, S3). - Novior.MentorAgent: the README and the 1.0.0-rc.15 notes said that the warning about writes that run without confirmation comes at startup. It comes the first time the actions are read: at startup only with
WarmUpAtStartuporMapMentorAgentA2A(), otherwise with the first conversation or the first MCP or tour request. With[Description]alone it also names the methods that only read, untilIsReadOnlyActionor[MentorAction(ReadOnly = true)]declares them. The README now says both (BUG-154, S3). - Novior.MentorAgent.Server: the README's minimal SignalR client called Stop, the confirmations and the session save and restore without the hub's credentials. With cookies from another origin, or a bearer token, those calls were anonymous and did nothing. It now sends them, like the complete components. The README also no longer says that the MCP and A2A servers are built into
MentorAgent(BUG-155, S3). - Novior.MentorAgent: the READMEs, the XML documentation of
AddMentorAgent()and the startup warning for a callback that throws listedAppDescriptionandAgentCardamong the options read at registration. OnlyAppNameis read there, as the name of the MCP server. The A2A card is built from the real options whenMapMentorAgentA2A()runs (BUG-156, S4). - Novior.MentorAgent: the README's MAUI step 3, pasted into the MAUI Blazor Hybrid template, did not compile. It lacked
using System.Reflection;andusing Microsoft.Extensions.Configuration;, andAddUserSecretsneedsMicrosoft.Extensions.Configuration.UserSecrets, which neither the template norMentorAgentbrings. The step now names both and the package, and says thatAddUserSecretsneeds the project'sUserSecretsIdand finds the secrets only on the development machine (BUG-157, S3). - Novior.MentorAgent.Abstractions: its README said that the core package depends on
ModelContextProtocol.AspNetCore. Since 1.0.0-rc.15 that transport is in the Server package, and the core referencesModelContextProtocol(BUG-158, S3).
1.0.0-rc.15
Section titled “1.0.0-rc.15”Published on NuGet on 7 October 2026 (UTC): MentorAgent 1.0.0-rc.15 (external site).
- MentorAgent.Server:
AddMentorAgentMcp()andAddMentorAgentA2A()register the MCP server and the A2A agent. Each one registers only when its option is on,McpServerEnabledorA2AServerEnabled, asAddMentorAgentdid up to 1.0.0-rc.14.AddMentorAgentServer()calls both, so a host that calls it changes nothing. Without them,MapMentorAgentMcp()andMapMentorAgentA2A()stop the host at startup, with an error that names the method to add. - MentorAgent: a RAG source can see who is asking, from where and after what. MentorAgent now calls
IMentorRagSource.SearchAsync(MentorRagRequest, CancellationToken). The request carries the message,RagResultCount, the last three turns of the conversation, the signed-in user (ClaimsPrincipal), and the name and data of the current page. The default implementation callsSearchAsync(query, maxResults), so every existing source compiles and works as before. - MentorAgent.Abstractions:
MentorRagResult.Metadataholds key/value facts about a document, such as a date or a version. The model sees them under the document's title. They also travel with the citation chips: hub clients receivemetadatainRagSourcesReady. It is an init property, so the constructor with four values does not change. - MentorAgent:
IMentorRagSource.DefaultMinScorelets a source declare the relevance threshold for its own scale. It applies when the host has not setRagMinScore, in code or in configuration. A vector source that declares one, say 0.6, now gets its documents to the model with the default options. Before, the default of 2 discarded every cosine score. The warning about a wrong scale now says which threshold discarded everything: the option, the source's or the default. - MentorAgent:
MentorOptions.ChatReducerreplaces the reducer of the built-in in-memory history.MentorChatReducer, in theMentorAgent.Corenamespace, is the new default, and you can give it to a history provider of your own. AChatReducerthat cannot apply logs a warning: next to a history provider you supply, or withUseServiceManagedHistory.
Changed
Section titled “Changed”- The five packages are licensed under the Apache License 2.0 from this version, with a
NOTICEfile next toLICENSE. Versions up to and including 1.0.0-rc.14 keep the MIT License. - Package metadata: the authors are the copyright holders named in
NOTICE, and the project page is mentoragent.net. - Breaking — MentorAgent: the MCP server and the A2A agent moved to MentorAgent.Server, together with
MapMentorAgentMcp()andMapMentorAgentA2A(), which stay in theMentorAgent.Extensionsnamespace.AddMentorAgentno longer registers them. The reason: their packages needMicrosoft.AspNetCore.App, which does not exist on Android, iOS or Mac Catalyst. A MAUI app that referenced MentorAgent built only for Windows (NETSDK1082). Now the MAUI Blazor Hybrid template builds fornet10.0-androidunchanged, and it no longer needs a higherMicrosoft.Extensions.Logging.Debug(NU1605). MentorAgent now referencesModelContextProtocol1.3.0 andA2A1.0.0-preview2, for the MCP and A2A clients. MentorAgent.Server referencesModelContextProtocol.AspNetCore1.3.0 andA2A.AspNetCore1.0.0-preview2 (BUG-119, S2).- Migration. A host that calls
AddMentorAgentServer()changes nothing in its code. A Blazor Server host that serves MCP or A2A without the hub adds theMentorAgent.Serverpackage, and callsbuilder.Services.AddMentorAgentMcp(),AddMentorAgentA2A()or both afterAddMentorAgent(). Itsusinglines stay as they are. Code compiled against 1.0.0-rc.14 must be rebuilt, because the types changed assembly. - A host no longer receives the hosting packages through MentorAgent, so it references the ones it uses:
Microsoft.Agents.AI.Hosting,Microsoft.Agents.AI.Hosting.A2A,Microsoft.Agents.AI.Hosting.AspNetCore,Microsoft.Agents.AI.Hosting.A2A.AspNetCore,Microsoft.Extensions.Hosting,Microsoft.Extensions.Logging.Console, and the otherMicrosoft.Extensions.Configuration.*andLogging.*packages that came with them.
- Migration. A host that calls
- MentorAgent: the READMEs now describe MCP and A2A in MentorAgent.Server, where the code is.
- Breaking — MentorAgent: writes ask for confirmation by default, with
RequireConfirmationForWrites, new and on by default. A[MentorAction]that declares neitherReadOnly = truenorRequiresConfirmationis treated as an action that changes data. It shows the confirmation banner like one declaredRequiresConfirmation = true, in the Blocking flow and withHitlMode.Nativealike. Since it needs confirmation, it is also withheld from the MCP server (tools/list) and from the A2A agent card. And it is no longer one of the actions without rules that tool filtering may send when a message matches nothing. WithRequireActionForChangeRequestson, more actions can now be required as the first call, because only actions that ask for confirmation are ever required. Only[MentorAction]methods are covered: a method with[Description]alone asks for nothing and stays on/mcp, as before. Mark it[MentorAction]to get the default. See Roles, confirmation and governance.- Migration. Declare
ReadOnly = trueon the actions that only read, andRequiresConfirmation = falseon the writes that must run without asking. Or setoptions.RequireConfirmationForWrites = falsefor the 1.0.0-rc.14 behavior. The first time MentorAgent reads your actions, a warning lists the writes that run without confirmation, in two lists: the[MentorAction]methods opted out, and the[Description]methods not declared read-only withIsReadOnlyAction.
- Migration. Declare
- Breaking — MentorAgent: the package brings no AI provider SDK any more (BUG-120, S2). It no longer references
Azure.AI.OpenAI2.9.0-beta.1,Azure.IdentityandMicrosoft.Extensions.AI.OpenAI10.6.0, which the library never used. It referencesSystem.ClientModel1.10.0, the version those packages brought, to read the HTTP status of a provider'sClientResultException. Your app now adds its provider at the version it chooses: see Model providers. For Azure OpenAI that isAzure.AI.OpenAIandMicrosoft.Extensions.AI.OpenAI, forAsIChatClient(), plusAzure.IdentityforDefaultAzureCredential.- With the Azure Responses API, keep
OpenAIat 2.10, withMicrosoft.Extensions.AI.OpenAIpinned to 10.6.0. With 2.11 or later,GetResponsesClient()fromAzure.AI.OpenAI2.9.0-beta.1 throws when it is called:MissingMethodException: Method not found: 'Void OpenAI.Responses.ResponsesClient..ctor(System.ClientModel.Primitives.ClientPipeline, OpenAI.OpenAIClientOptions)'. - Chat Completions needs no pin: with
OpenAI2.14 its client is built where the Responses one throws.
- With the Azure Responses API, keep
- Breaking — MentorAgent: the built-in history keeps tool calls and their results (BUG-121, S2). Up to 1.0.0-rc.14 it was trimmed by
MessageCountingChatReducer, which drops every message with a function call or result. From the next turn on, the model no longer saw the data a tool had read, and answered a follow-up by guessing or by calling the tool again. The default is nowMentorChatReducer. It counts every message againstMaxSessionMessages, tool calls and results included. It trims whole turns, oldest first, and never sends a result without the call that produced it. In a lab run of 84 turns, the turns answered correctly went from 85% to 95%, and tokens grew by about 9%. With the sameMaxSessionMessages, a session holds fewer turns.- Migration. Nothing to change. For the 1.0.0-rc.14 behavior, set
options.ChatReducer = new MessageCountingChatReducer(50), which is experimental (MEAI001).
- Migration. Nothing to change. For the 1.0.0-rc.14 behavior, set
- Breaking — MentorAgent: the options are validated when the host starts (
ValidateOnStart) (BUG-123, S4). An ASP.NET Core or worker host with an invalid configuration now stops at start, with the reason. Examples: noChatClientorAgent, an emptyScanAssemblies, or bothChatHistoryProviderandChatHistoryProviderFactory. Up to 1.0.0-rc.14 it started, listened and failed on the first request, although the READMEs said that it threw at startup. A MAUI app has no such start: it still gets the error the first time it uses MentorAgent.- Migration. A host that started with an invalid configuration fixes it.
- Breaking — MentorAgent: a class listed in
[TeamMember(Tools = ...)]is the toolbox of that member only (BUG-125, S3). Up to 1.0.0-rc.14 the scan also made its methods actions of the coordinator, published on/mcpand on the A2A card, because the class is registered in dependency injection. A[MentorSkill]class keeps its coordinator tools, because of its role as a skill. Member tools are now found by the same rules as every other action: public instance methods declared on the class itself, with[MentorAction]or a non-empty[Description]. A member no longer gets inherited or static methods, or a method with an empty[Description](BUG-126, S3). See Level 3: teams.- Migration. When MentorAgent finds your actions, an Information line names each class taken from the coordinator, the members that list it and its methods (
… is listed in the Tools of …). An action that the coordinator must offer too goes on a class not listed inTools. A member tool inherited from a base class must be declared on the listed class.
- Migration. When MentorAgent finds your actions, an Information line names each class taken from the coordinator, the members that list it and its methods (
- Breaking — MentorAgent.Server:
POST /mentor/approveanswers404when no turn waits for the answer any more: it was answered already, the turn was stopped, or the connection that raised it has closed. Up to 1.0.0-rc.14 every call got200, so a client could not tell an approval that ran from one that reached nothing.- Migration. A client that treats any answer other than 2xx as an error should treat
404as "nothing left to answer", and close its dialog. The WebAssembly client of MentorAgent.Blazor already does. See Any front end.
- Migration. A client that treats any answer other than 2xx as an error should treat
- Breaking — MentorAgent:
IMentorStateService.OnApprovalResponseis no longer raised for an answer that found no turn waiting: after Stop, after the connection or the circuit closed, or a second time (BUG-129). Up to 1.0.0-rc.14 it was, in process and in the WebAssembly client. So a custom confirmation dialog that closed only on this event closed in those cases too. Now it stays open.- Migration. Close a custom dialog when its buttons are clicked and on
OnBusyChanged(false), as the README's Custom HITL confirmation dialog example does. KeepOnApprovalResponsefor an audit trail of the decisions that were carried out.
- Migration. Close a custom dialog when its buttons are clicked and on
- Breaking — MentorAgent: on the hub, on
/mentor/chatand over A2A, MentorAgent takes the caller from the request: the user of the hub connection, orHttpContext.User(BUG-131). It asks the host'sAuthenticationStateProvideronly where no MentorAgent transport runs, such as a Blazor circuit. If your own provider added claims or roles to the user, they are no longer seen there.- Migration. Add them with an
IClaimsTransformation. ASP.NET Core applies it toHttpContext.User, and so to the user of the hub connection too.
- Migration. Add them with an
- Breaking — MentorAgent: memory and
RateLimitPerUseridentify a signed-in user byNameIdentifier, as before. Otherwise they usesub,oidor the name, with the claim in the key (sub:…,name:…), like the owner checks (BUG-142). A user known by name alone in 1.0.0-rc.14, as with Windows authentication, gets a new key.- Migration. In your memory store, rename those users' keys from
<name>toname:<name>.
- Migration. In your memory store, rename those users' keys from
- MentorAgent: README:
ReadOnlyandIsReadOnlyActionsay whatreadOnlyHintmeans on/mcp. Some MCP clients skip their own confirmation for such a tool, so a write declared read-only by mistake runs from them with nobody asked. The MentorAgent.Server README says the same in its MCP section. - MentorAgent: README:
OnActionExecutingcarries the text shown to the user, not the tool name. That text is the action'sDescription, or a label for a routing, a team or a hosted tool.OnActionCompletedcarries the tool name, andOnActionFailedthe tool name and the error. The MentorAgent.Server (ActionExecuting) and MentorAgent.Blazor READMEs say the same. - MentorAgent: README: a tool result is drawn as a card by its shape, not by its .NET type: an object with a non-empty string
kind, or an array of them. Your own records with akindproperty are drawn as cards too, and the README says how to avoid it. - MentorAgent: README: the banner of the five READMEs says that this is a release candidate for 1.0.0, not a public preview. The Extensibility table lists
IMentorAgentSource,IMentorQueryEmbedding,ClassifierChatClientandSkillSources/SkillFilter. Its row on history providers points toChatHistoryProviderFactory:ChatHistoryProvideris one instance shared by every user. - MentorAgent: the XML documentation of
MentorOptionsmatches the code.RequiresApprovalgets tool names: MCP tools without a prefix, never a remote agent.DashboardRoleguards the metrics endpoint only. Routing followsRoutingStrategy.AgentCardUrlis a base URL (agent-card.json). There is noITextSearchwrapper.RagSystemPromptTemplateis in English. - MentorAgent.Server: the A2A comments say that a task runs as the user of the request, and that
RateLimitPerUserdoes not hold an anonymous caller across tasks.
Removed
Section titled “Removed”- Breaking — MentorAgent: the
MENTOR001build check (buildTransitive/MentorAgent.targets) and itsMentorAgentSkipOpenAIVersionCheckswitch (BUG-120). They stopped every build that resolvedOpenAI2.11 or later, including a project on the current Agent Framework that never callsGetResponsesClient().
- MentorAgent: README: the Requirements table lists the package's real references. Its Blazor row no longer contradicts the server package: any ASP.NET Core app works with MentorAgent.Server. The
MENTOR001section is replaced by Provider package versions, which says which call fails and on which versions. - MentorAgent: BUG-122 (S3): the warm-up (
WarmUpAtStartup) is now always registered, and decided on the real options when the host starts. It was registered only if the snapshot taken at registration asked for it, and that snapshot swallowed any exception from theAddMentorAgentcallback. So a callback that failed beforeWarmUpAtStartup = truelost the warm-up without a word. Such an exception is now logged as a warning at start, naming the options decided at registration. - MentorAgent: the warm-up starts on
ApplicationStarted, after a web host is listening, as documented. It started insideStartAsync, before the other hosted services. - MentorAgent: BUG-124 (S3): README, When the options are read and checked. The
AddMentorAgentcallback runs twice.EnableObservability,ObservabilitySourceName,McpServerEnabled,A2AServerEnabled,AppName,AppDescriptionandAgentCardare read at registration, so aConfigure<MentorOptions>registered later does not reach them. The MentorAgent.Server README and the XML documentation ofAddMentorAgenthave the same note. - MentorAgent: BUG-125: a team member is told "These tools are read-only." only when all its tools are declared read-only (
ReadOnly = trueorIsReadOnlyAction) and none asks for confirmation. Every member was told so, whatever its tools did. - MentorAgent: BUG-127 (S4): README, Which methods become tools. Inherited and static methods are not found. A method with
[Description]alone has no roles and no confirmation, so with tool filtering it can be sent when a message matches nothing. The MentorAgent.Server README says the same. - MentorAgent.Server: BUG-128 (S2): a confirmation outlived the connection that raised it. When the owner's hub connection closed, the hub forgot who had raised it, but the turn kept waiting. Anybody who knew the action id could approve it with
POST /mentor/approve, with no owner left to check, and the action ran. Now the end of a connection, or of a Blazor Server circuit, cancels the turn running in it, with its confirmation. - MentorAgent: BUG-129 (S3):
OnApprovalResponseis raised only when the answer reached the turn waiting for it. After Stop the request stayed pending, so a late Confirm raisedOnApprovalResponse(…, true)for an action that never ran. It happened in process, and in the WebAssembly client, which raised the event before sending the answer. Now the request leaves the pending list with its wait, and the WebAssembly client raises the event once the server has accepted the answer. - MentorAgent.Server: BUG-130 (S3): the owner of a connection is recognized without a
NameIdentifierclaim./mentor/approve,/mentor/canceland/mentor/sessionreadNameIdentifieralone, and so did the key that binds a session snapshot to its owner. With Windows authentication, or JwtBearer withMapInboundClaims = false, the owner was refused (403) its own confirmations, Stop and session. Now they readNameIdentifier, thensub, thenoid, then the identity's name, as the MCP rate limit does. A name never matches another user's identifier. Snapshots saved by 1.0.0-rc.14 for a user withNameIdentifierstill restore. - MentorAgent.Server: BUG-131 (S2): in a Blazor Web App, the hub,
/mentor/chatand A2A know who is calling. MentorAgent read the user from the host'sAuthenticationStateProvider. WithAddRazorComponents()that is Blazor's provider, which throws outside a circuit, and the server's bridge, registered withTryAdd, lost to it. EveryRequiredRolesaction was refused to everyone, with an error logged on each call, and memory andRateLimitPerUserfollowed a connection instead of a person. A Blazor Server app serving A2A without the hub had no bridge at all. Now each transport records its caller, and MentorAgent reads it first. The host's registration stays as it is, in any order ofAddRazorComponents()andAddMentorAgentServer(). When the server's own provider is registered, it also takes a circuit's user from Blazor (IHostEnvironmentAuthenticationStateProvider), as Blazor's own provider does. - MentorAgent: BUG-142 (S3): a signed-in user with only
suboroid, as with JwtBearer andMapInboundClaims = false, got a new identity for each session. So memory andRateLimitPerUserdid not follow the person. - MentorAgent.Server: BUG-132 (S2): README, CORS and the JWT example under Authentication show the whole pipeline:
UseCors,UseAuthentication,UseAuthorization, thenMap…. AProgram.csthat protected the hub without callingUseAuthentication()andUseAuthorization()itself got them from ASP.NET Core ahead ofUseCors. The browser's preflight for/mentor-hub/negotiatewas answered401without CORS headers, and a client on another origin never connected. The MentorAgent.Blazor README says the same under Stop and confirmations. See Secure the endpoints. - MentorAgent.Server: BUG-133 (S2): README, the complete React, Angular and Vue components send the hub's identity on approve, cancel and session: a
getTokenfunction, or cookies withcredentials: 'include'. They show an error when the server refuses an answer or a Stop. They sent a barefetch: with an authenticated hub the server answered401, the dialog closed and the turn stayed waiting, with nothing on screen. The Angular and Vue components also take an absolute hub URL (MENTOR_HUB_CONFIG,useMentorHub(hubUrl, getToken)), and send approve and cancel to the hub's origin. - MentorAgent.Server: BUG-134 (S3): README, the three components free the UI when the connection drops (
onreconnecting,onclose), and restore the saved conversation inonreconnected. The events table lists the three callbacks. A connection lost during a turn left the UI busy, even after the client reconnected: the new connection never sendsBusyChanged(false)for that turn. - MentorAgent.Server: BUG-136 (S2): README, the complete React component shows the assistant's replies. It added an empty bubble for every reply, because it reset the streaming buffer before React ran the update that read it. The three components no longer add an empty bubble when a segment closes before a confirmation.
- MentorAgent.Blazor: BUG-135 (S3): README, the client setup example has
using MentorAgent.Abstractions.Models;. Without it,MentorLanguageandMentorThemedid not compile (CS0103). - MentorAgent: BUG-137 (S3): README and XML documentation.
RequireConfirmation = falseturns off the confirmations of your actions, of the MCP servers you connect and ofRequiresApproval. It does not turn off the approvals that a hosted MCP server asks for (RequireApproval,AlwaysRequireApprovalTools). Both said that it disabled every confirmation dialog. - MentorAgent: BUG-138 (S3): README, voice input. Your server receives only the transcript, but some browsers, Chrome among them, send the audio to their maker's speech service. The README said that nothing left the page except the transcript. The MentorAgent.Blazor README says the same now.
- MentorAgent: BUG-143 (S3): with
HitlMode.Blocking, Confirm ran aRequiredRolesaction for a user who had lost the role while the banner waited, because the roles were read only before the banner. They are read again after the answer, as withNative, in specialists and teams too. - MentorAgent: BUG-144 (S3): after Cancel on a specialist's confirmation, reached through
route_to_specialist, the answer could report a problem that never happened. The coordinator got only the specialists' words, and a team withHandoffTohad just told it to carry out the action. The result of the delegation now starts withDECLINED BY THE USER, names the declined action and any that ran beside it, and carries the rule for a declined action. An approved team's result says that a declined confirmation is the user's decision. - MentorAgent: BUG-140 (S2): README, Blazor Web App.
@rendermode="InteractiveServer"on<ChatWidget />, the simplest setup for every Auto app, needs Interactivity location: Per page/component. With Global it throwsNotSupportedExceptiononce the layout runs in WebAssembly, and the WebAssembly template fails with HTTP 500 until its server addsAddInteractiveServerComponents()andAddInteractiveServerRenderMode(). The README also sent the CSS and JS links to anindex.htmlthat a Web App does not have: when prerendered, the widget writes them itself, otherwise they go inApp.razor. The MentorAgent.Blazor README says the same. See Blazor WebAssembly and Auto. - MentorAgent.Blazor: BUG-139 (S2): README, the client project of a Blazor Web App registers no
HttpClient, and without one the WebAssembly runtime did not start (CannotResolveService). The README said the template's was enough. The client examples now register one. The MentorAgent and MentorAgent.Server READMEs say the same. - MentorAgent.Blazor: BUG-145 (S2): on WebAssembly a relative
HubUrl, including the default/mentor-hub, never reached the server. The .NET SignalR client read it asfile:///mentor-hub, and the widget did not connect (TypeError: Failed to fetch). It is now resolved against the page's base address, as a browser does. - MentorAgent: BUG-146 (S2): a
[MentorTeam]stopped discussing after its first runs in a session. Every run shared one group chat manager, whose count of iterations was never reset. OnceMaxIterationswas spent, the team ran with no member speaking and returned nothing. Each run now gets its own manager. - MentorAgent: BUG-147 (S2): a tool that threw showed the exception's text in the chat, even with
OnExceptionset. A failure after the action, inOnToolResult, the cards or a screen update, reported an action that had run as failed, so the model could run it again. Now only the tool's own exception is a failure. WithOnExceptionset, the chat shows the app's message, or a localized "The action could not be completed.", never the exception's text. The model still gets the app's message, or else the exception's. AnOnToolResultthat throws withholds the result, as on the MCP server. A Stop during the action is not logged as a failure. The widget no longer shows the text of a send that failed. - MentorAgent: BUG-148 (S3): the gate's warnings named the user and carried a tool's whole exception. They now name a fingerprint (
caller#…, the same as the MCP audit line) and the exception's type. The whole exception is logged at Debug. - MentorAgent: BUG-149 (S3): with a
Languageother than English, the input box of a widget hosted on the server still read "Type a message...".MentorOptions.InputPlaceholderdefaulted to that text and hid the translation. It is nowstring?with no default, as in MentorAgent.Blazor, and an unset placeholder uses the localized text. In English the default text is now "Write a message...". - MentorAgent.Abstractions: BUG-150 (S2): the widget's stylesheet loaded the Sora and JetBrains Mono fonts from Google Fonts. That is a request to a third party on every page with the widget, refused under
default-src 'self'and missing offline. The two fonts now ship in the package, inwwwroot/fonts: variable WOFF2, Latin and Latin Extended, under the SIL Open Font License 1.1. The package is about 110 KB larger, and the stylesheet requests nothing from another origin. The avatar's size and the alignment of a table column moved from style attributes to the stylesheet, so with the default options the widget needs nostyle-src 'unsafe-inline'.ThemeDark or Minimal andPrimaryColorstill write a<style>block, andMentorDashboarduses style attributes. - MentorAgent: BUG-151 (S3): the error for a missing model suggested
new OllamaChatClient(...), a type that no package of the library brings, andAIProjectClientwithout its package. Each example now names its package, and Ollama goes through its OpenAI-compatible endpoint. - MentorAgent.Declarative: BUG-141 (S3): README, the install command lacked
--prerelease, whichdotnet add packageneeds while only prereleases exist. So did the twoMentorAgent.Servercommands in the MentorAgent README. The License sections point to the package'sLICENSE.
Known issues
Section titled “Known issues”- MentorAgent: BUG-074 (S3): with
MentorshipLevel.Proactive, the assistant can still offer next steps that the application does not have. On the Blazor Server sample it happened in 3 turns of 15 after the 1.0.0-rc.14 rule, and in 5 before. For example "add it to the cart", "the available deals", "plan a reorder". It stays open for 1.0.0 by the product owner's decision: the closing offers keep their wording. - MentorAgent: BUG-118 (S2) is closed for the hosts that turn on
RequireActionForChangeRequests, added in 1.0.0-rc.14. Without it, the model can still describe an action it never performed: "Stock aggiornato" with no tool called, or "Ecco la pagina Prodotti" with no navigation. With it, a complete request that the classifier does not recognize runs as it would without the option. - The rest of BUG-106 is closed for the hosts that turn on
RequireLookupForRecordQuestions, added in 1.0.0-rc.14. Without it, a catalog question can still be answered with an offer to look the value up. - MentorAgent: with
HitlMode.Native, a confirmation closed by Stop is closed only in memory. A snapshot saved in that state and restored still carries the open request, which can make the next turn fail as in BUG-116.
1.0.0-rc.14
Section titled “1.0.0-rc.14”Published on NuGet on 3 October 2026 (UTC): MentorAgent 1.0.0-rc.14 (external site).
- MentorAgent:
[MentorAction(ReadOnly = true)]andMentorOptions.IsReadOnlyActiondeclare the actions that only read.IsReadOnlyActiontakes a tool name, for[Description]methods. MentorAgent takes the host's word for it: the MCP server publishes such an action withreadOnlyHint. An action that needs confirmation is never read-only. - MentorAgent:
MentorOptions.RequireLookupForRecordQuestions, off by default. It closes the rest of BUG-106 for the hosts that turn it on. A classifier model reads each message. When it says that the message asks for a value of the application's records, the first model call must call a declared read-only action that the tool filter selected for that message. The model can also hand the request to a specialist (ChatToolMode.RequireAny).- Cost. One classifier call on each turn whose selection holds a declared read. It uses
ClassifierChatClientwhen set, withinSafetyCheckTimeout. On the ApiServer sample, the median latency grew by about one second. It grew by two to three seconds where a read now happens that did not happen before. - Failures. A classifier that fails, or answers anything else, leaves the turn as it would be without the option.
- Measured on the ApiServer sample, against the previous build. A product's price came from a read 19 times in 19, against 17 in 20. A stock level, 20 in 20 against 19 in 20. A product that does not exist was answered without an invented figure 10 times in 10, on both builds.
- Requirements.
EnableToolFiltering, anEmbeddingGeneratorand declared reads. A startup warning says when the option has no effect.
- Cost. One classifier call on each turn whose selection holds a declared read. It uses
- MentorAgent:
MentorOptions.RequireActionForChangeRequests, off by default (BUG-118). The classifier can say that a message asks to carry out one of the actions that need confirmation and that the tool filter selected for it. If the message also gives every input that action needs, the first model call must call one of those actions, or hand the request to a specialist or a team. So the confirmation banner comes before any sentence. When the message asks for a page, the first call must benavigate_to.- Incomplete requests are not forced. The classifier sees the required inputs of each action. A request is not forced, and the assistant may ask, when it leaves an input out ("Annulla l'ordine 1004" when
cancel_orderalso needs a reason). The same holds when it only describes the record ("the last order"), gives a name where the input is an ID, or needs the current value ("add 5 units"). - Only actions that show a banner are required: declared confirmation, with
RequireConfirmationon. WithHitlMode.Native, noAutoApprovalRulesrule is consulted for the required call. An action is never required when its input schema cannot be shown faithfully: a$ref, a combination of schemas, or no parameter marked required. - Pages. A page request is matched against the application's
[MentorPage]pages. A request from another agent is never required to navigate. - Cost. One classifier call per turn while the application has a page or the message selected such an action. With
RequireLookupForRecordQuestionson as well, it is the same call. - Measured before release on Azure gpt-4.1, three repetitions per message. With the two actions that a stock or price request usually selects, the classifier was right 207 times in 207 on 69 development messages. It was right 60 times in 60 on 20 messages written after the last change. With all nine actions of the ApiServer sample that need confirmation, it was right 204 times in 207 and 58 in 60: the misses were complete requests left unforced. An incomplete request or a read question was never labelled as an action.
- Measured live on the ApiServer sample (3 October), on the same build with the option off and on in turn. Asked "Imposta lo stock dell'iPad Air a 30" with the option off, the assistant said it was done without calling a tool 11 times in 25. With the option on, it showed the banner 25 times in 25, and 15 times in 15 on the final build. "Portami alla pagina prodotti" navigated 5 times in 10 with the option off, and 10 in 10 and 8 in 8 with it on. Requests missing a value were always asked about. Reads and greetings did not change.
- Requirements.
EnableToolFilteringand anEmbeddingGenerator. A startup warning says when the option has no effect, or covers page requests only.
- Incomplete requests are not forced. The classifier sees the required inputs of each action. A request is not forced, and the assistant may ask, when it leaves an input out ("Annulla l'ordine 1004" when
Changed
Section titled “Changed”- Breaking — MentorAgent:
MapMentorAgentMcp()no longer attaches theMentorAgentMcpCORS policy (BUG-108). MCP clients that are not browsers need none. For a browser-based client, callapp.UseCors()andMapMentorAgentMcp(configure: e => e.RequireCors("MentorAgentMcp")). A host that replaced that policy, as the 1.0.0-rc.13 README suggested, needs theconfigureline too. AMentorAgentMcppolicy that the host registers beforeAddMentorAgentis no longer replaced by the one that allows any origin. See MCP server. - Breaking — MentorAgent.Server: the body of
/mentor/sessionis opaque: see Security. Snapshots that clients saved before 1.0.0-rc.14 are refused with400, so save the conversation again. To restore after a restart, or on another instance, persist and share the Data Protection key ring. - MentorAgent: the classifier of
RequireLookupForRecordQuestionsruns at temperature 0, like the other classifiers: its wording was measured at that temperature. No difference was measured on the 1.0.0-rc.14 messages: 141 right in 141 at either temperature.RequireActionForChangeRequestsadds its labels to the question only when that option is on. The turn that answers an approval left open by Stop (BUG-116) is never forced. On that turn the stopped action is declared for its answer, and calling it again could satisfy the required call. - MentorAgent: tool filtering: when no action clears
ToolFilterMinScore, the three best-ranked actions that need no confirmation and no role are sent anyway, withinToolFilterMaxTools. An MCP tool qualifies only when its server marks itreadOnlyHint. This costs about 80 input tokens per model call on such turns, greetings included. GiveRequiresConfirmationto every action that changes data (BUG-106). - MentorAgent: the coordinator's prompt says to state record values only from a tool, the page data or the documents. The web search capability no longer mentions prices (BUG-106).
- MentorAgent:
RateLimitPerUser,OnToolResultand the top actions of the dashboard now cover MCPtools/call(BUG-107). MCP calls have their own allowance, separate from chat messages, counted perNameIdentifier,suboroidclaim. A caller with none of them is counted by remote address whenIHttpContextAccessoris registered. Otherwise all such callers share one allowance. Each call writes one Information log line with a fingerprint of the caller. - MentorAgent:
RefuseOutOfScoperefusals now count inGuardrailBlockCountand in thementoragent.guardrail_blockscounter. WithRefuseOutOfScopeand the safety check on, the scope check of hosted tools asks its own question on the turns where a hosted tool is about to be declared (BUG-105). - MentorAgent: compaction is not installed with
UseServiceManagedHistory: it had nothing to compact. A reset of the conversation writes one Information log line. - MentorAgent.Abstractions: the widget's "New conversation" button is disabled from the moment a message is sent until its reply ends, and while a confirmation is pending. A confirmation banner still open when the turn ends, after Stop, is dismissed.
- MentorAgent: A2A: a navigation, a UI action, a memory write or a skill no longer counts as grounding. So the request behind such a reply is sent once more, as for a reply that used no tool (BUG-106).
- MentorAgent: tool filtering: a message that matches no action carries the actions selected for the previous message. Only one message back, never actions that were carried themselves, and never an action that needs confirmation alone. Before, the answer to the assistant's own question ("Sì, procedi", or the reason it asked for) arrived without the action that the question was about. A new or restored conversation carries nothing.
- MentorAgent:
MentorshipLevel.Proactive: the assistant may offer a next step only when a tool of the current request, a page, a skill, a specialist or a team can carry it out. Otherwise it offers none. It never offers an export, an e-mail, a ticket, a reminder, an alert or parcel tracking (BUG-074). With tool filtering on, the prompt no longer presents the number of actions as the tools at hand.
MentorAgent: BUG-104 (S1): with
EnableCompactionon and a local history, the question of every turn that called a tool or ran a UI action was not stored. A local history is the built-in provider,ChatHistoryProviderFactoryorChatHistoryProvider. The Agent Framework's compaction marked the question as history in place (Agent Framework issuemicrosoft/agent-framework#8441), and stamped stored messages with its attribution. Now compaction works on copies. Questions lost on earlier versions cannot be recovered from their snapshots.MentorAgent: BUG-105 (S2):
RefuseOutOfScoperefused price questions about the application's own catalogue, 4 times in 4 measured. It judged messages against the cost rule of hosted tools, and saw the page names only. Now it asks its own question, which defaults to answering, and sees the pages' descriptions. The classifier's labels are read by position:Contains("OUT")matched "about" and "without".MentorAgent: BUG-106 (S2): a catalogue question that matched no action was sent with the core tools only. The reply invented a price range, or said that the catalogue did not have it. See Changed.
MentorAgent: BUG-107 (S2): MCP
tools/callskippedOnToolResult, the per-user rate limit and the tool metrics. A host that redacts results served them unredacted to MCP callers. Now a hook that throws withholds the result (isError).MentorAgent: BUG-108 (S2): the README's MCP steps, followed as written, answered 500 to every request on a pipeline without
app.UseCors(). See Changed.MentorAgent.Blazor: BUG-109 (S3): on WebAssembly, "New conversation" before the first message raised the Blazor error bar, because the hub was not connected yet.
BUG-110 (S3):
/mentor/sessionandRestoreSessionAsync:- a marker that was not an integer answered 500;
- a snapshot saved by a host that keeps its history another way was accepted, then failed every turn or restored an empty conversation. Another way means Responses instead of Chat Completions, or another history provider;
- a restored conversation that the service no longer knew failed every turn until a reset. Now, when the first turn after the restore fails because the provider does not know the conversation, a new one starts. A content filter, a missing deployment, a 429 or a 5xx keep the restored conversation.
On WebAssembly, the
NotSupportedExceptionpoints to/mentor/session.MentorAgent.Server: BUG-111 (S3): the package README now has the rule of BUG-102, keep the transcript in the session, with its recipe. It no longer says that a reset clears the history.
MentorAgent: BUG-114 (S3): over A2A, the judge of a second reply without data withheld policies that contain a number, such as a spending limit, as
NOT GROUNDED. And it passed "the catalogue does not list the price", when nobody had looked. Measured on Azure gpt-4.1 with fourteen replies, three times each: 25 right in 42 before, 42 in 42 now.MentorAgent: BUG-115 (S2): after the user declined a confirmation, the reply could invent why the action had not run. For example "the order is probably already being processed", for an order that was Pending. The localized text said "the operation was cancelled", even for a request to cancel an order, and the Native flow sent no instruction at all. Now both modes send the same structured result: nothing was checked or changed, and no other reason or record state is to be given. The
confirm.deniedtext no longer uses the verb for cancelling, in all 10 languages.MentorAgent: BUG-116 (S2): with
HitlMode.Native, Stop pressed while a confirmation waited made every later turn fail until "New conversation", withToolApprovalRequestContent found … no matching ToolApprovalResponseContent. Now the open request is answered, as not run, at the start of the next turn, with no extra model call. The fix also covers:- a second Stop, or a failure, before that answer is stored;
- a run that fails after the user confirmed: the action may have run, so it is reported with an unknown outcome and never run again;
- the cap on approval rounds.
On that turn the tool filter and the router decide on the new message. A snapshot saved in that state and restored, on the same host or elsewhere, still carries the open request.
MentorAgent: BUG-117 (S2): a provider error that arrived inside the stream, on a run that wrote no text, ended the turn with nothing on screen: no reply and no
Errorevent. Examples are a 429 on the Responses API, or a hosted tool that failed. Now it takes the path of a thrown provider error: the localized message,OnExceptionand the error metrics. Text written after the last tool call is kept, with no error under it. A sentence written before a tool call is not an answer. A model refusal reads as a block (guardrail.blocked), not as an error.
Security
Section titled “Security”- MentorAgent: BUG-103 (S1): with
McpCallerPrincipalset and roles in a claim type other thanClaimTypes.Role, a signed-in caller with no roles could list and call a role-gated action, once a caller with the role had asked first. Entra ID tokens carry such arolesclaim, and so does JwtBearer withMapInboundClaims = false. The tool list was cached per caller under a key built from theClaimTypes.Roleclaims, while the decision usedIsInRole. Now the list is decided on every request: the resolver is asked once, andClaimsPrincipal.IsInRoleis the only test, fortools/listandtools/callalike. - MentorAgent.Server: BUG-110 (S3):
GET /mentor/sessiongave the client the conversation in clear. An edited snapshot was restored as history, and another user's snapshot could be restored into one's own connection. Now the snapshot is protected with ASP.NET Core Data Protection, under a purpose that names the user of the connection. It is opaque, tamper-evident, and restorable only for that user. On a host without sign-in, every visitor is the same anonymous user.POSTchecks the owner before it reads the body.
Known issues
Section titled “Known issues”- MentorAgent: BUG-074 (S3): with
MentorshipLevel.Proactive, the assistant can still offer next steps that the application does not have. On the Blazor Server sample it happened in 3 turns of 15 after the new rule, and in 5 before. For example "add it to the cart", "the available deals", "plan a reorder". - MentorAgent: BUG-118 (S2) is closed for the hosts that turn on
RequireActionForChangeRequests: see Added. Without it, the model can still describe an action it never performed: "Stock aggiornato" with no tool called, or "Ecco la pagina Prodotti" with no navigation. With it, a complete request that the classifier does not recognize runs as without the option. - The rest of BUG-106 is closed for the hosts that turn on
RequireLookupForRecordQuestions: see Added. Without it, a catalogue question can still be answered with an offer to look the value up.
1.0.0-rc.13
Section titled “1.0.0-rc.13”Published on NuGet on 29 September 2026 (UTC): MentorAgent 1.0.0-rc.13 (external site).
CHANGELOG.md lists no known issues for this version, but BUG-074 is still open: see Known issues.
THIRD-PARTY-NOTICES.mdin every package, with the notices for the Feather (MIT) and Lucide (ISC) icons used by the components of MentorAgent.Abstractions. They were missing.
Changed
Section titled “Changed”- Tool filtering (
EnableToolFiltering): when every action aboveToolFilterMinScoreneeds confirmation, the three best-ranked actions that do not need it are now sent with them, withinToolFilterMaxTools. An action needs confirmation throughRequiresConfirmation, theRequiresApprovalpredicate, or an MCP server that requires approval. A single match that needs no confirmation is still sent alone. This is the structural fix for BUG-099, under Fixed. - The release notes of each package now come from
CHANGELOG.md, and every package contains that file.
Removed
Section titled “Removed”- Breaking:
MentorRemoteAgent.RequiredRoles. It was never enforced: setting it only logged a warning, and any user could reach the agent. To restrict a remote agent, authorize on the remote side: protect the peer's/a2aendpoint and give its actions roles. Or do not configure the agent on hosts whose users may not use it. See A2A server. - Breaking (dependencies): MentorAgent no longer depends on
Microsoft.Agents.AI.FoundryandAzure.AI.Projects, which the library never used. To keep usingAIProjectClientorFoundryEvals, add<PackageReference Include="Microsoft.Agents.AI.Foundry" Version="[1.17.0-preview.260804.1]" />to your project. A newer version needs OpenAI 2.11 or later, and the build stops withMENTOR001: see Provider package versions.
- BUG-099 (S1): with
EnableToolFilteringon, a read question could reach the model with a single write action, and a question about stock set the stock to 0. 1.0.0-rc.12 mitigated it with confirmation on the actions that change data. Now an action that needs confirmation never reaches the model alone. - BUG-101 (S3): an MCP
tools/callcould name a tool that the MCP server does not list: an action that needs confirmation, which the server withholds, or a name that never existed. The call was logged as an unhandled exception with a stack trace, and the caller got "An error occurred invoking '…'". Now the server answers "Unknown tool: '…'" withisError, the same for both kinds of name, and logs nothing as an error. - BUG-102 (S3): a custom history provider that kept the transcript in a field carried the previous conversation into a new one. This happened after
ResetSessionAsync, the widget's reset button or the hub'sResetSession, because the provider lives as long as the circuit or connection. The README now says to keep the transcript in the session, with a recipe that usesProviderSessionState<T>. The built-in provider was not affected.
1.0.0-rc.12
Section titled “1.0.0-rc.12”Published on NuGet on 23 September 2026 (UTC): MentorAgent 1.0.0-rc.12 (external site).
- MentorAgent:
MentorOptions.ToolFilterMinTools, default0. With0, tool selection stays exactly as in 1.0.0-rc.11. WithEnableToolFilteringon, once one action scores aboveToolFilterMinScore, at least this many of the best-ranked actions are sent, whatever their score. It is opt-in because it can help or hurt. A minimum can stop a single write action from being offered for a read question. But it can also add a candidate that the model then wrongly prefers (see BUG-099 under Known issues).
MentorAgent: BUG-100 (S2): an action that needs confirmation (
RequiresConfirmation, or theRequiresApprovalpredicate) could be called during an A2A task. It then held the task open until the calling agent gave up, because both the blocking and the native approval path waited for an answer nobody could give. Such an action is now refused at once in both HITL modes, and the model is told that it has to be performed from the application itself. The A2A agent card already left these actions out.MentorAgent: BUG-098 (S2): on a turn served without a Blazor circuit, such as an A2A task on a Blazor Server host, an action with
NavigateToran. Then the automatic navigation threw while readingNavigationManager.Uri, and the action was reported as failed. So the model ran it again, and the caller was told that it had not happened. Now:- a turn from another agent does not navigate automatically;
- a page URL that cannot be read no longer turns a completed action into a failure.
An exception thrown by your own
OnToolResulthook still reports an action that already ran as failed, so make sure that the hook does not throw.MentorAgent: BUG-097 (S3): on a Blazor Server host with memory or
RateLimitPerUseron, every A2A task logged a warning that theAuthenticationStateProviderthrew. A role-gated tool that the model reached for was logged as an Error with a stack trace, and answered "Error during authorization check". The provider is still asked, so a headless host keeps the identity of an authenticated peer. When the identity cannot be read on a task from another agent, the task is treated as anonymous (logged at Debug), and a gated tool is refused as for any anonymous caller.
Known issues
Section titled “Known issues”- MentorAgent: BUG-099 (S1, mitigated; present since tool filtering was introduced): with
EnableToolFilteringon (off by default), the filter sends only the actions whose score is aboveToolFilterMinScore. So a read question can end up with a single write action above the line. It was observed as a question about stock levels, answered by calling the stock-update action with a quantity of 0. What to do: mark every action that changes data with[MentorAction(RequiresConfirmation = true)]. A person is then asked first, and over A2A the action is refused (BUG-100).ToolFilterMinToolsis an additional, opt-in lever. A structural fix (declaring actions read-only) is planned for a later version. Fixed in 1.0.0-rc.13 in a different way: actions that need no confirmation are now sent along with the ones that do. - MentorAgent: BUG-074 (S3): with
MentorshipLevel.Proactive, the assistant can offer next steps the application does not have.
1.0.0-rc.11
Section titled “1.0.0-rc.11”Published on NuGet on 23 September 2026 (UTC): MentorAgent 1.0.0-rc.11 (external site).
- MentorAgent:
MentorOptions.SafetyCheckTimeoutandMentorOptions.SafetyCheckFailure(BUG-084).SafetyCheckTimeoutdefaults to 15 seconds; zero or negative means no limit, and Stop still cancels the check.SafetyCheckFailureisMentorSafetyCheckFailure.Allow, the default and the previous behavior, orBlock.Blockrefuses the message with a localized "can't check it right now, try again", or withholds the reply. Both options apply to the input and the output check, built-in or custom. A timeout logs one line naming what to change. Nothing changes for a host that sets neither option.
Changed
Section titled “Changed”- MentorAgent:
MapMentorAgentMcp()andMapMentorAgentA2A()now take their default path fromMcpServerPathandA2AServerPath: thepathparameter is nowstring? path = null. Before, nothing read those options (BUG-091, S3). If you set either option to a value other than the default and map the endpoint without an explicit path, the endpoint now moves to the configured path. - MentorAgent: the output safety check now runs on
ClassifierChatClient, like the input check, and is metered under the model id of that client (BUG-096, S3).
MentorAgent: BUG-082 (S2): on a host with remote A2A agents, a local specialist's answer could reach the user presented as the remote agent's, with no remote call made. Every delegated answer now states its source to the coordinator:
- a local specialist, with a note that no remote agent was contacted, and an instruction to call once more with
specialistset if the user meant one; - the remote agent ("that system's data, not this application's");
- a named remote agent that never took part ("NOT X'S ANSWER", plus a warning for the operator).
Every configured peer counts as remote, including one whose card could not be fetched when the session was built, and the router's list marks remote entries. Hosts without remote agents, and turns that arrived over A2A, are unchanged.
- a local specialist, with a note that no remote agent was contacted, and an instruction to call once more with
MentorAgent: BUG-083 (S2, present in 1.0.0-rc.10): a Blazor Server host could not answer another agent. Every A2A task it received completed with an empty message: a turn served over A2A has no circuit, and reading
NavigationManager.Urithrew. Now the read is guarded, and the A2A handler fails a task that produced no text, instead of completing it empty. Headless hosts (MentorAgent.Server) were not affected.MentorAgent: BUG-084 (S2): the safety checks had a fixed limit of 15 seconds, and a check that failed or timed out let the message or the reply through. So on a slow model the input check was skipped on every message. Stop could not interrupt the input check. A custom
InputGuardrailthat honored its cancellation token threw out ofSendMessageAsync, and the widget stayed busy for good. See the new options above. An error now produces a single stack trace per turn.MentorAgent.Blazor: BUG-086 (S2): on WebAssembly, answering a confirmation and pressing Stop used the host's
HttpClientwith a relative URL and no token, so the owner check refused the requests of a signed-in user. They now go to the hub's origin with the hub's bearer token (AccessTokenProvider).MentorAgent: BUG-087 (S2):
ConfigureChatClientPipelineis now built with the host's services. The documentedb => b.UseLogging()made every coordinator build fail.MentorAgent.Abstractions: BUG-088 (S2): the buttons of a
MentorCardViewrendered inside aChatWidget.CardTemplatedid nothing. They now reach the widget's action dispatcher.BUG-089 (S2): UI actions registered by a hub client (WebAssembly, React, MAUI) now keep their parameter hint, and the WebAssembly page context generates the same hints as Blazor Server.
MentorAgent: BUG-090 (S3):
navigate_tono longer waits forSignalReadyon hub, SSE and A2A turns, where no page can send it. Each navigation to a page withHasUIActionsused to cost the fullReadyTimeoutand a warning.MentorAgent: BUG-092 (S2):
[MentorAction(ProactiveHint = ...)]was stored and never read. It now reaches the model, appended to the tool description as "Guidance: ...". Semantic tool filtering does not use it.MentorAgent: BUG-093 (S2):
SkillsRefreshIntervalhad no effect, because every session built its own cache. The composed skill sources are now cached once per process.MentorAgent.Abstractions: BUG-095 (S2): a
ChatInputcomposed withoutChatWidgetthrew on the first message (an unguarded JavaScript call), which ended the Blazor Server circuit.Documentation: corrections across the five READMEs, among them:
- attribute examples that did not compile;
- SignalR enums arriving as numbers;
- the text on the anonymous identity and the rate limit (per session since 1.0.0-rc.5);
- how to protect
/mcpand/a2a, and what to expect from them.
The XML docs and the server's startup warning now match the
PerSessiondefault.
Security
Section titled “Security”- MentorAgent.Declarative: BUG-094 (S2):
webSearch,codeInterpreter,fileSearchandmcptool entries in a YAML definition created provider-hosted tools outside MentorAgent's gate, against the package's guarantee that a definition file cannot add a capability the application does not already have. They are now removed with a warning, and onlykind: functionentries are kept. Breaking: a definition that relied on those entries loses them. Provider-hosted tools are configured by the host application (MentorOptions.HostedTools), not by a definition file.
Known issues
Section titled “Known issues”- MentorAgent: BUG-074 (S3): with
MentorshipLevel.Proactive, the assistant can offer next steps the application does not have.
1.0.0-rc.10
Section titled “1.0.0-rc.10”Published on NuGet on 19 September 2026 (UTC): MentorAgent 1.0.0-rc.10 (external site).
- MentorAgent: a MentorAgent A2A caller now sends its own name for the peer as A2A message metadata (
mentoragent.addressedAs), and a MentorAgent peer reads it into the turn's context, so it knows that the name refers to itself. The value comes from another machine and goes into a prompt, so only a single token of letters, digits,-,_and.(at most 64 characters) is accepted. Anything else is dropped whole.
MentorAgent: BUG-081 (S2): a turn served over A2A could state figures no tool had returned. Two changes:
- The A2A turn notice is now a procedure: call the tool first; take every number, name, date or status from a tool result of this turn; if no tool has it, reply only that the application cannot provide it.
- As a structural backstop, when an A2A turn ends without the coordinator calling any tool, the reply is discarded. The request runs once more, with a tool call required on the first model call of that attempt. If that attempt also ends without a tool call, the classifier model is asked whether the reply states a value from the application's live records. Unless the answer is a clear no, the caller receives "NOT GROUNDED: ..." instead of the value.
There are never more than two attempts, and only A2A requests without a tool call pay for the extra one. A reply without a tool call that states no data is returned unchanged.
MentorAgent: BUG-081 (second part): a peer did not know that the caller's name for it, carried inside the request, meant itself, and answered that it had no access to that system. The notice now says so, backed by the
mentoragent.addressedAsmetadata above.
Known issues
Section titled “Known issues”- MentorAgent: BUG-074 (S3): with
MentorshipLevel.Proactive, the assistant can offer next steps the application does not have.
1.0.0-rc.9
Section titled “1.0.0-rc.9”Published on NuGet on 19 September 2026 (UTC): MentorAgent 1.0.0-rc.9 (external site).
- MentorAgent: BUG-080 (S2): two hosts that list each other as remote A2A agents could delegate one request back and forth without end, each hop a paid turn. The cause:
route_to_specialistadds an internal[Specialist requested: NAME]marker for the local router (since 1.0.0-rc.8). The marker crossed the wire, and the peer read it as its own instruction. The A2A client now strips it, on both the streaming and the non-streaming path. In addition, a turn that arrived over A2A is no longer offered the host's remote agents. They are absent from the coordinator's prompt, the router's prompt and the description ofroute_to_specialist, and one Debug line names what was withheld. The host's own specialists, declarative agents, teams and tools still serve the request.
Known issues
Section titled “Known issues”- MentorAgent: chaining A → B → C through a MentorAgent host is not supported in 1.0: a turn that arrives over A2A is not offered the host's own remote agents.
- MentorAgent: BUG-073 (residual): on a Chat Completions host, the cold first turn of a process can still narrate a handoff without calling
route_to_specialist. The fix in 1.0.0-rc.7 lowers the rate; it does not remove the behavior. - MentorAgent: BUG-074 (S3): with
MentorshipLevel.Proactive, the assistant can offer next steps the application does not have.
1.0.0-rc.8
Section titled “1.0.0-rc.8”Published on NuGet on 18 September 2026 (UTC): MentorAgent 1.0.0-rc.8 (external site).
- MentorAgent:
route_to_specialist, the coordinator's delegation tool, takes an optional second argument,specialist, naming the specialist to use when the user named one or one clearly fits. When it is omitted, the router chooses. Additive.
Changed
Section titled “Changed”- MentorAgent: a turn that arrives over A2A now tells the model that no human is present: carry the request out and reply with the result, with no follow-up questions, offers or announcements in place of action. Hub and SSE turns are unchanged. (Tightened in 1.0.0-rc.10, BUG-081.)
- MentorAgent: the router at the entry of the handoff workflow now has a short prompt of its own (about 400 tokens) instead of the coordinator's entire prompt, which was paid a second time on every delegated turn (part of BUG-076).
MentorAgent: BUG-078 (S2): the A2A server had never completed a round trip with any client. On the server side:
- the agent card advertised the protocol binding
HTTP+JSONwhileMapMentorAgentA2Amaps the SDK's JSON-RPC endpoint (it now saysJSONRPC); - the handler changed a task's status without submitting the task first;
- it disposed a DI scope in a way that threw after the turn had already run and been billed.
On the client side,
A2AChatClientread only Message events inside the handoff workflow. So it could not read the answer of a MentorAgent server, which arrives as the final status update of a task. It now reads a final Task or StatusUpdate too, and skips Working statuses.- the agent card advertised the protocol binding
MentorAgent: BUG-076 (S2): the router was told to call
route_to_specialist, the tool it runs inside, so it narrated a handoff instead of performing one, and the narration was returned as the specialist's answer. The router now has a router's prompt: who the specialists are; call exactly one handoff function; never answer; never say you are forwarding. The tool returns what the specialists said, as text. When only the router spoke, the result is "NOT DELEGATED ..." and the operator gets a warning. When a specialist threw an exception, it is reported as "DELEGATION FAILED", with the error in the warning.MentorAgent: BUG-077 (S3): model calls made under the coordinator (the router, Level-2 specialists, Level-3 team members and agents built by an
IMentorAgentSource) ran on the raw host client and were never metered. They now run inside the metering wrapper. Azure's first streamed chunk carries an empty (not null) model id. So the wrapper now takes the first id that is not empty, and falls back to the client's own deployment. This way, aClassifierChatClienton its own deployment gets its own dashboard row.MentorAgent: BUG-079 (S3): specialists had no rule against inventing data. Generated specialist prompts and the prompt of every team member now carry a grounding rule: state only facts a tool returned; if nothing provides what is asked, say so, and never estimate or invent a number, name, date or status. Custom
[MentorAgent(Instructions = ...)]prompts are left exactly as written: a custom prompt replaces the rule too, so add it to your own instructions.MentorAgent: BUG-075 (S3), second pass: on hosts with memory on, the safety classifier is now told that the secrets its rules protect are the system's, and that what users tell the assistant about themselves is theirs to give and to ask back. Asking the assistant to remember a private code, and asking for it back, are no longer classified unsafe. The model itself may still decline to keep something its user calls private, and says why.
Known issues
Section titled “Known issues”- MentorAgent: BUG-074 (S3): with
MentorshipLevel.Proactive, the assistant can offer next steps the application does not have.
1.0.0-rc.7
Section titled “1.0.0-rc.7”Published on NuGet on 16 September 2026 (UTC): MentorAgent 1.0.0-rc.7 (external site).
- MentorAgent: BUG-073 (S2): the coordinator was told it could delegate to its specialists but never how:
route_to_specialistappeared nowhere in the prompt, and its description named no agent. So the model announced handoffs and ended the turn without calling anything. The capabilities block now says how to delegate and forbids announcing a handoff that was not performed, and the tool's description names every specialist it reaches: declared with attributes, supplied by a source, and remote. - MentorAgent: BUG-075 (S3): asking the assistant to remember a personal fact was classified unsafe on a host with memory on. Remembering what the user asks to keep is now named to the classifier as a configured capability (completed in 1.0.0-rc.8).
- MentorAgent: BUG-072 (S3): a signed-in user whose
AuthenticationStateProviderthrew was silently keyed as anonymous, and since 1.0.0-rc.5 as a different anonymous in every circuit. The fallback that fails closed stays; it is now logged once per session, without a stack trace per visitor. - MentorAgent: BUG-068 (addendum): the "Remote agent 'X' connected" line was still logged at Information for every circuit. It now follows the once-per-process rule.
Known issues
Section titled “Known issues”- MentorAgent: BUG-074 (S3): with
MentorshipLevel.Proactive, the assistant can still offer actions the application does not have. The rule is in the prompt; a structural fix is left open as a product decision.
1.0.0-rc.6
Section titled “1.0.0-rc.6”Published on NuGet on 14 September 2026 (UTC): MentorAgent 1.0.0-rc.6 (external site).
- MentorAgent: BUG-068 (S3): the configuration summary was not written once per process, as the notes of 1.0.0-rc.5 stated. A second browser circuit printed the whole summary again, at Information: the skills catalog, the external agents, the hosted image model, the note on the Azure image header, the hosted MCP server, the list of hosted tools and the declarative handoff. It is now written once per process; later builds log it at Debug instead of dropping it. Degradation warnings stay per session.
- MentorAgent: BUG-069 (S2): an agent supplied by an
IMentorAgentSource(a declarative YAML specialist, or one of the host's own) joined the handoff graph but was never named in the coordinator's instructions, so the assistant said it did not exist. Agents supplied by a source are now listed with their descriptions, beside the ones declared with attributes. - MentorAgent: BUG-070 (S4): every skill on the published A2A agent card carried a flattened name (for example
Getallordersforanalysis). Skill names are now readable. - MentorAgent: BUG-071 (S4): a turn in which the input safety check was the first to fail printed two stack traces instead of one.
1.0.0-rc.5
Section titled “1.0.0-rc.5”Published on NuGet on 13 September 2026 (UTC): MentorAgent 1.0.0-rc.5 (external site).
- MentorAgent:
MentorOptions.ClassifierChatClient: the client MentorAgent uses for its own one-word decisions (input safety, hosted-tool scope, extraction of facts after the turn). Point it at a small deployment, because those calls sit in front of the reply. It defaults toChatClientand is metered under its own model id. - MentorAgent:
MentorOptions.AnonymousIdentity(MentorAnonymousIdentity.PerSessionby default, orShared): who a signed-out visitor is, for memory and for the rate-limit counter. See Changed. - MentorAgent:
MentorOptions.RefuseOutOfScope(off by default): refuse a message that is not about this application, using the scope verdict the classifier already produces. It is free whenEnableSafetyCheckis on, because both questions travel in one call. - MentorAgent:
MentorOptions.WarmUpAtStartup(off by default): build one coordinator when the application starts, so the first visitor does not pay for the catalog embeddings, the shared MCP sessions and the remote agent cards. - MentorAgent:
MentorMcpServer.Shared(bool?, defaultnull): one connection per process, or one per session. When it is unset, a server reached overServerUrlis shared and a server started fromCommandis not, because a local child process can hold state for the person who started it. - MentorAgent:
MapMentorAgentMcp(path, configure)andMapMentorAgentA2A(path, configure)take an optionalAction<IEndpointConventionBuilder>, so the host can applyRequireAuthorization()or other conventions to/mcpand/a2a: see Secure the endpoints. Both previously discarded their convention builders. - MentorAgent:
IMentorQueryEmbedding: the embedding of the current message, computed once per turn. Inject it into yourIMentorRagSourceinstead of embedding the query a second time.
Changed
Section titled “Changed”MentorAgent: Breaking: signed-out visitors are now isolated per session by default (
AnonymousIdentity = PerSession). Before, every unauthenticated session shared the literal keyanonymous, so one visitor's facts were recalled for the next, and one visitor could spend everybody's rate-limit allowance. Single-user hosts, such as MAUI, desktop and kiosk apps, may want the old behavior: there it is what makes memory survive a restart. They must setAnonymousIdentity = MentorAnonymousIdentity.Shared. A warning is logged when a host opts back into the shared bucket and a second session reaches it.MentorAgent: faster turns and lower cost per visitor:
- Routing, tool filtering and memory relevance share one embedding per text per turn, instead of embedding the same sentence two to four times.
- The tool catalog and the routing exemplars are embedded once per process instead of once per browser circuit.
- The input safety check and the hosted-tool scope check ask both questions in one classifier call.
- The composer is handed back when the answer is complete, not after the extraction of facts that follows the turn.
- MCP sessions and A2A agent cards are shared per process, with a failure backoff for the card cache.
The measured time to the first character fell from 2.6–3.0 s to 1.6–2.0 s on the same question.
MentorAgent: RAG citation chips show only the documents the answer actually cited: documents are numbered in the prompt, and the model is asked to cite them. If it cites none, no chips are shown.
MentorAgent:
MentorshipLevel.Proactiveasks for one sentence before acting instead of a plan, and may offer only next steps the application can actually perform.MentorAgent: the A2A agent card now publishes the application's ungated actions as skills, its input and output modes and its streaming capability. Before, it carried only a name and a description.
MentorAgent: one provider failure now produces one stack trace instead of one per component that met it, and the coordinator's configuration summary is logged once per process instead of once per session (completed in 1.0.0-rc.6 and 1.0.0-rc.7, BUG-068).
- MentorAgent: BUG-062 (S3): text written before a tool call was glued to the text after it, and a Markdown table opening the second part stopped rendering as a table.
- MentorAgent: BUG-063 (S3): in
HitlMode.Native, a user without the required role was shown the confirmation box and refused only after approving it. The role gate now runs first, as it always did in Blocking mode. - MentorAgent: BUG-065 (S4): the RAG "wrong scale" warning fired for thresholds that were on the source's own scale, and did so once per visitor.
- MentorAgent: BUG-066 (S3): the hosted-tool scope classifier was built on the raw
ChatClient, so its billed calls appeared in no dashboard. - MentorAgent: BUG-067 (S3): the safety classifier was never told what the application is equipped with (for example an MCP filesystem server or image input), and refused legitimate messages. It is now told, and a refused message is logged by fingerprint rather than by its text.
Security
Section titled “Security”- MentorAgent: BUG-064 (S1): two anonymous visitors of the same site shared one memory. Anonymous visitors are now isolated per session by default (see Changed).
1.0.0-rc.4
Section titled “1.0.0-rc.4”Published on NuGet on 9 September 2026 (UTC): MentorAgent 1.0.0-rc.4 (external site).
- MentorAgent: BUG-061 (S3): the classifier of provider errors recognized an unreachable image URL only in the Chat Completions wording. So on the Responses API, the client that hosted tools require, the user saw the generic error instead of the specific message. The Responses API wording is now recognized too. It is keyed on the pair "error while downloading file" and "parameter: url", so a failure on a file supplied by the operator, such as a vector-store document, still falls through to the generic message.
1.0.0-rc.3
Section titled “1.0.0-rc.3”Published on NuGet on 4 September 2026 (UTC): MentorAgent 1.0.0-rc.3 (external site).
- MentorAgent.Blazor:
MentorAgentBlazorOptions.AccessTokenProvidersupplies the bearer token for the hub connection, read on every connect and reconnect. It is the WebAssembly equivalent of the JavaScript client'saccessTokenFactory. Returnnullwhile nobody is signed in; the connection then behaves as before. The hub connection is a singleton, opened on the first render of the widget, and the token is read only on connect and reconnect. So a sign-in that happens later takes effect on the next reload or reconnect: restore a persisted token before the host runs. - MentorAgent.Blazor:
MentorAgentBlazorOptions.ConfigureConnection, an escape hatch ontoHttpConnectionOptionsfor anything the named options do not cover (a custom header, a transport restriction, cookies,UseDefaultCredentials). - MentorAgent.Server:
MapMentorAgentServer(configureTransports: e => e.RequireAuthorization())applies an endpoint convention to the hub and to both/mentor/chatendpoints. It is optional: omitting it changes nothing. - MentorAgent.Server: a one-line startup warning when the SSE endpoint ends up with no authorization metadata while memory is on, and a README section listing every endpoint, what an anonymous caller can do with it and how to protect it. See Secure the endpoints.
- MentorAgent.Server:
GET /mentor/session?connectionId=...returns the session snapshot of the connection (204 when there is nothing to save, 404 for an unknown connection), andPOST /mentor/session?connectionId=...restores one (400 for a snapshot that is not MentorAgent's, without touching the live conversation). This gives WebAssembly, React, Vue and MAUI clients a way to survive a reconnect, which starts a new conversation. Both verbs are restricted to the owner of the connection (see Security). - MentorAgent:
MentorOptions.ChatHistoryProviderFactory(Func<IServiceProvider, ChatHistoryProvider>), invoked once per coordinator with the service provider of that coordinator, so a provider can key its storage by whatever identifies the caller. Prefer it in any application with more than one user. Setting both it andChatHistoryProviderthrows inMentorOptions.Validate()at startup. - MentorAgent:
MentorOptions.McpCallerPrincipalresolves theClaimsPrincipalof the MCP caller. A role-gated action is then published over MCP only when that principal is authenticated and holds one of the action's roles. The action is withheld when there is no resolver (the default), when the principal is null or unauthenticated, or when the resolver throws. Confirmation gates (RequiresConfirmation, theRequiresApprovalpredicate) are never satisfied by it, because there is no human on the far end of an MCP call. The published tool list is evaluated per caller identity. - MentorAgent: provider errors the user can act on are now shown as specific localized messages, instead of "An error occurred while processing the response". These errors are: an unreachable image URL, quoted back; a conversation past the context window; a throttled provider; a rejected image; a timeout. Everything else (an expired key, a missing deployment, a firewall rule) stays generic. Provider text is never forwarded,
IncludeWorkflowExceptionDetailskeeps its meaning and default, and the full exception is still logged. There are seven new localizer keys, in all ten languages, including the generic fallback, which was previously hard-coded in English.
Changed
Section titled “Changed”- MentorAgent: Breaking: the package now ships an MSBuild guard (
buildTransitive). It fails the build witherror MENTOR001when the resolvedOpenAIpackage is 2.11.0 or later (BUG-045, S1). Before, the application built and then died at startup with aMissingMethodExceptionfromAzureOpenAIClient.GetResponsesClient(). The pins are now exact ranges:Microsoft.Extensions.AI.OpenAI[10.6.0]andMicrosoft.Agents.AI.Foundry[1.17.0-preview.260804.1]. If the guard fires, remove your direct reference toMicrosoft.Extensions.AI.OpenAI10.7.0 or later, or toMicrosoft.Agents.AI.Foundry1.18.0 or later, and let MentorAgent supply them; or pin them to those versions. To override the check deliberately, set the MSBuild propertyMentorAgentSkipOpenAIVersionCheck=true. See Provider package versions. - MentorAgent: on a turn that calls a UI action, the sentence the model writes alongside the call now reaches the user (a consequence of the streaming fix, BUG-052).
- MentorAgent: the input safety classifier now receives the application's scope (
AppName,AppDescription, the names of the discovered pages) and is told that reading the application's own business data is safe however broadly it is phrased. Attempts to override the instructions are still refused (BUG-047). - MentorAgent: the scope text the hosted-tool domain gate derives now names the hosted capabilities that are enabled, and states the decision rule as a constraint on the subject. A custom
HostedToolDomainScopeis left exactly as written (BUG-050). - MentorAgent.Abstractions: the README gives every component a worked example (
MentorCardView,MessageBubble,ChatInput,OnboardingTour,ConfirmationBanner,WelcomePanel,RagSourcePanel, the MCP and A2A badges,TypingIndicator), plus a "Composing your own chat surface" walkthrough.
- MentorAgent.Server: BUG-051 (S1): the hub method
SendMessagetakes(string text, IReadOnlyList<MentorAttachment>? attachments). SignalR binds arguments by count, so a C# default value never applies. The documented clients all invoked it with one argument: the JavaScript quickstart, the React hook, the Angular service, the Vue composable, the .NET MAUI or console client, and the UI-actions walkthrough. The server rejected these calls with "Invocation provides 1 argument(s) but target expects 2", and the client saw "Failed to invoke 'SendMessage' due to an error on the server". All six snippets are corrected. If you wrote a client from them, passnull(or[]) as the second argument; nothing changed on the server. See Any front end. - MentorAgent: BUG-054 (S1): MentorAgent could not start at all on .NET MAUI (Blazor Hybrid), even with skills off. The skills builder read
IHostEnvironment.ContentRootPath, which throws on MAUI, and the exception killed the whole Blazor renderer. The content root now falls back toAppContext.BaseDirectory, where the content files of a MAUI app land, so a relativeSkillsFolderstill resolves. - MentorAgent: BUG-053 (S2): the documented Blazor Hybrid (MAUI) render mode failed its first build with
NU1605. The core README now has a setup section for Blazor Hybrid (MAUI), including the package pin that resolves the error. See .NET MAUI. - MentorAgent: BUG-047 (S2): with
EnableSafetyCheckon, ordinary requests for the application's own records were refused depending on their wording (see Changed). - MentorAgent: BUG-052 (S2): registering one UI action switched token streaming off for every turn on that page, and the whole reply arrived in a single frame. The UI-actions loop now streams, withholding only calls to its own registered actions (filtered by name), so genuine tool calls of the outer pipeline pass through untouched.
- MentorAgent: BUG-050 (S3): with
HostedToolDomainCheckon, the README's own image-generation example was refused as out of scope (see Changed). - MentorAgent: BUG-044 (S3): the core README's first Azure OpenAI Responses API example, and the same form in the doc comment of
MentorOptions, did not compile. They now showGetResponsesClient().AsIChatClient("deployment"). - MentorAgent.Abstractions: BUG-048 (S3): seven of the nine buttons of an open panel were icon-only and named by
titlealone, so screen readers announced them as unnamed buttons. Every icon-only control now also carries anaria-labelfrom the same localizer key. - MentorAgent.Abstractions: BUG-049 (S3): the text of the MCP and A2A badges was hard-coded (Italian in
ChatWidget, English inMcpStatusBadge). Six new localizer keys in all ten languages (mcp.connecting,mcp.allOnline,mcp.someOnline,mcp.offline,a2a.pill,a2a.agents), read by both components.
Security
Section titled “Security”MentorAgent.Blazor: BUG-046 (S1): the WebAssembly client could not authenticate its hub connection, so the server saw every user as anonymous:
- every
RequiredRolesaction was blocked; RateLimitPerUserbecame one global limit;- all users shared the memory key
anonymous. WithMemoryAutoCaptureon by default, personal facts extracted from one person's conversation reached the next person's prompt.
Fixed by
AccessTokenProviderandConfigureConnection(see Added). Upgrade MentorAgent.Blazor and MentorAgent.Server together. A WebSocket handshake cannot send anAuthorizationheader, so a JWT host must read theaccess_tokenquery parameter for/mentor-hub. The Server README has aJwtBearerEvents.OnMessageReceivedrecipe.- every
MentorAgent: BUG-055 (S1):
MentorOptionsis a singleton, so an object assigned toChatHistoryProviderserved every circuit, connection and user in the process, and one user's conversation could be served to another. UseChatHistoryProviderFactoryin any application with more than one user.ChatHistoryProvideris kept for single-user hosts and for providers that partition their own storage, and now logs at Debug that it is shared.MentorAgent.Server: BUG-060 (S1): the hub and SSE endpoints could not be protected through
MapMentorAgentServer(), because it discarded their endpoint builders. So an anonymous caller could run paid turns, with one memory bucket and one rate-limit counter that all anonymous callers shared. UseconfigureTransports(see Added).MentorAgent.Server: BUG-058 (S1, present since before 1.0.0-rc.2):
POST /mentor/approvelet anyone who learned an action id approve a gated action that its owner had not answered, or deny one that the owner wanted. The server now records which connection raised each pending confirmation. It accepts an answer only from the owner of that connection, with the same ownership check as/mentor/session, andPOST /mentor/cancelgets the same check. Breaking: on an authenticated host, approve and cancel requests must carry the same identity as the hub connection. An anonymous caller against an authenticated connection is refused with 401, and a different user with 403. Hosts with no authentication, SSE confirmations and in-process Blazor Server confirmations are unchanged.
1.0.0-rc.2
Section titled “1.0.0-rc.2”Published on NuGet on 24 August 2026 (UTC): MentorAgent 1.0.0-rc.2 (external site).
- MentorAgent:
MentorOptions.SkillSourcesaccepts any Agent FrameworkAgentSkillsSource: a database, a remote catalog, a store per tenant or Microsoft'sAgentFileSkillsSource.- Its skills reach the assistant through the same
load_skillandread_skill_resourcetools, catalog prompt and gate as MentorAgent's own. - Sources are composed with the framework's aggregating, filtering, deduplicating and caching decorators.
- An application skill always wins a name collision: the duplicate is skipped with a warning.
- Sources need a model. MentorAgent uses
Agentwhen it is set, otherwise a plain agent overChatClient. With neither, sources are skipped with a warning. - MentorAgent's own
SKILL.mdconvention is unchanged: register the framework's file source as well if you want both dialects.
- Its skills reach the assistant through the same
- MentorAgent:
MentorOptions.SkillFilter(it applies to skills from sources only, never to your own) andMentorOptions.SkillsRefreshInterval(it adds caching of the sources; it had no effect until 1.0.0-rc.11, because every session built its own cache: BUG-093). - MentorAgent:
MentorOptions.AutoApprovalRules(withHitlMode.Native) approves a tool call before any confirmation box appears, through the framework'sToolApprovalAgentmiddleware. It also turns on "don't ask again": after a user approves a call, matching calls stop asking for the rest of the session. It is opt-in:HitlMode.Nativealone does not add the middleware. A rule skips the question, never the permission:RequiredRolesis still checked. A call that is not approved automatically still arrives asConfirmationRequired, and is answered withPOST /mentor/approve. - MentorAgent:
MentorOptions.MaxAutoApprovalIterationscaps how many times one turn may run again because every approval it surfaced was auto-approved. Each extra run is a billable model call.
Changed
Section titled “Changed”- The family moves onto the Microsoft Agent Framework 1.18.0 line (
Microsoft.Agents.AI1.18.0) andMicrosoft.Extensions.AI10.7.0.Microsoft.Agents.AI.Foundrystays on 1.17.0-preview andMicrosoft.Extensions.AI.OpenAIon 10.6.0, so thatOpenAIstays at 2.10.0. Version 2.11.0 removes a constructor thatAzure.AI.OpenAI2.9.0-beta.1 still calls. With it, a host using Azure OpenAI hosted tools or service-managed history would die at startup with aMissingMethodExceptionfromAzureOpenAIClient.GetResponsesClient()(BUG-043, S1, fixed before this release). See Known issues. - MentorAgent.Declarative:
Microsoft.Agents.AI.Declarativemoves to 1.18.0-rc1, on the same line as the core package. - MentorAgent: a bare
GET /mcp(mapped byMapMentorAgentMcp()) now answers 400 with a JSON-RPC error naming the missingMcp-Session-Idheader. Before, it answered 406 (the behavior of the MCP SDK).
Known issues
Section titled “Known issues”- BUG-045 (S1): the hold on
OpenAIis a minimum, not a ceiling. A project that referencesMicrosoft.Extensions.AI.OpenAI(10.7.0 or later) orMicrosoft.Agents.AI.Foundry(1.18.0 or later) directly resolvesOpenAI2.11.0 or later, builds cleanly and dies at startup. Keep those two packages at 10.6.0 and 1.17.0-preview. Fixed in 1.0.0-rc.3 by exact pins and theMENTOR001build error.
1.0.0-rc.1
Section titled “1.0.0-rc.1”Published on NuGet on 19 August 2026 (UTC): MentorAgent 1.0.0-rc.1 (external site).
IMentorOrchestrator.SerializeSessionAsyncandIMentorOrchestrator.RestoreSessionAsync, to save and restore a conversation. The equivalentIMentorSessionManagermethods take the coordinatorAIAgent, which no public API returns, so they could not be called (BUG-025, S2).MentorModelUsage.RequestsWithoutUsage: requests that were billed but reported no token counts (for example a turn the user stopped), disclosed instead of counted as zero.- MentorAgent.Server: two SSE frames.
{"type":"confirmationRequired","actionId":"...","tool":"...","message":"..."}: answer it withPOST /mentor/approve?actionId=...&approved=true|falseon a second request while the stream is open, and the parked turn resumes. And{"type":"navigation","url":"..."}fornavigate_to(BUG-037, S2). The README now documents the complete set of SSE frames:chunk,cards,navigation,confirmationRequired,completed,error.
Changed
Section titled “Changed”- MentorAgent.Server: Breaking: the SSE frame
{"type":"completed"}now means the turn is over. Before, it fired when the streaming segment ended, including for a turn parked on a human confirmation, which was reported as completed with no action id to approve (BUG-038, S2). A client that treatedcompletedas "the answer is finished" keeps working; a client that used it to decide the request had succeeded must now also handleconfirmationRequired. - MentorAgent: Breaking: session snapshots are now stamped (
{"mentorAgentSession":1,"session":...}), and anything else is refused before the live session is touched. Before, arbitrary JSON restored as an empty session that silently replaced the live conversation (BUG-026, S3). Snapshots written by 1.0.0-preview.5 are refused: discard them rather than migrating. - MentorAgent: refusals now reach the model with a structural marker (
declined_by_userorstopped_by_user), and the instruction travels in the tool result, instead of looking like a crashed tool that the model offers to retry (BUG-031, S3). - MentorAgent: MentorAgent's own
last_sessionbookkeeping is still written, but no longer injected into the memory context, where it always took a slot (BUG-014, S3). - MentorAgent: the output of the evaluation report meant for machines (including
FailureReason) uses the invariant culture (BUG-020, S4).
Removed
Section titled “Removed”- MentorAgent: the stale second copy of the widget stylesheet and script that the core package shipped under its own
_contentpath, referenced by nothing (BUG-023, S4).
- MentorAgent: BUG-018 (S1): a
[TeamTerminationCondition]on a Level-3 team removed the iteration cap instead of tightening it, so a predicate that never fired ran the group chat without bound. Custom conditions now run in addition toMaxIterations, never instead of it. - MentorAgent: BUG-013 (S2): on Path B (
options.Agent) the tool list was built and logged but never sent to the model, so the assistant had no application actions,navigate_to,invoke_ui_actionor memory tools. The list is now passed throughChatClientAgentRunOptions, whose tools are added to the agent's own. - MentorAgent: BUG-015 (S2): Path B also received none of MentorAgent's instructions and none of the context of each turn (page, memory, RAG, skills); they are now added alongside the host's own persona. BUG-006 (S2): a custom
AIAgentcould fail to start at all, telling the user to reload the page. BUG-007 (S3): the diagnostics of Path B were unreachable. - MentorAgent: BUG-027 (S3):
RagMinScoredefaults to 2, a scale that suits keyword-scored sources. Vector stores, instead, return a cosine similarity between 0 and 1, so on a vector store every document was silently discarded. A warning is now logged once per provider, naming the threshold, the document count and the highest score seen. For a vector store, setRagMinScorebetween 0.5 (loose) and 0.75 (strict), or 0 to disable filtering. - MentorAgent: BUG-016 (S3):
UseRag = truewith noIMentorRagSourceregistered now warns when the coordinator is built. BUG-017 (S3): aRagSystemPromptTemplatewithout the{documents}placeholder now warns (it dropped every document while still showing citation chips). - MentorAgent: BUG-028 (S2):
MaxSessionMessages = 0(or negative, or an empty key inappsettings.json) threw while the coordinator was assembled. It is now guarded, and read like the neighbouring options that use 0 for "no limit". - MentorAgent: BUG-011 (S2): an assembly listed twice in
ScanAssembliesregistered everything twice, and the coordinator failed to build. Duplicates are now removed with a warning. BUG-008 (S3): "Native HITL is enabled but no tool requires approval" is now logged at a level operators watch. - MentorAgent: fixes to the token and cost metrics:
- BUG-030 (S2): Azure OpenAI does not reliably report the response model id, and a blank id was attributed to the cheap model, so escalated turns were priced as cheap ones.
- BUG-034 (S2): a dated model id (
gpt-4.1-2025-04-14for a deployment namedgpt-4.1) produced a separate dashboard row with no price. It is now folded onto the configured or priced model by an exact match of the trailing date, never by prefix. - BUG-033 (S3): MentorAgent's own model calls (memory auto-capture, the safety check, the hosted-tool domain gate) are now metered.
- BUG-032 (S3): a turn the user stopped is now counted, with its latency, instead of vanishing from the metrics.
- MentorAgent: BUG-012 (S2): answering a confirmation synchronously (an auto-approval policy, a client that approves in advance) parked the turn forever, with no error.
- MentorAgent: BUG-019 (S3): a UI action requested by the model ran against the page registrations captured before the model call, so navigating away during the turn ran a handler on a disposed component. Registrations are now resolved when the action runs.
- MentorAgent: BUG-010 (S3): tool results containing a tab or another control character produced JSON the model could not parse.
- MentorAgent: BUG-029 (S2):
AgentCardInfo.IconUrl,Provider,DocumentationUrland the version override now reach the published A2A agent card.AgentCardInfo.Tagsis documented as reserved and not published, because the A2A specification attaches tags to skills, not to the card. - MentorAgent.Abstractions: BUG-024 (S2): in hands-free voice mode the microphone stayed open during playback, so the assistant transcribed its own answer and sent it back as the next question. The microphone now closes when an answer begins, and the half-heard fragment is discarded.
- MentorAgent.Abstractions: BUG-039 (S3): loading
MentorAgent.jstwice (the configuration recommended on WebAssembly, whereindex.htmlcarries a script tag and the widget injects a second one) reset the voice state machine during a session. The state now survives. Upgrade MentorAgent.Abstractions and MentorAgent.Blazor together. - MentorAgent.Abstractions: BUG-022 (S4): the RAG citation chips read a CSS variable no stylesheet declares and rendered at full brightness. They now use the theme's secondary text level.
- MentorAgent.Blazor: BUG-009 (S2):
IMentorOrchestrator.RespondToApprovalAsyncon WebAssembly went through theRespondToApprovalhub method, which deadlocks while the turn awaiting approval holds the connection. It now posts to/mentor/approve.CancelCurrentRequestno longer invokes the hub on a dead connection. - MentorAgent.Server: BUG-036 (S2): the documented SSE
cardsframe was lost, because several handlers wrote to the response concurrently inside an empty catch block. All frames now go through a single ordered writer, and a failed write is logged. - Documentation (each of these broke custom clients written from the READMEs):
- the streaming event is
StreamingChunk, notReceiveChunk(BUG-001, S2); - navigation arrives as
NavigationRequested, notNavigateTo(BUG-005, S2); - the protocol reference now lists all 18 events from server to client, including
CardsandHostedToolsDeclared(BUG-002, S2), and marksCancelRequestandRespondToApprovalas not to be used, in favor of the HTTP routes; - the memory tool is
forget_all, notforget(BUG-003, S3); - the skills example follows the tool-naming rule (BUG-004, S3);
CancelCurrentRequest,RespondToApprovalAsyncand the metrics snapshot served over HTTP (includingDeflectionRate) are documented with reference tables and examples (BUG-040, BUG-041, S3);- the READMEs now state that a SignalR reconnect is a new connection, a new DI scope and therefore a new conversation.
- the streaming event is
Security
Section titled “Security”- MentorAgent: BUG-021 (S1): the MCP server published every
[MentorAction], including actions restricted withRequiredRolesand actions markedRequiresConfirmation, to any client that could reach/mcp: an endpoint mapped with permissive CORS by default, whose requests carry no signed-in principal. Gated actions are now withheld from the MCP surface, and the withheld set is logged with each tool and the reason. - MentorAgent: BUG-035 (S1): the same hole existed for actions gated by the
RequiresApprovalpredicate; both routes now fail closed. Breaking: a gated action is no longer reachable over MCP, and there is no opt-in to publish it anyway. If an MCP client relied on one, perform that action from the application instead. (1.0.0-rc.3 addedMcpCallerPrincipalfor publishing role-gated actions to authenticated callers.)
Known issues
Section titled “Known issues”- On Blazor WebAssembly,
SerializeSessionAsyncandRestoreSessionAsyncthrowNotSupportedException, because the session lives in the DI scope of the server. (1.0.0-rc.3 addedGETandPOST /mentor/sessionfor remote clients.) - A SignalR reconnect, including with
withAutomaticReconnect(), is a new connection and therefore a new conversation. - MentorAgent.Server: the SSE stream forwards six of the hub's eighteen events.
GeneratedImages, RAG citations and the line on hosted-tool activity are hub-only. - MentorAgent.Server: the hub's limit on received messages is sized from the image options. An oversized argument aborts the connection instead of returning an error.
- MentorAgent: with
A2AServerUrlunset, the A2A agent card advertises a bare path, which is useless to a client on another host. Set it to the absolute URL.
1.0.0-preview.5
Section titled “1.0.0-preview.5”Published on NuGet on 12 August 2026 (UTC): MentorAgent 1.0.0-preview.5 (external site).
MentorAgent.Declarative: first release.
AddMentorAgentDeclarative(options)defines Level-2 specialists in YAML instead of C# classes. It loads*.agent.yamlfiles fromDirectoryand inlineDefinitions.SearchPatterndefaults to*.agent.yaml, andRecursivetofalse. It can also expose one configuration section throughConfigurationSection. The agents join the same handoff graph as[MentorAgent]classes. A YAML file names tools; it does not define them. Each tool is resolved from the Level-1 tools that the application already registers, already wrapped in MentorAgent's gate. SoRequiredRoles, human approval, action feedback and per-tool metrics keep working. A malformed definition is logged and skipped, and never stops the assistant from starting. Definition files are code: load them only from paths fixed at deploy time. The Agent Framework's declarative stack (Power Fx and its dependencies) stays out of the core package. See The three agent levels.MentorAgent:
IMentorAgentSource(withMentorAgentSourceContext): supply Level-2 specialists that the scan for the[MentorAgent]attribute cannot see. They join the same handoff graph, and the tools handed to a source arrive already gated.Generative UI Level 2, cards: a tool can return a
MentorCard(or several) instead of a string. The widget renders it as a card with a title, a subtitle, label and value fields, an accent color, and buttons. A button can send a message, navigate, or run a UI action that the page registered. New in this version:- the contracts
MentorCard,MentorCardField,MentorCardAction,MentorCardActionKindandMentorCardAccent; - the
MentorCardViewcomponent (XSS-safe: noMarkupString); IMentorStateService.OnCardsReadyandNotifyCardsReady;MentorOptions.EnableGenerativeCards(defaulttrue;falserestores the previous text behavior).
Because cards come from application code, the conversation cannot add a button or change where one points. The model is told that the card is on screen, and receives the data in compact form.
- the contracts
MentorAgent.Abstractions:
ChatWidget.CardTemplaterenders a kind of card your own way; the other kinds use the built-in renderer. The buttons of aMentorCardViewinside a template did nothing until 1.0.0-rc.11 (BUG-088).MentorAgent.Server: cards are forwarded to remote clients as a
Cardshub event and a{"type":"cards"}SSE frame, serialized in camelCase with string enums. Additive: a client that ignores them still receives the whole answer as text.Onboarding tour:
EnableOnboardingTour(defaultfalse, onMentorOptions,MentorWidgetOptionsandMentorAgentBlazorOptions),IMentorTour,MentorTourStepand theOnboardingTourcomponent. A short tour when a user first opens the widget, generated once per process from the[MentorPage]pages and the assistant's tools. Each step can carry a ready-made question. A generated URL that matches no registered page is dropped; without aChatClient, a deterministic tour is built from the same data. Register your ownIMentorTourto script it by hand.MentorAgent.Server:
GET /mentor/tourreturns the tour steps as JSON for headless and WebAssembly clients; enableEnableOnboardingTouron the server as well. It is unauthenticated by design: the payload is the public screen names and capability descriptions, identical for every user and cached per process.MentorAgent.Blazor:
MentorAgentBlazorOptions.TourUrl, to fetch the tour from the server. If the fetch fails, the widget opens normally.Voice options, on
MentorOptions,MentorWidgetOptionsandMentorAgentBlazorOptions:VoiceStreaming(defaulttrue);VoiceBargeIn(defaulttrue): playback stops when the user presses the microphone, sends a message, presses Stop or starts a new conversation;VoiceHandsFree(opt-in): the transcript is sent on silence, and the microphone reopens when the spoken answer ends;VoiceRate(default1.0).
Changed
Section titled “Changed”- Voice output now speaks each sentence while the answer streams, instead of reading the finished reply back. A decimal point is not treated as a full stop, and fenced code blocks are skipped rather than read out.
- MentorAgent.Server: the endpoint table in the README now lists
/mentor/approve,/mentor/cancel,/mentor/admin/metricsand/mentor/tour.
1.0.0-preview.4
Section titled “1.0.0-preview.4”Published on NuGet on 4 August 2026 (UTC): MentorAgent 1.0.0-preview.4 (external site).
MentorAgent: provider-hosted tools.
MentorOptions.HostedTools(MentorHostedTools.WebSearch | CodeInterpreter | FileSearch | ImageGeneration | HostedMcp) lets the model provider run these tools on its own infrastructure: web search, a sandboxed code interpreter, file search, image generation and remote MCP calls.- Related options:
FileSearchVectorStoreIds(required for file search),FileSearchMaxResults,HostedMcpServers(MentorHostedMcpServer, withRequireApproval,AlwaysRequireApprovalToolsandNeverRequireApprovalTools),HostedImageModelandHostedImageSize(WIDTHxHEIGHT; a value that cannot be parsed is ignored with a warning). - They fail closed: without vector store ids, file search is skipped with a warning; without servers, hosted MCP is skipped with a warning too.
- Availability depends on the provider client. The Responses API and Foundry support the full set; Chat Completions supports only web search. The Responses API also needs
UseServiceManagedHistory. - The enabled set is logged at startup and listed in the coordinator's system prompt. When a tool is withheld on a turn, the model is told so in that request (appended to
ChatOptions.Instructions), so it refuses instead of inventing a result.
- Related options:
MentorAgent:
MentorOptions.ShowHostedToolActivity(defaulttrue) reports the work done on the provider's side through the existing channels: action-feedback lines such as "Searching the web…", web-search and file-search sources as citation chips, and generated images attached to the message.MentorAgent.Server: the hub events
GeneratedImages(string[])(data: URIs or absolute URLs, ready for<img src>) andHostedToolsDeclared(int)(sent once on connect, with the activeMentorHostedToolsflags). Hosted-tool activity also arrives on the existingActionExecuting,ActionCompletedandRagSourcesReadyevents. Additive.MentorAgent.Abstractions: a hosted-tools badge in the widget header, driven by
MentorWidgetOptions.ShowHostedToolsStatusandHostedTools(mirrored onMentorAgentBlazorOptions), plusIMentorStateService.OnHostedToolsDeclaredandNotifyHostedToolsDeclared: the widget prefers the set the server declares over its local option. New CSS variables--bm-hosted-textand--bm-a2a-text, overridden per theme.MentorAgent: cost controls for hosted tools:
FilterHostedTools(defaulttrue) puts hosted tools through the semantic tool filter, with their own thresholdHostedToolFilterMinScore(effective default 0.15).MaxHostedToolCallsPerSessionlimits the hosted-tool calls per session (0 = unlimited).HostedToolDomainCheck, withHostedToolDomainScopeandHostedToolDomainClassifier, lets a small model decide whether the message concerns the application at all. It runs once per turn, and only when a hosted tool would otherwise run. If the check itself fails, the turn goes on (it fails open).
All three require
EnableToolFilteringand anEmbeddingGenerator: without them nothing is filtered, and a startup warning names the ignored options.MentorAgent:
MentorOptions.HitlMode:MentorHitlMode.Blocking(the default, unchanged) orNative.Nativeuses the Agent Framework approval flow (ApprovalRequiredAIFunctionandToolApprovalRequestContent), with one extra round trip for each approved call. The confirmation box and the client protocol are the same in both modes.MentorOptions.RequiresApprovalis a predicate on the tool name: when it returnstrue, that tool requires confirmation. It works for any tool, including tools you do not own (MCP, skills, remote agents). See Governance.Multimodal image input:
EnableImageInput,AllowedImageTypes(default png, jpeg, gif, webp),MaxImageBytes(default 4 MB) andMaxImagesPerMessage(default 4), all validated again on the server: the copies on the widget only drive the checks in the browser. Rejected attachments are dropped with a warning, and the turn still runs. It requires a chat model with vision. New contractsMentorAttachmentandMentorUserMessage, andIMentorOrchestrator.SendMessageAsync(text, attachments); a turn with only images is valid. The composer accepts file upload, clipboard paste, drag and drop and a remote URL. In the browser, it scales down an image larger thanMaxImageBytes: to at most 2000 px, with the original type kept. Animated GIFs are not re-encoded.MentorAgent.Blazor:
WasmMentorOrchestratorandMentorHubClientgainSendMessageAsync(text, attachments).MentorAgent.Server:
POST /mentor/chat, accepting{ "message": "...", "attachments": [ { "mimeType", "dataBase64" | "url", "fileName" } ] }(GET remains for text only). WithEnableImageInputon,AddMentorAgentServer()raisesHubOptions<MentorHub>.MaximumReceiveMessageSizetoMaxImageBytes * MaxImagesPerMessage * 4/3 + 512 KB, scoped to the MentorAgent hub and only ever raising an existing value: keep the image options tight.MentorAgent.Server:
POST /mentor/cancel?connectionId=...stops a turn in progress from outside the hub. SignalR dispatches one hub invocation at a time per connection, so theCancelRequesthub method could only run after the turn it was meant to stop.MentorAgent:
MentorOptions.UseServiceManagedHistory, for providers that keep the conversation on the service (the Responses API, Foundry, Copilot Studio): the Agent Framework refuses to combine their conversation id with a local history provider. With it on, no history provider is installed, andMaxSessionMessagesandEnableCompactionno longer apply.MentorAgent: duplicate tool names among the filterable tools are reported at startup.
Changed
Section titled “Changed”- MentorAgent.Server: Breaking: the hub method
SendMessagenow takes a second argument,attachments. SignalR binds arguments by count, so every client must pass both: sendnull(or[]) when there are no attachments. A one-argument invocation is rejected. (This release documented the argument as optional; corrected in 1.0.0-rc.3, BUG-051.) - MentorAgent.Abstractions: Breaking:
ChatInput.OnSendis nowEventCallback<MentorUserMessage>instead ofEventCallback<string>. Update handlers to take aMentorUserMessageand readText(andAttachments). - MentorAgent: tool filtering and model routing now decide once per turn instead of once per request, because providers that keep the conversation reject a change of tool list or deployment in the middle of a turn.
- MentorAgent: provider-side errors that arrive inside the stream are logged at Error level with message, code and details, instead of a bare "Stream content: ErrorContent" line.
Deprecated
Section titled “Deprecated”- MentorAgent.Server: the
RespondToApprovalandCancelRequesthub methods are kept for backwards compatibility only (CancelRequestworks only while the connection is idle). UsePOST /mentor/approveandPOST /mentor/cancel.
- MentorAgent:
ChatOptionswas copied property by property in two middlewares, droppingTools, so a page registering UI actions offered the model only those actions instead of the full tool list, andConversationId, which broke every local tool call under service-managed history. Options are now cloned. - Stop never worked for SignalR clients, including the WebAssembly widget, because the
CancelRequesthub method queued behind theSendMessagestill streaming.WasmMentorOrchestrator.CancelCurrentRequestand the README client examples now usePOST /mentor/cancel. Upgrade MentorAgent.Blazor and MentorAgent.Server together: the WebAssembly client's Stop needs the new endpoint, and the hosted-tools badge and image attachments need the server of this version (a mismatched pair falls back to the local badge option). - MentorAgent.Abstractions: a citation with no URL (a document matched in a vector store, a file produced by the code interpreter) rendered as a link to "#" that jumped to the top of the host page. The chip now has no
hrefand is styled as non-interactive. - MentorAgent.Abstractions: a failure in the send itself (for example the transport rejecting the payload) left the chat with no reply, no error and no busy indicator. It now surfaces as an error bubble and clears the busy state.
- MentorAgent.Abstractions: the A2A (indigo) and hosted-tools (amber) chips hard-coded pale text meant for the dark theme, and were nearly invisible on the Minimal (light) theme.
Security
Section titled “Security”- MentorAgent: tools invoked inside a Level-2 specialist or a Level-3 team bypassed the confirmation box and the
RequiredRolescheck, because those agents run their own function-calling loop inside the workflow. The gate is now attached to the function itself, so role checks, confirmation, action feedback,NavigateTo,OnToolResult,OnExceptionand per-tool metrics apply at every level. Nested tools always use the blocking approval flow, even underHitlMode.Native; the user is asked exactly once. - MentorAgent:
MentorMcpServer.RequiresConfirmationwas documented but not enforced. Tools from such a server now require confirmation in both HITL modes.
Known issues
Section titled “Known issues”- MentorAgent: provider-hosted tools run on the provider and never pass through the function-calling middleware, so
RequiredRoles,RequiresConfirmationand per-tool metrics do not apply to them. Hosted MCP servers can require approval throughMentorHostedMcpServer.RequireApproval. - MentorAgent: the counter of
MaxHostedToolCallsPerSessionlives in the orchestrator scope. Over SignalR it spans the connection, while eachPOST /mentor/chatcall is its own session, so a stateless HTTP client gets a cap per request, not per user. - MentorAgent: on Azure OpenAI, hosted image generation also needs the
x-ms-oai-image-generation-deploymentrequest header, which MentorAgent cannot add to anIChatClientthat is already built. Attach it as a pipeline policy where you construct theAzureOpenAIClient. A startup log line restates this whenever image generation is on.
1.0.0-preview.3
Section titled “1.0.0-preview.3”Published on NuGet on 24 July 2026 (UTC): MentorAgent 1.0.0-preview.3 (external site).
- Token and cost dashboard: the admin-only
MentorDashboardcomponent (never shown in the end-user widget), over anIMentorMetricssnapshot (MentorMetricsSnapshot).- It attributes usage to each model: the cheap chat model, the strong routing model and the embedding model (
MentorModelUsage,MentorModelKind). - It has hourly time series (
MentorUsagePoint), a model selector, time charts in inline SVG (no JavaScript, CSP-safe, theme-aware), a cost table per model and the top actions. - Cost comes from the
ModelPricingyou supply (ModelPrice; there are no built-in prices). - History is kept for
MetricsRetention(default 7 days). A pluggableIMentorMetricsStore(RAM only by default) adds persistence, saved everyMetricsPersistenceInterval(default 30 s). - Labels are localized in 10 languages. In WebAssembly, pass the fetched snapshot and set the component's
Languageparameter.
- It attributes usage to each model: the cheap chat model, the strong routing model and the embedding model (
- MentorAgent.Server:
GET /mentor/admin/metricsreturns the metrics snapshot for headless dashboards, gated byMentorOptions.DashboardRole(default"Admin"). - MentorAgent: model routing:
StrongChatClientwithRoutingStrategy(MentorRoutingStrategy.Semantic,Classifier,CascadeorCustom, the default),RoutingThreshold(default 0.35),RoutingComplexExemplars,RoutingClassifierClient, and theUseStrongModelandUseStrongModelAsyncpredicates. - MentorAgent: token and cost controls:
- a token counter and a log line per call;
EmbeddingGenerator;- opt-in semantic tool filtering (
EnableToolFiltering,ToolFilterMaxToolsdefault 12,ToolFilterMinScoredefault 0.35); - opt-in history compaction (
EnableCompaction,CompactionTokenThresholddefault 4000,CompactionMaxTurnsdefault 8); - memory ranked by embeddings (
MemoryRelevanceFiltering). It requiresEmbeddingGeneratorand falls back to the last N; identity and preference facts are always kept.
- MentorAgent:
MentorOptions.MemoryAutoCapture(defaulttrue): after each turn, a dedicated small model call saves durable user facts (name, role, team, preferences), so memory no longer depends on the model calling theremembertool. Set it tofalseto avoid the extra call per user message. - MentorAgent:
MentorOptions.EnableRichResponses(defaulttrue): the coordinator is asked to format tabular data as Markdown tables and enumerations as lists, which the widget renders safely (Generative UI, Level 1). - MentorAgent: middleware hooks: an output safety check (
EnableOutputSafetyCheck) alongside the existing input check;InputGuardrailandOutputGuardrail;OnToolResult, to transform a tool result before it reaches the model;OnException; andConfigureChatClientPipeline, to add your own delegating chat clients. - MentorAgent: OpenTelemetry observability:
EnableObservability,ObservabilitySourceName(default"MentorAgent") andObservabilityIncludeSensitiveData(prompt and response content, for development). It produces traces and metrics that follow the GenAI conventions for model calls, plus spans and counters per turn and per tool. - MentorAgent: structured outputs:
IMentorStructured.GenerateAsync<T>returns a strongly typed result, with a JSON schema derived fromT. - MentorAgent: evaluation kit:
MentorEvaluatorover the Agent Framework's native evaluation, runningEvalCases (MentorEvalOptions,MentorEvalReport,MentorEvalResult) and gating on token budget and quality withreport.ThrowIfFailed().
Changed
Section titled “Changed”- MentorAgent.Server: identity bridge:
AddMentorAgentServer()passes the authenticated SignalR or HTTP principal to the core, so per-user memory, per-user rate limiting andRequiredRoleswork for headless clients, not only for Blazor Server. - MentorAgent.Server: the coordinator is built once per SignalR connection instead of once per hub method call, so external MCP servers connect once and the conversation persists across messages.
- MentorAgent: with
MemoryAutoCaptureon and aChatClientconfigured, theremembertool and its prompt block are dropped. The forget tool is always available. - MentorAgent: the HITL confirmation message now spells out the concrete arguments the assistant is about to pass, over every transport (including the
ConfirmationRequiredevent for headless clients). The full text is available as a tooltip. - MentorAgent: a slimmer system prompt that works better with prompt caching. RAG relevance relies on the vector search and
RagMinScorealone.
- MentorAgent.Abstractions: event handlers (
@onclick,@onchange,@bind) in the shipped components compiled to literal HTML attributes and never fired, which broke the suggestion chips ofWelcomePanel, the buttons of the confirmation box and the MCP and A2A status badges. Upgrade to get working handlers. - MentorAgent: the system prompt no longer includes a bare "User: not authenticated" line for anonymous users, which made the model invent authorization rules and refuse tools with no role requirement. Role-gated tools remain enforced by the middleware.
1.0.0-preview.2
Section titled “1.0.0-preview.2”Published on NuGet on 22 June 2026 (UTC): MentorAgent 1.0.0-preview.2 (external site).
Changed
Section titled “Changed”- New package icon for all packages.
- MentorAgent.Server: README: the HITL examples for Angular, Vue and .NET MAUI or console use
POST /mentor/approveinstead of theRespondToApprovalhub call, which deadlocks, and every client example (React, Angular, Vue, MAUI) handles theMcpServerStatusChangedevent. - MentorAgent.Blazor: README:
OnMcpServerStatusChangedis forwarded over the SignalR hub and fires on the client.
1.0.0-preview
Section titled “1.0.0-preview”Published on NuGet on 22 June 2026 (UTC): MentorAgent 1.0.0-preview (external site).
- First release under the MentorAgent name, as the successor of BlazorMentor. It targets .NET 10 and Microsoft Agent Framework 1.6.1. The packages:
- MentorAgent: the core library and widget for Blazor Server and in-process hosts,
AddMentorAgent(); - MentorAgent.Server:
AddMentorAgentServer()andMapMentorAgentServer(), exposing the/mentor-hubSignalR hub, the/mentor/chatSSE stream andPOST /mentor/approvefor headless clients such as React, Angular, Vue and .NET MAUI; - MentorAgent.Blazor: the Blazor WebAssembly and Auto client,
AddMentorAgentBlazor()withHubUrl; - MentorAgent.Abstractions: shared components and contracts, installed transitively.
- MentorAgent: the core library and widget for Blazor Server and in-process hosts,
- MentorAgent: MCP server: expose MentorAgent as an MCP server (
McpServerEnabled,McpServerPath,ShowMcpStatus). Nothing readMcpServerPathuntil 1.0.0-rc.11 (BUG-091): pass the path toMapMentorAgentMcp()instead. - MentorAgent: MCP client: consume external MCP servers configured through
McpServers. - MentorAgent: A2A server: expose MentorAgent as an A2A agent (
A2AServerEnabled,A2AServerPath,A2AServerUrl,ShowA2AStatus). Nothing readA2AServerPathuntil 1.0.0-rc.11 (BUG-091): pass the path toMapMentorAgentA2A()instead. - MentorAgent: A2A consumer: delegate to remote A2A agents through the handoff workflow (
RemoteAgents,MentorRemoteAgent, with authenticationHeadersfor each agent). Remote agents are listed in the coordinator's system prompt.MentorRemoteAgent.RequiredRolesis accepted but not enforced: a startup warning says the roles are not checked. - MentorAgent: Agent Skills with progressive disclosure (
EnableSkills,SkillsFolder,[MentorSkill]). - MentorAgent: RAG through
IMentorRagSource(UseRag,RagResultCount,RagMinScore,ShowRagSources). - MentorAgent: Level-3 group-chat teams, for deliberation among several agents before acting (
[MentorTeam],[TeamMember]). - MentorAgent: detection of prompt injection and jailbreaks by a model (
EnableSafetyCheck) and per-user rate limiting (RateLimitPerUser). - MentorAgent: memory context for user preferences (
UseMemoryContext,MemoryContextCount). - MentorAgent: typed and async overloads for UI actions:
RegisterUIAction<T>,RegisterUIActionAsync,RegisterUIActionAsync<T>. - MentorAgent:
IncludeWorkflowExceptionDetails, to surface internal errors during development.
Changed
Section titled “Changed”- MentorAgent: a reworked system prompt compared with BlazorMentor: a Communication Style block, more natural memory instructions, and cleaner prompts for Level-2 and Level-3 agents.
- MentorAgent: compared with BlazorMentor, the A2A consumer threw
UriFormatExceptionwhen a remote agent card contained relativeSupportedInterfacesURLs, and the coordinator did not route to remote A2A agents after a successful connection.
Known issues
Section titled “Known issues”- MentorAgent:
MentorRemoteAgent.RequiredRolesis not enforced: any user can reach a remote agent. The property was removed in 1.0.0-rc.13.
See also
Section titled “See also”- What's new — What changed in the current MentorAgent version, what to do when you upgrade, its known issues and limitations, and how versions are numbered.
- Choose your packages — Which MentorAgent package to install for Blazor, MAUI, or a backend for React, Angular, Vue and mobile apps, and what each one contains.
