Repository navigation
Release v3.2.0
Summary
Decision Making joins the generative capabilities as a first-class AI capability. A caller supplies a context and a finite set of outcomes; the provider returns a probability distribution over exactly those outcomes. Nothing is generated.
It also adds the Decision Engine service itself — a small CPU-first inference service — under Source/DecisionEngine/.
Added
IDecisions— submit context plus a finite set of choices, get back every choice with its probability, the highest-probability choice, and the margin to the runner-up. Thresholds are deliberately left to consumers so the raw distribution survives intact (#392)- A batch overload on
IDecisionsfor callers scoring many candidates against one task, with results guaranteed in request order (#392) Decisionas anAIProviderCapabilityand anAIModelCapability, advertised independently of the conversational and agentic capabilities (#392)AIProviderType.DecisionEngineandAddDecisionEngineProvider/ReconfigureDecisionEngineProviderfor configuring decision providers the same way as any other AI provider (#392)AIModelCapabilities.For(AIProviderType, ModelName)— capability for a decision model is declared by provider type rather than inferred from the model identifier, which carries no marker that would distinguish it from a chat model (#392)AIProviderCapabilities— what each provider type can be used for. A decision engine advertisesDecisionand neitherConversationalnorAgentic, so existing compatibility checks refuse to schedule an agent onto it (#392)AddCratisAI(ai => ai.WithDecisions<TResolver>())registers the decision surface. Nothing decision-related is registered when it is not called (#392)- Telemetry on
Cratis.AI.Decisions: decision duration, count, and top-probability distribution. Context text is not recorded unless explicitly enabled (#392) - The Cratis Decision Engine service under
Source/DecisionEngine/— Decision API v1, CPU-first, model and calibration temperature configurable, with an artifact cache so restarts do not re-download weights (#392)
Changed
ConfiguredAIProvidernow projects the Decision Engine provider events (#392)
Notes for reviewers
Three enums gained a member and all three are persisted in events — appended, never renumbered. AIProviderCapability.Decision = 2, AIModelCapability.Decision = 4, AIProviderType.DecisionEngine = 6.
Why scoring rather than generating. The service scores each choice by mean per-token log-likelihood conditioned on a prompt that includes the full option set, then softmaxes. Asking a 0.5B model to emit the answer would give one label and a self-reported confidence worth nothing; scoring gives a real distribution for one short forward pass per choice. Mean rather than summed log-likelihood, or longer choices would lose on length alone.
What is deliberately absent. No thresholds, no fallback, no retry policy anywhere in this package — those differ per workflow, and centralizing them would both force one answer on every consumer and destroy the signal that later calibration depends on.
Verification. dotnet build -c Release clean; dotnet test 292/292 passing (Cratis.AI.Specs); pytest 20/20 passing (Source/DecisionEngine). The service has not yet been run against real weights — that happens in Cratis/Infrastructure#58, where it is deployed and benchmarked.