You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Python: .NET: [Feature]: Add IDecisionClient (reference of dotnet/extensions#7764), DecisionLoopEvaluator, and a TypeSafe (Jev) provider package #8562
Summary. Add first-class support for decision-oriented inference in .NET Agent Framework: a provider-neutral IDecisionClient (an experimental reference implementation of the shape proposed for Microsoft.Extensions.AI in dotnet/extensions#7764), a DecisionLoopEvaluator that uses it to judge loop completion, and a Microsoft.Agents.AI.TypeSafe provider package for TypeSafe AI's Jev ("System One") model. An implementation with an ADR, tests, and a working sample is ready on a branch; this issue records the scope and the design questions for maintainers before the PR.
Relationship to existing issues.#8545 asks for the same integration but proposes waiting for the MEAI abstraction and adding nothing to MAF meanwhile. #8556 asks for Jev support in the Python SDK. This issue is the .NET counterpart of #8556 and a concrete, implementable variant of #8545: the upstream proposal is a day-old, untriaged community issue with no maintainer response, and MEAI 10.10.0 (the version this repository references) contains no decision types, so gating on it blocks everything, including calibration work and evaluation frameworks that want one shared contract.
What a decision model is, and why it is not an IChatClient
A decision model does not generate text. It takes a piece of state plus one or more bounded, typed questions and returns typed probabilistic answers in one call:
Binary: P(true) for a proposition (Jev: noul), no separate confidence;
Choice: the selected member of a caller-defined set plus a probability distribution over every member (Jev: choice);
Score: a position on a caller-defined ordered scale plus a distribution over its levels (Jev: score).
Prompting an IChatClient for {"answered": true} gives syntactic structure; it does not give the probability, the distribution, batching of heterogeneous questions against one state, or a closed output domain declared before inference. Several MAF decision points are exactly this shape: should the loop continue, is the task complete, which authorized tools or Skills are relevant, which participant acts next, should a result be escalated. Jev is fast and cheap relative to a generative judge (vendor: $0.042 per million input tokens, output free), which matters for control-plane decisions that run on every iteration.
Proposed design
Contract in Microsoft.Agents.AI.Abstractions, [Experimental(MAAI001)], mirroring [API Proposal]: Add a provider-neutral abstraction for decision-oriented AI models dotnet/extensions#7764 name for name: IDecisionClient : IDisposable (GetResponseAsync(DecisionRequest, DecisionOptions?, ct), GetService), DecisionRequest (JsonElement State, IList<DecisionQuestion> Questions), DecisionOptions, DecisionQuestion with BinaryDecisionQuestion / ChoiceDecisionQuestion / ScoreDecisionQuestion, DecisionResponse (answers keyed by question id, ModelId, UsageDetails), DecisionAnswer with BinaryDecisionAnswer / ChoiceDecisionAnswer / ScoreDecisionAnswer, DecisionClientMetadata, and a GetResponseAsync<TState>(state, JsonTypeInfo<TState>, ...) extension. Two additions beyond the proposal, offered upstream too: a classified DecisionClientException (Authentication, InvalidRequest, RateLimited, Overloaded, ProviderUnavailable, InvalidResponse, Unknown; IsTransient), and range validation on answers so an out-of-range probability cannot exist as an object. The types are a staging ground: when MEAI ships an equivalent, they are deleted and consumers retarget the namespace. MAF does not evolve the shape independently.
DecisionLoopEvaluator : LoopEvaluator in Microsoft.Agents.AI, next to AIJudgeLoopEvaluator. After each iteration it asks one binary question ("Has the agent fully addressed the user's original request?") against a minimal, source-generated text projection of the loop state and applies a configurable completion threshold (default 0.90). It continues with a deterministic feedback message rather than model prose. Failure policy: Throw (default), Continue, or DeferToNextEvaluator; provider failure is never interpreted as "incomplete"; cancellation always propagates; non-text request content is rejected unless a StateFactory is supplied. Because LoopAgent evaluates evaluators in order and stops only when all return Stop, [DecisionLoopEvaluator, AIJudgeLoopEvaluator] is a cheap-then-strong cascade with no new abstraction: the generative judge runs only when the decision model believes the work is complete.
Microsoft.Agents.AI.TypeSafe: TypeSafeDecisionClient over POST https://api.typesafe.ai/v1/systemone (or OpenRouter's relay), strict parsing, HTTP failure classification, no silent retries, API key never in exception messages, feature-usage index 75. Follows the existing provider-package precedent (.OpenAI, .Foundry, .CopilotStudio).
Not in scope: tool or Skill shortlisting, group-chat routing, workflow branching, model routing, or any authorization decision. Those reuse existing seams (AIContextProvider, AgentSkillsProvider, GroupChatManager) later; a decision model may shortlist among already-authorized candidates but never authorize or bypass approval.
Status
Implemented on a fork branch (joslat/adr-0042-decision-loop-evaluator) with ADR-0042, PublicAPI baselines for all target frameworks, 45 evaluator test cases, 47 provider test cases, the feature-registry validation, and a Harness_Step06_DecisionLoop sample. Verified live against Jev jev-1.13.0 with an OpenAI-compatible primary model: the cascade finished a three-part task in four iterations with a single generative judge call; a mixed batch returned a binary probability, a choice distribution, and a weighted score in one call.
Questions for maintainers
Is an experimental reference copy of the MEAI proposal acceptable in Microsoft.Agents.AI.Abstractions (deleted when MEAI ships), or should it live in a satellite package such as Microsoft.Agents.AI.Decisions?
Is Microsoft.Agents.AI.TypeSafe the right home for the provider, or should it be provider-owned from the start?
usingIDecisionClientjev=newTypeSafeDecisionClient(apiKey,new(){ModelId="jev-1.13.0"});// Cheap decision model first; the generative judge verifies only when the decision model believes the work is done.AIAgentloop=newLoopAgent(innerAgent,[newDecisionLoopEvaluator(jev,new(){CompletionThreshold=0.90,FailureBehavior=DecisionLoopFailureBehavior.DeferToNextEvaluator,}),newAIJudgeLoopEvaluator(strongJudgeChatClient),],newLoopAgentOptions{MaxIterations=6});// Direct use: three primitives, one call, one state.DecisionResponseresponse=awaitjev.GetResponseAsync(newDecisionRequest(state,[newBinaryDecisionQuestion("refund_requested","Does the customer request a refund?"),newChoiceDecisionQuestion("request_type","What is the main request?",[new("refund"),new("rebooking"),new("information")]),newScoreDecisionQuestion("frustration","How frustrated is the customer?",[new("calm"),new("concerned"),new("angry")]),]));varrefund=(BinaryDecisionAnswer)response.Answers["refund_requested"];// refund.TrueProbability
changed the title [-].NET: [Feature]: Add IDecisionClient (reference of dotnet/extensions#7764), DecisionLoopEvaluator, and a TypeSafe (Jev) provider package[/-][+]Python: .NET: [Feature]: Add IDecisionClient (reference of dotnet/extensions#7764), DecisionLoopEvaluator, and a TypeSafe (Jev) provider package[/+]on Sep 20, 2026
Description
Summary. Add first-class support for decision-oriented inference in .NET Agent Framework: a provider-neutral
IDecisionClient(an experimental reference implementation of the shape proposed forMicrosoft.Extensions.AIin dotnet/extensions#7764), aDecisionLoopEvaluatorthat uses it to judge loop completion, and aMicrosoft.Agents.AI.TypeSafeprovider package for TypeSafe AI's Jev ("System One") model. An implementation with an ADR, tests, and a working sample is ready on a branch; this issue records the scope and the design questions for maintainers before the PR.Relationship to existing issues. #8545 asks for the same integration but proposes waiting for the MEAI abstraction and adding nothing to MAF meanwhile. #8556 asks for Jev support in the Python SDK. This issue is the .NET counterpart of #8556 and a concrete, implementable variant of #8545: the upstream proposal is a day-old, untriaged community issue with no maintainer response, and MEAI 10.10.0 (the version this repository references) contains no decision types, so gating on it blocks everything, including calibration work and evaluation frameworks that want one shared contract.
What a decision model is, and why it is not an
IChatClientA decision model does not generate text. It takes a piece of state plus one or more bounded, typed questions and returns typed probabilistic answers in one call:
P(true)for a proposition (Jev:noul), no separate confidence;choice);score).Prompting an
IChatClientfor{"answered": true}gives syntactic structure; it does not give the probability, the distribution, batching of heterogeneous questions against one state, or a closed output domain declared before inference. Several MAF decision points are exactly this shape: should the loop continue, is the task complete, which authorized tools or Skills are relevant, which participant acts next, should a result be escalated. Jev is fast and cheap relative to a generative judge (vendor: $0.042 per million input tokens, output free), which matters for control-plane decisions that run on every iteration.Proposed design
Microsoft.Agents.AI.Abstractions,[Experimental(MAAI001)], mirroring [API Proposal]: Add a provider-neutral abstraction for decision-oriented AI models dotnet/extensions#7764 name for name:IDecisionClient : IDisposable(GetResponseAsync(DecisionRequest, DecisionOptions?, ct),GetService),DecisionRequest(JsonElement State,IList<DecisionQuestion> Questions),DecisionOptions,DecisionQuestionwithBinaryDecisionQuestion/ChoiceDecisionQuestion/ScoreDecisionQuestion,DecisionResponse(answers keyed by question id,ModelId,UsageDetails),DecisionAnswerwithBinaryDecisionAnswer/ChoiceDecisionAnswer/ScoreDecisionAnswer,DecisionClientMetadata, and aGetResponseAsync<TState>(state, JsonTypeInfo<TState>, ...)extension. Two additions beyond the proposal, offered upstream too: a classifiedDecisionClientException(Authentication,InvalidRequest,RateLimited,Overloaded,ProviderUnavailable,InvalidResponse,Unknown;IsTransient), and range validation on answers so an out-of-range probability cannot exist as an object. The types are a staging ground: when MEAI ships an equivalent, they are deleted and consumers retarget the namespace. MAF does not evolve the shape independently.DecisionLoopEvaluator : LoopEvaluatorinMicrosoft.Agents.AI, next toAIJudgeLoopEvaluator. After each iteration it asks one binary question ("Has the agent fully addressed the user's original request?") against a minimal, source-generated text projection of the loop state and applies a configurable completion threshold (default 0.90). It continues with a deterministic feedback message rather than model prose. Failure policy:Throw(default),Continue, orDeferToNextEvaluator; provider failure is never interpreted as "incomplete"; cancellation always propagates; non-text request content is rejected unless aStateFactoryis supplied. BecauseLoopAgentevaluates evaluators in order and stops only when all returnStop,[DecisionLoopEvaluator, AIJudgeLoopEvaluator]is a cheap-then-strong cascade with no new abstraction: the generative judge runs only when the decision model believes the work is complete.Microsoft.Agents.AI.TypeSafe:TypeSafeDecisionClientoverPOST https://api.typesafe.ai/v1/systemone(or OpenRouter's relay), strict parsing, HTTP failure classification, no silent retries, API key never in exception messages, feature-usage index 75. Follows the existing provider-package precedent (.OpenAI,.Foundry,.CopilotStudio).AIContextProvider,AgentSkillsProvider,GroupChatManager) later; a decision model may shortlist among already-authorized candidates but never authorize or bypass approval.Status
Implemented on a fork branch (
joslat/adr-0042-decision-loop-evaluator) with ADR-0042, PublicAPI baselines for all target frameworks, 45 evaluator test cases, 47 provider test cases, the feature-registry validation, and aHarness_Step06_DecisionLoopsample. Verified live against Jevjev-1.13.0with an OpenAI-compatible primary model: the cascade finished a three-part task in four iterations with a single generative judge call; a mixed batch returned a binary probability, a choice distribution, and a weighted score in one call.Questions for maintainers
Microsoft.Agents.AI.Abstractions(deleted when MEAI ships), or should it live in a satellite package such asMicrosoft.Agents.AI.Decisions?Microsoft.Agents.AI.TypeSafethe right home for the provider, or should it be provider-owned from the start?DecisionClientExceptionand answer validation be proposed to [API Proposal]: Add a provider-neutral abstraction for decision-oriented AI models dotnet/extensions#7764 as part of the contract?AIJudgeLoopEvaluator; a rejected key is not evidence of incompleteness) and adds a separateTransientFailureBehaviorfor rate limits, overload, and outages, which is what .NET: [Feature]: Integrate Microsoft.Extensions.AI decision-model inference into agent decision points #8545's concern is really about. It also adopts .NET: [Feature]: Integrate Microsoft.Extensions.AI decision-model inference into agent decision points #8545's observability point: an optionalILoggerFactoryyields one debug line per decision (iteration, probability, threshold, outcome) and a warning when a failure policy is applied, never the state. Is that split acceptable?Code Sample
Language/SDK
.NET