Loading...
Loading...
Guides technology selection and implementation of AI and ML features in .NET 8+ applications using ML.NET, Microsoft.Extensions.AI (MEAI), Microsoft Agent Framework (MAF), GitHub Copilot SDK, ONNX Runtime, and OllamaSharp. Covers the full spectrum from classic ML through modern LLM orchestration to local inference. Use when adding classification, regression, clustering, anomaly detection, recommendation, LLM integration (text generation, summarization, reasoning), RAG pipelines with vector search, agentic workflows with tool calling, Copilot extensions, or custom model inference via ONNX Runtime to a .NET project. DO NOT USE FOR projects targeting .NET Framework (requires .NET 8+), the task is pure data engineering or ETL with no ML/AI component, or the project needs a custom deep learning training loop (use Python with PyTorch/TensorFlow, then export to ONNX for .NET inference).
npx skill4agent add dotnet/skills technology-selection| Input | Required | Description |
|---|---|---|
| Task description | Yes | What the AI/ML feature should accomplish (e.g., "classify support tickets", "summarize documents") |
| Data description | Yes | Type and shape of input data (structured/tabular, unstructured text, images, mixed) |
| Deployment constraints | No | Cloud vs. local, latency SLO, cost budget, offline requirements |
| Existing project context | No | Current .csproj, existing packages, target framework |
| Task type | Technology | Rationale |
|---|---|---|
| Structured/tabular data: classification, regression, clustering, anomaly detection, recommendation | ML.NET ( | Reproducible (given a fixed seed and dataset), no cloud dependency, purpose-built models for these tasks |
| Natural language understanding, generation, summarization, reasoning over unstructured text (single prompt → response, no tool calling) | LLM via Microsoft.Extensions.AI ( | Requires language model capabilities beyond pattern matching; no orchestration needed |
| Agentic workflows: tool/function calling, multi-step reasoning, agent loops, multi-agent collaboration | Microsoft Agent Framework ( | Requires orchestration, tool dispatch, iteration control, and guardrails that |
| Building GitHub Copilot extensions, custom agents, or developer workflow tools | GitHub Copilot SDK ( | Integrates with the Copilot agent runtime for IDE and CLI extensibility |
| Running a pre-trained or fine-tuned custom model in production | ONNX Runtime ( | Hardware-accelerated inference, model-format agnostic |
| Local/offline LLM inference with no cloud dependency | OllamaSharp with local AI models supported by Ollama | Privacy-sensitive, air-gapped, or cost-constrained scenarios |
| Semantic search, RAG, or embedding storage | Microsoft.Extensions.VectorData.Abstractions + a vector database provider (e.g., Azure AI Search, Milvus, MongoDB, pgvector, Pinecone, Qdrant, Redis, SQL) | Provider-agnostic abstractions for vector similarity search; pair with a database-specific connector package (many are moving to community toolkits) |
| Ingesting, chunking, and loading documents into a vector store | Microsoft.Extensions.AI.DataIngestion (preview) + Microsoft.Extensions.VectorData.Abstractions (MEVD) | Handles document parsing, text chunking, embedding generation, and upserting into a vector database; pairs with Microsoft.Extensions.VectorData.Abstractions |
| Both structured ML predictions AND natural language reasoning | Hybrid: ML.NET for predictions + LLM for reasoning layer | Keep loosely coupled; ML.NET handles reproducible scoring, LLM adds explanation |
| Layer | Library | NuGet package | Use when |
|---|---|---|---|
| Abstraction | Microsoft.Extensions.AI (MEAI) | | You need a provider-agnostic interface for chat, embeddings, or tool calling. This is the foundation — always include it. Use |
| Provider SDK | OpenAI, Azure.AI.OpenAI, Azure.AI.Inference, OllamaSharp | | You need a concrete LLM provider implementation. These wire into MEAI via |
| Orchestration | Microsoft Agent Framework | | The task involves tool/function calling, agentic loops, multi-step reasoning, multi-agent coordination, durable context, or graph-based workflows. This is required whenever the scenario involves agents or tools — do not hand-roll tool dispatch loops with |
| Copilot integration | GitHub Copilot SDK | | You are building extensions or tools that integrate with the GitHub Copilot runtime — custom agents, IDE extensions, or developer workflow automation that leverages the Copilot agent platform. |
Microsoft.Extensions.AIIChatClientIEmbeddingGeneratorOpenAIAzure.AI.OpenAIMicrosoft.Agents.AIMicrosoft.Agents.AIIChatClientGitHub.Copilot.SDKHttpClient<PackageReference Include="Microsoft.ML" Version="4.*" />
<PackageReference Include="Microsoft.ML.AutoML" Version="0.*" />
<!-- Only if custom numerical work is needed: -->
PackageReference Include="System.Numerics.Tensors" Version="10.*"
<PackageReference Include="MathNet.Numerics" Version="5.*" />
<!-- Only for data exploration: -->
<PackageReference Include="Microsoft.Data.Analysis" Version="0.*" />Do NOT use Accord.NET — it is archived and unmaintained.
<!-- Always start with the abstraction layer -->
<PackageReference Include="Microsoft.Extensions.AI" Version="9.*" />
<!-- Orchestration (agents, workflows, tools, memory) — prerelease; use dotnet add package Microsoft.Agents.AI --prerelease -->
<PackageReference Include="Microsoft.Agents.AI" Version="1.*-*" />
<!-- Cloud LLM provider (pick one) -->
<PackageReference Include="Azure.AI.OpenAI" Version="2.*" />
<!-- OR -->
<PackageReference Include="OpenAI" Version="2.*" />
<!-- Client-side token counting for cost management -->
<PackageReference Include="Microsoft.ML.Tokenizers" Version="2.*"
<!-- Local LLM inference -->
<PackageReference Include="OllamaSharp" Version="5.*" />
<!-- Custom model inference -->
<PackageReference Include="Microsoft.ML.OnnxRuntime" Version="1.*" />
<!-- Vector store abstraction -->
<PackageReference Include="Microsoft.Extensions.VectorData.Abstractions" Version="9.*" />
<!-- Document ingestion, chunking, and vector store loading (preview) -->
<PackageReference Include="Microsoft.Extensions.AI.DataIngestion" Version="9.*-*" />
<!-- Copilot platform extensibility -->
<PackageReference Include="GitHub.Copilot.SDK" Version="1.*" />Stack coherence rule: Never mix raw SDK calls (to OpenAI) withHttpClient, Microsoft Agent Framework, or Copilot SDK in the same workflow. Pick one abstraction layer per workflow boundary and commit to it. See Step 1b for the layering rules.Microsoft.Extensions.AI
// Configuration via IOptions<T>
services.Configure<AiOptions>(configuration.GetSection("AI"));
// Register the AI client through the abstraction
services.AddChatClient(builder => builder
.UseOpenAIChatClient("gpt-4o-mini-2024-07-18"));var mlContext = new MLContext(seed: 42);var split = mlContext.Data.TrainTestSplit(data, testFraction: 0.2);var metrics = mlContext.BinaryClassification.Evaluate(predictions);
logger.LogInformation("AUC: {Auc:F4}, F1: {F1:F4}", metrics.AreaUnderRocCurve, metrics.F1Score);mlContext.Auto()services.AddPredictionEnginePool<ModelInput, ModelOutput>()
.FromFile(modelPath);0var options = new ChatOptions
{
Temperature = 0f,
MaxOutputTokens = 1024,
};var result = await chatClient.GetResponseAsync<MySchema>(prompt, options, cancellationToken);services.AddChatClient(builder => builder
.UseOpenAIChatClient(modelId)
.Use(new RetryingChatClient(maxRetries: 3)));var apiKey = configuration["AI:ApiKey"]
?? throw new InvalidOperationException("AI:ApiKey not configured");// Pin to a specific dated version, not just "gpt-4o"
var modelId = "gpt-4o-2024-08-06";Microsoft.Agents.AIIChatClientChatClientAgentAgentWorkerMicrosoft.Agents.AIvar settings = new AgentInvokeOptions
{
MaximumIterations = 10,
};message.Contentawait foreach (var message in agent.InvokeStreamingAsync(history, settings))
{
logger.LogDebug("Agent step: Role={Role}, ContentLength={Length}",
message.Role, message.Content?.Length ?? 0);
}var results = await vectorStore.SearchAsync(query, new VectorSearchOptions
{
Top = 5,
MinimumScore = 0.75f,
});var response = await chatClient.GetResponseAsync<ClassificationResult>(prompt, options);
if (response is null || !response.IsValid())
{
logger.LogWarning("LLM returned invalid response, falling back to rule-based classifier");
return ruleBasedClassifier.Classify(input);
}gpt-4o-2024-08-06IHttpClientFactoryIAsyncEnumerableawait foreach (var update in chatClient.GetStreamingResponseAsync(prompt, options))
{
yield return update.Text;
}services.AddHealthChecks()
.AddCheck<OpenAIHealthCheck>("openai");PredictionEnginePool<TIn, TOut>PredictionEnginedotnet build -c Release -warnaserrordotnet test -c ReleaseIOptions<T>dotnet build -c Release -warnaserror| Anti-pattern | Redirect |
|---|---|
| Using an LLM for classification on structured/tabular data | Use ML.NET instead — it is faster, cheaper, and deterministic |
| Calling LLM APIs without retry or timeout logic | Add |
Storing API keys in | Use user-secrets (dev), environment variables, or Azure Key Vault (prod) |
| Using Accord.NET for new projects | Migrate to ML.NET — Accord.NET is archived and unmaintained |
| Building custom neural networks in .NET from scratch | Use a pre-trained model via ONNX Runtime or call an LLM API |
| RAG without chunking strategy or relevance filtering | Implement semantic chunking and set a minimum similarity score threshold |
| Agentic loops without iteration limits or cost ceilings | Add |
Using MEAI | Pick one abstraction layer and commit to it |
Implementing tool calling or agentic loops manually with | Use |
| Using Agent Framework for a single prompt→response call | Use MEAI |
| Using Copilot SDK for general-purpose LLM apps | Copilot SDK is for Copilot platform extensions only — use MEAI + Agent Framework for standalone apps |
| Calling OpenAI SDK directly in business logic instead of through MEAI | Register the provider via |
Using | Use |
Using | Define a custom delegate type — ref structs cannot be generic type arguments |
Using | Use |
| Pitfall | Solution |
|---|---|
| Over-engineering with LLMs | Start with the simplest approach (rules, ML.NET) and add LLM capability only when simpler methods fall short |
| Evaluating ML models on training data | Always use |
| LLM output drift between deployments | Pin to specific dated model versions (e.g., |
| Token cost surprises | Set |
| Non-reproducible ML training | Set |
| RAG returning irrelevant context | Set a minimum similarity score and limit the number of injected chunks |
| Cold start latency on ML.NET models | Pre-warm the |
| Microsoft Agent Framework + raw OpenAI SDK in same class | Choose one orchestration layer per workflow boundary |