{
    "version": "https://jsonfeed.org/version/1",
    "title": "LogicGrid Blog",
    "home_page_url": "https://logicgrid.dev/blog",
    "description": "Articles about building AI agents in .NET",
    "items": [
        {
            "id": "https://logicgrid.dev/blog/introducing-logicgrid",
            "content_html": "<p>We're launching <strong>LogicGrid</strong> — a .NET-native framework for building multi-agent AI systems. It's been ten months in the making, and today the beta is on NuGet.</p>\n<p>This post is the \"why we built this\" version. If you'd rather just see code, jump straight to the <a class=\"\" href=\"https://logicgrid.dev/docs/getting-started/quickstart\">Quickstart</a> — five minutes from zero to a running agent.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-problem\">The problem<a href=\"https://logicgrid.dev/blog/introducing-logicgrid#the-problem\" class=\"hash-link\" aria-label=\"Direct link to The problem\" title=\"Direct link to The problem\" translate=\"no\">​</a></h2>\n<p>We needed to build an AI feature for a regulated environment where customer data couldn't leave the network. Two requirements that turned out to be in tension:</p>\n<ol>\n<li class=\"\">We were on .NET. Migrating to Python was a non-starter.</li>\n<li class=\"\">We needed local LLMs. Cloud providers were off the table for compliance reasons.</li>\n</ol>\n<p>We tried the obvious frameworks:</p>\n<ul>\n<li class=\"\"><strong>Semantic Kernel</strong> worked, but the path for local LLMs felt like it had been added late. Most of the documentation, examples, and ergonomics were Azure-first.</li>\n<li class=\"\"><strong>LangChain.NET</strong> worked for prototypes, but it lagged the Python version in features and the integration coverage was thin.</li>\n<li class=\"\"><strong>Rolling our own</strong> worked too — but every team should not have to rebuild agent orchestration from scratch.</li>\n</ul>\n<p>So we built LogicGrid: the framework we wished existed.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"whats-different\">What's different<a href=\"https://logicgrid.dev/blog/introducing-logicgrid#whats-different\" class=\"hash-link\" aria-label=\"Direct link to What's different\" title=\"Direct link to What's different\" translate=\"no\">​</a></h2>\n<p>Three things distinguish LogicGrid from what's already out there:</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"1-local-llms-are-first-class\">1. Local LLMs are first-class<a href=\"https://logicgrid.dev/blog/introducing-logicgrid#1-local-llms-are-first-class\" class=\"hash-link\" aria-label=\"Direct link to 1. Local LLMs are first-class\" title=\"Direct link to 1. Local LLMs are first-class\" translate=\"no\">​</a></h3>\n<p>Same code runs against Ollama, vLLM, LM Studio, TEI, OpenAI, Anthropic, Gemini, or any OpenAI-compatible endpoint. Switching providers is a one-line change:</p>\n<div class=\"language-csharp codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-csharp codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> llm </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> LlmClientBase</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">Ollama</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"llama3.2\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:rgb(106, 153, 85)\">// var llm = LlmClientBase.OpenAI(\"gpt-4o\");</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:rgb(106, 153, 85)\">// var llm = LlmClientBase.Anthropic(\"claude-sonnet-4-6\");</span><br></div></code></pre></div></div>\n<p>There's no second-tier path for local providers. The streaming protocol, tool calling, and embeddings work identically across all of them.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"2-observability-is-built-in\">2. Observability is built in<a href=\"https://logicgrid.dev/blog/introducing-logicgrid#2-observability-is-built-in\" class=\"hash-link\" aria-label=\"Direct link to 2. Observability is built in\" title=\"Direct link to 2. Observability is built in\" translate=\"no\">​</a></h3>\n<p>Every agent step, tool call, retry, and LLM call emits a structured event. Token counts, timings, errors, tool arguments — all of it, no extra code:</p>\n<div class=\"language-csharp codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-csharp codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> ctx </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">AgentContext</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">WithLogging</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">WithTracing</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">out</span><span class=\"token plain\"> </span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> trace</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> agent</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">RunAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"...\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> ctx</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><br></div></code></pre></div></div>\n<p>Pipe it to a console, file, or OpenTelemetry collector. When a customer reports a bad answer, you can pull up the full trace. No black boxes.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"3-zero-hidden-runtime-dependencies\">3. Zero hidden runtime dependencies<a href=\"https://logicgrid.dev/blog/introducing-logicgrid#3-zero-hidden-runtime-dependencies\" class=\"hash-link\" aria-label=\"Direct link to 3. Zero hidden runtime dependencies\" title=\"Direct link to 3. Zero hidden runtime dependencies\" translate=\"no\">​</a></h3>\n<p>LogicGrid targets <code>netstandard2.0</code>, <code>net6.0</code>, and <code>net8.0</code>. The full SBOM ships in <a href=\"https://github.com/logicgrid-dev/LogicGrid\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">the public repo</a> as <code>bom.json</code>. The dependency graph is small enough that you can audit every package before it touches your build server.</p>\n<p>This matters for air-gapped enterprise deployments where every transitive dependency is a question to answer.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"whats-in-the-box\">What's in the box<a href=\"https://logicgrid.dev/blog/introducing-logicgrid#whats-in-the-box\" class=\"hash-link\" aria-label=\"Direct link to What's in the box\" title=\"Direct link to What's in the box\" translate=\"no\">​</a></h2>\n<p>The framework is split across five NuGet packages so you only pull in what you need:</p>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">dotnet </span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">add</span><span class=\"token plain\"> package LogicGrid.Core     </span><span class=\"token comment\" style=\"color:rgb(106, 153, 85)\"># Agents, admins, orchestration, events</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">dotnet </span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">add</span><span class=\"token plain\"> package LogicGrid.Memory   </span><span class=\"token comment\" style=\"color:rgb(106, 153, 85)\"># Vector stores, embeddings, hybrid search</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">dotnet </span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">add</span><span class=\"token plain\"> package LogicGrid.Rag      </span><span class=\"token comment\" style=\"color:rgb(106, 153, 85)\"># Full RAG pipeline</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">dotnet </span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">add</span><span class=\"token plain\"> package LogicGrid.Tools    </span><span class=\"token comment\" style=\"color:rgb(106, 153, 85)\"># Tool / function calling</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">dotnet </span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">add</span><span class=\"token plain\"> package LogicGrid.Mcp      </span><span class=\"token comment\" style=\"color:rgb(106, 153, 85)\"># MCP (Model Context Protocol) client</span><br></div></code></pre></div></div>\n<p>Highlights:</p>\n<ul>\n<li class=\"\"><strong>Multi-agent orchestration</strong> — Sequential, GroupChat, Graph, Parallel, MapReduce, Reflexion</li>\n<li class=\"\"><strong>Hybrid search</strong> — BM25 + dense retrieval fused with Reciprocal Rank Fusion. Beats either alone for codes, IDs, proper nouns</li>\n<li class=\"\"><strong>Tool calling</strong> — Define tools as plain C# methods with attributes. Schema is generated for you</li>\n<li class=\"\"><strong>MCP client</strong> — Talk to any MCP server, stdio or HTTP, including resumable sessions</li>\n<li class=\"\"><strong>Observability</strong> — Structured events, console / file / OTel sinks, run tracing for audit</li>\n</ul>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"a-5-minute-example\">A 5-minute example<a href=\"https://logicgrid.dev/blog/introducing-logicgrid#a-5-minute-example\" class=\"hash-link\" aria-label=\"Direct link to A 5-minute example\" title=\"Direct link to A 5-minute example\" translate=\"no\">​</a></h2>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">dotnet </span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">add</span><span class=\"token plain\"> package LogicGrid.Core</span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">ollama pull llama3.2</span><br></div></code></pre></div></div>\n<div class=\"language-csharp codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-csharp codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">using</span><span class=\"token plain\"> </span><span class=\"token namespace\">LogicGrid</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Core</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Agents</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">using</span><span class=\"token plain\"> </span><span class=\"token namespace\">LogicGrid</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Core</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> llm </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> LlmClientBase</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">Ollama</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"llama3.2\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name\" style=\"color:rgb(78, 201, 176)\">IAgent</span><span class=\"token plain\"> agent </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">Agent</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&lt;</span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&gt;</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">name</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Helper\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">description</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Answers questions concisely.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">systemPrompt</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Answer in one short sentence.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">Console</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">WriteLine</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> agent</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">RunAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"What is the capital of France?\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">AgentContext</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"ask\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><br></div></code></pre></div></div>\n<p>Three using statements. Four logical lines. No <code>appsettings.json</code> ritual, no DI registration dance.</p>\n<p>When you outgrow a single agent, the multi-agent patterns are right there:</p>\n<div class=\"language-csharp codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-csharp codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> admin </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">GroupChatAdmin</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&lt;</span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\"> </span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&gt;</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">name</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Editorial\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">llmClient</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">agents</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">[</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">]</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token plain\"> researcher</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> writer</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> critic </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">Console</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">WriteLine</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> admin</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">RunAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Explain RRF in 200 words.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><br></div></code></pre></div></div>\n<p>The <a class=\"\" href=\"https://logicgrid.dev/docs/getting-started/quickstart\">Quickstart</a> walks through the rest.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"whats-next\">What's next<a href=\"https://logicgrid.dev/blog/introducing-logicgrid#whats-next\" class=\"hash-link\" aria-label=\"Direct link to What's next\" title=\"Direct link to What's next\" translate=\"no\">​</a></h2>\n<p>LogicGrid is at <code>0.1.3-beta</code> today. The core API is stable enough that we're building production systems on it, and after months of external feedback we're moving to beta.</p>\n<p>The roadmap toward beta and 1.0:</p>\n<ul>\n<li class=\"\">More providers (xAI, Cohere, Bedrock)</li>\n<li class=\"\">More document loaders (PDF beyond text extraction, structured Office docs)</li>\n<li class=\"\">More vector store integrations (pgvector, Qdrant, Weaviate first-party)</li>\n<li class=\"\">A persistent memory store backed by SQLite</li>\n<li class=\"\">Real-world performance benchmarks</li>\n</ul>\n<p>If you try it and something is missing or broken, <a href=\"https://github.com/logicgrid-dev/LogicGrid/issues\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">open an issue</a> or jump into <a href=\"https://github.com/logicgrid-dev/LogicGrid/discussions\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">discussions</a>. Early-adopter feedback shapes what we ship next.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"how-logicgrid-fits-with-whats-already-out-there\">How LogicGrid fits with what's already out there<a href=\"https://logicgrid.dev/blog/introducing-logicgrid#how-logicgrid-fits-with-whats-already-out-there\" class=\"hash-link\" aria-label=\"Direct link to How LogicGrid fits with what's already out there\" title=\"Direct link to How LogicGrid fits with what's already out there\" translate=\"no\">​</a></h2>\n<p>If you're already happy with Semantic Kernel or LangChain.NET, that's great — keep using them. We didn't build LogicGrid to replace them; we built it because we needed something different.</p>\n<p>For a side-by-side, see <a class=\"\" href=\"https://logicgrid.dev/blog/langchain-vs-semantic-kernel-vs-logicgrid\">LangChain vs Semantic Kernel vs LogicGrid</a>.</p>\n<p>If you're frustrated by Semantic Kernel's posture toward local LLMs, see <a class=\"\" href=\"https://logicgrid.dev/blog/semantic-kernel-alternative-for-dotnet\">A Semantic Kernel Alternative for .NET</a>.</p>\n<p>If you're new to the whole space, <a class=\"\" href=\"https://logicgrid.dev/blog/how-to-use-ollama-with-csharp\">How to use Ollama with C#</a> is the gentlest on-ramp.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"try-it\">Try it<a href=\"https://logicgrid.dev/blog/introducing-logicgrid#try-it\" class=\"hash-link\" aria-label=\"Direct link to Try it\" title=\"Direct link to Try it\" translate=\"no\">​</a></h2>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">dotnet </span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">add</span><span class=\"token plain\"> package LogicGrid.Core</span><br></div></code></pre></div></div>\n<p>Five minutes from zero to a running agent. If it doesn't fit your stack, you'll know quickly. If it does, the <a class=\"\" href=\"https://logicgrid.dev/docs/getting-started/quickstart\">docs</a> walk you through everything else.</p>\n<p>Thanks for reading. We're excited to see what people build.</p>",
            "url": "https://logicgrid.dev/blog/introducing-logicgrid",
            "title": "Introducing LogicGrid — Multi-Agent AI Orchestration for .NET",
            "summary": "Why we built LogicGrid, what's different about it, and how it fits alongside Semantic Kernel and LangChain.NET. With a 5-minute walkthrough.",
            "date_modified": "2026-04-25T00:00:00.000Z",
            "author": {
                "name": "LogicGrid Team",
                "url": "https://logicgrid.dev"
            },
            "tags": [
                "announcement",
                "dotnet",
                "csharp",
                "ai-agents",
                "llm"
            ]
        },
        {
            "id": "https://logicgrid.dev/blog/multi-agent-framework-for-dotnet",
            "content_html": "<p>If you've spent any time building with LLMs, you've probably hit the wall: a single prompt only gets you so far. Stuff too much into one prompt and the model loses the plot. Try to do too many things at once and you get inconsistent output.</p>\n<p>The answer most teams converge on is <strong>multi-agent architectures</strong> — multiple specialized agents, each with a focused role, coordinated by an orchestrator. This post covers when and why to reach for multi-agent in .NET, what patterns work, and how to build them without losing your mind.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"why-multi-agent\">Why multi-agent?<a href=\"https://logicgrid.dev/blog/multi-agent-framework-for-dotnet#why-multi-agent\" class=\"hash-link\" aria-label=\"Direct link to Why multi-agent?\" title=\"Direct link to Why multi-agent?\" translate=\"no\">​</a></h2>\n<p>Single-agent systems work great for narrow tasks: summarize this, translate that, classify the other. But when the task has multiple steps with different cognitive loads, single-agent breaks down.</p>\n<p>Consider: \"Research recent advances in retrieval-augmented generation, write a 500-word summary, and check it for factual accuracy.\" That's three jobs:</p>\n<ul>\n<li class=\"\"><strong>Research</strong> — needs broad context, can use tools, ok to be slow</li>\n<li class=\"\"><strong>Writing</strong> — needs focused context, ok to be fast, no tools needed</li>\n<li class=\"\"><strong>Fact-checking</strong> — needs verifying mindset, can use tools, narrow context</li>\n</ul>\n<p>Cram all three into one prompt and you get a mediocre version of each. Split them into three agents and each one does its job well.</p>\n<p>That's the multi-agent pitch in one sentence: <strong>specialization beats generalization, even at the prompt level.</strong></p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"when-not-to-use-multi-agent\">When NOT to use multi-agent<a href=\"https://logicgrid.dev/blog/multi-agent-framework-for-dotnet#when-not-to-use-multi-agent\" class=\"hash-link\" aria-label=\"Direct link to When NOT to use multi-agent\" title=\"Direct link to When NOT to use multi-agent\" translate=\"no\">​</a></h2>\n<p>Before getting excited, the honest answer: most production AI features should be single-agent. Multi-agent adds:</p>\n<ul>\n<li class=\"\"><strong>Latency</strong> — each agent is an LLM call. Three agents means 3x the wall-clock time.</li>\n<li class=\"\"><strong>Cost</strong> — same math, 3x the tokens.</li>\n<li class=\"\"><strong>Failure modes</strong> — any agent in the chain can fail or hallucinate, and downstream agents have to handle it.</li>\n<li class=\"\"><strong>Debugging complexity</strong> — when something goes wrong, which agent caused it?</li>\n</ul>\n<p>If you can solve your problem with one well-crafted prompt and a structured output, do that. Multi-agent is for problems you genuinely can't fit into one head.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-patterns\">The patterns<a href=\"https://logicgrid.dev/blog/multi-agent-framework-for-dotnet#the-patterns\" class=\"hash-link\" aria-label=\"Direct link to The patterns\" title=\"Direct link to The patterns\" translate=\"no\">​</a></h2>\n<p>There are five practical patterns. Each maps to a different problem shape.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"1-sequential\">1. Sequential<a href=\"https://logicgrid.dev/blog/multi-agent-framework-for-dotnet#1-sequential\" class=\"hash-link\" aria-label=\"Direct link to 1. Sequential\" title=\"Direct link to 1. Sequential\" translate=\"no\">​</a></h3>\n<p>The simplest pattern. Output of agent A → input of agent B → input of agent C. Use when steps are linear and each depends on the previous.</p>\n<div class=\"language-csharp codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-csharp codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">using</span><span class=\"token plain\"> </span><span class=\"token namespace\">LogicGrid</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Core</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Admins</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> admin </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">SequentialAdmin</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&lt;</span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\"> </span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&gt;</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">name</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Pipeline\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">llmClient</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">agents</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">IAgent</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">[</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">]</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token plain\"> researcher</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> writer</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> editor </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> result </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> admin</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">RunAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Topic: Reciprocal Rank Fusion\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><br></div></code></pre></div></div>\n<p><strong>Best for</strong>: ETL-like flows, structured pipelines, document transformation.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"2-group-chat\">2. Group chat<a href=\"https://logicgrid.dev/blog/multi-agent-framework-for-dotnet#2-group-chat\" class=\"hash-link\" aria-label=\"Direct link to 2. Group chat\" title=\"Direct link to 2. Group chat\" translate=\"no\">​</a></h3>\n<p>Multiple agents share a conversation. An admin (often an LLM) decides who speaks next based on what the agents have said so far.</p>\n<div class=\"language-csharp codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-csharp codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> admin </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">GroupChatAdmin</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&lt;</span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\"> </span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&gt;</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">name</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Editorial\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">llmClient</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">agents</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">IAgent</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">[</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">]</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token plain\"> researcher</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> writer</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> critic </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">options</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">AdminOptions</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token plain\"> MaxLoops </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(181, 206, 168)\">10</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> article </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> admin</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">RunAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Explain hybrid search in 200 words.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><br></div></code></pre></div></div>\n<p>The admin LLM picks an agent, that agent contributes, then the admin picks again. The loop ends when the admin decides the task is done (often when a critic responds with \"DONE\").</p>\n<p><strong>Best for</strong>: open-ended creative tasks, debates, brainstorming, code review.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"3-graph-dag\">3. Graph (DAG)<a href=\"https://logicgrid.dev/blog/multi-agent-framework-for-dotnet#3-graph-dag\" class=\"hash-link\" aria-label=\"Direct link to 3. Graph (DAG)\" title=\"Direct link to 3. Graph (DAG)\" translate=\"no\">​</a></h3>\n<p>Each agent is a node. Edges describe data flow and conditionals. Branching, merging, and conditional routing are first-class.</p>\n<div class=\"language-csharp codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-csharp codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">using</span><span class=\"token plain\"> </span><span class=\"token namespace\">LogicGrid</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Core</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Graph</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> graph </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> AgentGraphBuilder</span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">Start</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\">classifier</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">ThenIf</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\">classifier</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> technicalAgent</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">        </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">condition</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> r </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=&gt;</span><span class=\"token plain\"> r</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">Contains</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"technical\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">ThenIf</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\">classifier</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> friendlyAgent</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">        </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">condition</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> r </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">!</span><span class=\"token plain\">r</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">Contains</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"technical\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">Then</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\">technicalAgent</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> formatter</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">Then</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\">friendlyAgent</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> formatter</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">Terminal</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\">formatter</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">Build</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> output </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> graph</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">RunAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Why is my deploy failing?\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><br></div></code></pre></div></div>\n<p><strong>Best for</strong>: complex workflows, conditional logic, fan-in/fan-out patterns. The pattern most production systems eventually grow into.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"4-parallel--map-reduce\">4. Parallel + Map-Reduce<a href=\"https://logicgrid.dev/blog/multi-agent-framework-for-dotnet#4-parallel--map-reduce\" class=\"hash-link\" aria-label=\"Direct link to 4. Parallel + Map-Reduce\" title=\"Direct link to 4. Parallel + Map-Reduce\" translate=\"no\">​</a></h3>\n<p>Run multiple agents in parallel and aggregate results.</p>\n<div class=\"language-csharp codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-csharp codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">using</span><span class=\"token plain\"> </span><span class=\"token namespace\">LogicGrid</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Core</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Admins</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> admin </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">ParallelAdmin</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&lt;</span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\"> </span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&gt;</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">name</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"MultiAnalyst\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">llmClient</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">agents</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">IAgent</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">[</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">]</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token plain\"> financialAnalyst</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> legalAnalyst</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> technicalAnalyst </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">aggregator</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> synthesizer</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> report </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> admin</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">RunAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Analyze this contract from three angles.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><br></div></code></pre></div></div>\n<p><strong>Best for</strong>: tasks where multiple perspectives need to be combined. Document analysis, code review, due diligence.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"5-reflexion-self-critique\">5. Reflexion (self-critique)<a href=\"https://logicgrid.dev/blog/multi-agent-framework-for-dotnet#5-reflexion-self-critique\" class=\"hash-link\" aria-label=\"Direct link to 5. Reflexion (self-critique)\" title=\"Direct link to 5. Reflexion (self-critique)\" translate=\"no\">​</a></h3>\n<p>An actor generates output. A critic evaluates it. If the critic approves, the run ends. If not, the actor retries with feedback. Loops until approved or <code>MaxIterations</code> is reached.</p>\n<div class=\"language-csharp codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-csharp codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> admin </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">ReflexionAdmin</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&lt;</span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\"> </span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&gt;</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">name</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Refiner\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">llmClient</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">actor</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> writer</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">critic</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> critic</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">options</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">ReflexionOptions</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token plain\"> MaxIterations </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(181, 206, 168)\">3</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> refined </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> admin</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">RunAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Write a marketing one-liner for our product.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><br></div></code></pre></div></div>\n<p><strong>Best for</strong>: tasks where quality matters more than speed. Marketing copy, code generation, summarization of high-stakes content.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"how-to-choose-a-pattern\">How to choose a pattern<a href=\"https://logicgrid.dev/blog/multi-agent-framework-for-dotnet#how-to-choose-a-pattern\" class=\"hash-link\" aria-label=\"Direct link to How to choose a pattern\" title=\"Direct link to How to choose a pattern\" translate=\"no\">​</a></h2>\n<p>Start by asking: <strong>what does my problem actually look like as a flowchart?</strong></p>\n<ul>\n<li class=\"\">One step? You don't need multi-agent.</li>\n<li class=\"\">A linear sequence of steps? <strong>Sequential</strong>.</li>\n<li class=\"\">Steps that depend on what previous steps said, in a non-deterministic way? <strong>Group chat</strong>.</li>\n<li class=\"\">Steps with branches and merges? <strong>Graph</strong>.</li>\n<li class=\"\">Multiple independent perspectives that combine? <strong>Parallel + aggregate</strong>.</li>\n<li class=\"\">One step but you want it to be really, really good? <strong>Reflexion</strong>.</li>\n</ul>\n<p>You can mix patterns. A graph node can be a group chat. A sequential pipeline can include a reflexion step at the end. The patterns compose.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"observability--the-part-nobody-talks-about\">Observability — the part nobody talks about<a href=\"https://logicgrid.dev/blog/multi-agent-framework-for-dotnet#observability--the-part-nobody-talks-about\" class=\"hash-link\" aria-label=\"Direct link to Observability — the part nobody talks about\" title=\"Direct link to Observability — the part nobody talks about\" translate=\"no\">​</a></h2>\n<p>Multi-agent systems are notoriously hard to debug. When the user gets a bad answer, was it the researcher's fault? The writer's? The critic's? The admin?</p>\n<p>The only way out is structured observability. Every agent step, every tool call, every retry, every LLM call should emit a structured event that you can query later.</p>\n<p>LogicGrid does this by default:</p>\n<div class=\"language-csharp codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-csharp codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> ctx </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">AgentContext</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">WithLogging</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">WithTracing</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">out</span><span class=\"token plain\"> </span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> trace</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> admin</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">RunAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Explain RRF in 200 words.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:rgb(106, 153, 85)\">// Inspect every step the admin and its agents took</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">foreach</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> span </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">in</span><span class=\"token plain\"> trace</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token plain\">Spans</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    Console</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">WriteLine</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token interpolation-string string\" style=\"color:rgb(206, 145, 120)\">$\"</span><span class=\"token interpolation-string interpolation punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token interpolation-string interpolation expression language-csharp\">span</span><span class=\"token interpolation-string interpolation expression language-csharp punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token interpolation-string interpolation expression language-csharp\">Name</span><span class=\"token interpolation-string interpolation punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token interpolation-string string\" style=\"color:rgb(206, 145, 120)\"> — </span><span class=\"token interpolation-string interpolation punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token interpolation-string interpolation expression language-csharp\">span</span><span class=\"token interpolation-string interpolation expression language-csharp punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token interpolation-string interpolation expression language-csharp\">Duration</span><span class=\"token interpolation-string interpolation expression language-csharp punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token interpolation-string interpolation expression language-csharp\">TotalMilliseconds</span><span class=\"token interpolation-string interpolation format-string punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token interpolation-string interpolation format-string\">F0</span><span class=\"token interpolation-string interpolation punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token interpolation-string string\" style=\"color:rgb(206, 145, 120)\">ms\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><br></div></code></pre></div></div>\n<p>Every event includes: agent name, run ID, timing, token count, tool calls, errors. Pipe it to a structured log, OpenTelemetry collector, or your own analytics.</p>\n<p>When a customer comes back with \"the agent gave a bad answer,\" you can pull up the full trace and see exactly what happened.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"cost-and-latency\">Cost and latency<a href=\"https://logicgrid.dev/blog/multi-agent-framework-for-dotnet#cost-and-latency\" class=\"hash-link\" aria-label=\"Direct link to Cost and latency\" title=\"Direct link to Cost and latency\" translate=\"no\">​</a></h2>\n<p>Three agents = three LLM calls = roughly 3x cost and 3x latency vs single agent. There are mitigations:</p>\n<ul>\n<li class=\"\"><strong>Mix model sizes.</strong> Use a small fast model for orchestration decisions and a large model only for the actual work.</li>\n<li class=\"\"><strong>Cache aggressively.</strong> Many multi-agent flows have agents that produce the same output for the same input. Cache at the agent boundary.</li>\n<li class=\"\"><strong>Run independent steps in parallel.</strong> Sequential is the worst case; parallel is free latency.</li>\n<li class=\"\"><strong>Run local for orchestration.</strong> Local LLMs (Ollama, vLLM) are essentially free per call. Use them for the cheap routing decisions and reserve hosted models for the heavy lifting.</li>\n</ul>\n<p>LogicGrid makes all four easy because providers are interchangeable in one line.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"a-real-example\">A real example<a href=\"https://logicgrid.dev/blog/multi-agent-framework-for-dotnet#a-real-example\" class=\"hash-link\" aria-label=\"Direct link to A real example\" title=\"Direct link to A real example\" translate=\"no\">​</a></h2>\n<p>Here's what a real production multi-agent system might look like — a code review bot:</p>\n<div class=\"language-csharp codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-csharp codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> llm </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> LlmClientBase</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">Ollama</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"llama3.2\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name\" style=\"color:rgb(78, 201, 176)\">IAgent</span><span class=\"token plain\"> securityReviewer </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">Agent</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&lt;</span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&gt;</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Security\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Looks for security issues.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Review the diff for security vulnerabilities. List concerns.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name\" style=\"color:rgb(78, 201, 176)\">IAgent</span><span class=\"token plain\"> perfReviewer </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">Agent</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&lt;</span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&gt;</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Performance\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Looks for performance issues.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Review the diff for performance problems. List concerns.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name\" style=\"color:rgb(78, 201, 176)\">IAgent</span><span class=\"token plain\"> styleReviewer </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">Agent</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&lt;</span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&gt;</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Style\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Looks for style issues.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Review the diff for style/readability. List concerns.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name\" style=\"color:rgb(78, 201, 176)\">IAgent</span><span class=\"token plain\"> synthesizer </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">Agent</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&lt;</span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&gt;</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Reviewer\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Synthesizes feedback.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Combine the reviews into a single PR comment, prioritized.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> admin </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">ParallelAdmin</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&lt;</span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\"> </span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&gt;</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">name</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"CodeReviewBot\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">llmClient</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">agents</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">IAgent</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">[</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">]</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token plain\"> securityReviewer</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> perfReviewer</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> styleReviewer </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">aggregator</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> synthesizer</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> review </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> admin</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">RunAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\">diffText</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">PostToGitHub</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\">review</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><br></div></code></pre></div></div>\n<p>Three independent reviewers run in parallel, then a synthesizer combines them into a single comment. Total wall-clock time is about the same as a single agent, but the output covers multiple dimensions.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"going-further\">Going further<a href=\"https://logicgrid.dev/blog/multi-agent-framework-for-dotnet#going-further\" class=\"hash-link\" aria-label=\"Direct link to Going further\" title=\"Direct link to Going further\" translate=\"no\">​</a></h2>\n<ul>\n<li class=\"\"><a class=\"\" href=\"https://logicgrid.dev/docs/orchestration/sequential\">Orchestration patterns</a> — sequential, group chat, graph, parallel, map-reduce, reflexion</li>\n<li class=\"\"><a class=\"\" href=\"https://logicgrid.dev/docs/observability/events\">Observability</a> — events, logging, tracing</li>\n<li class=\"\"><a class=\"\" href=\"https://logicgrid.dev/docs/getting-started/quickstart\">Quickstart</a> — build your first multi-agent system</li>\n</ul>\n<p>If you're comparing frameworks, see <a class=\"\" href=\"https://logicgrid.dev/blog/langchain-vs-semantic-kernel-vs-logicgrid\">LangChain vs Semantic Kernel vs LogicGrid</a>.</p>\n<p>If you want a single-agent introduction first, <a class=\"\" href=\"https://logicgrid.dev/blog/how-to-use-ollama-with-csharp\">How to use Ollama with C#</a> covers the basics.</p>",
            "url": "https://logicgrid.dev/blog/multi-agent-framework-for-dotnet",
            "title": "Multi-Agent Frameworks for .NET — A Practical Guide",
            "summary": "A practical look at why multi-agent architectures matter, when to use them, and how to build them in .NET. With patterns for sequential, group chat, graph, and reflexion orchestration.",
            "date_modified": "2026-04-18T00:00:00.000Z",
            "author": {
                "name": "LogicGrid Team",
                "url": "https://logicgrid.dev"
            },
            "tags": [
                "multi-agent",
                "dotnet",
                "csharp",
                "ai-agents",
                "orchestration",
                "llm"
            ]
        },
        {
            "id": "https://logicgrid.dev/blog/langchain-vs-semantic-kernel-vs-logicgrid",
            "content_html": "<p>If you're building AI agents in 2026 and you're not sure which framework to bet on, you're probably looking at three names: <strong>LangChain</strong> (Python, with a community .NET port), <strong>Microsoft Semantic Kernel</strong> (.NET, official), and <strong>LogicGrid</strong> (.NET-native, what you're reading about now).</p>\n<p>This post compares the three honestly. None of them is the right answer for everyone. The goal here is to give you concrete criteria for choosing.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"tldr\">TL;DR<a href=\"https://logicgrid.dev/blog/langchain-vs-semantic-kernel-vs-logicgrid#tldr\" class=\"hash-link\" aria-label=\"Direct link to TL;DR\" title=\"Direct link to TL;DR\" translate=\"no\">​</a></h2>\n<table><thead><tr><th>Pick this</th><th>If you...</th></tr></thead><tbody><tr><td><strong>LangChain (Python)</strong></td><td>Are on Python and want the largest ecosystem and integrations</td></tr><tr><td><strong>LangChain.NET</strong></td><td>Are on .NET, primarily prototype, and want familiarity with Python LangChain</td></tr><tr><td><strong>Semantic Kernel</strong></td><td>Are on .NET, deeply on Azure, and want first-party Microsoft support</td></tr><tr><td><strong>LogicGrid</strong></td><td>Are on .NET, need local LLMs as first-class, and want observability built in</td></tr></tbody></table>\n<p>The rest of this post explains why.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"what-each-one-is\">What each one is<a href=\"https://logicgrid.dev/blog/langchain-vs-semantic-kernel-vs-logicgrid#what-each-one-is\" class=\"hash-link\" aria-label=\"Direct link to What each one is\" title=\"Direct link to What each one is\" translate=\"no\">​</a></h2>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"langchain-python\">LangChain (Python)<a href=\"https://logicgrid.dev/blog/langchain-vs-semantic-kernel-vs-logicgrid#langchain-python\" class=\"hash-link\" aria-label=\"Direct link to LangChain (Python)\" title=\"Direct link to LangChain (Python)\" translate=\"no\">​</a></h3>\n<p>The original LangChain. Massive ecosystem — 700+ integrations, hundreds of community packages, every vendor has a connector. If you're in Python and you can name a vector DB, embedding model, or LLM provider, LangChain has a wrapper for it.</p>\n<p>LangChain has matured a lot since the early 2023 days when it was infamous for breaking changes. It's now reasonably stable, though still moving fast.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"langchainnet-community-port\">LangChain.NET (community port)<a href=\"https://logicgrid.dev/blog/langchain-vs-semantic-kernel-vs-logicgrid#langchainnet-community-port\" class=\"hash-link\" aria-label=\"Direct link to LangChain.NET (community port)\" title=\"Direct link to LangChain.NET (community port)\" translate=\"no\">​</a></h3>\n<p>A community-maintained C# port of LangChain. Maintained by <a href=\"https://github.com/tryAGI/LangChain\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">tryAGI</a>. It tracks the Python version with a lag — new features land in Python first and trickle over.</p>\n<p>For .NET teams who want LangChain familiarity, it's a reasonable choice. Just know that it's not officially supported by LangChain Inc., and the integration coverage is much narrower than Python.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"microsoft-semantic-kernel\">Microsoft Semantic Kernel<a href=\"https://logicgrid.dev/blog/langchain-vs-semantic-kernel-vs-logicgrid#microsoft-semantic-kernel\" class=\"hash-link\" aria-label=\"Direct link to Microsoft Semantic Kernel\" title=\"Direct link to Microsoft Semantic Kernel\" translate=\"no\">​</a></h3>\n<p>Microsoft's official .NET (and now Python and Java) framework for AI orchestration. Backed by significant Microsoft engineering. Deeply integrated with Azure OpenAI, Azure AI Search, and Microsoft 365.</p>\n<p>Semantic Kernel uses a \"kernel + plugins + planner\" architecture. You register plugins (skills) with the kernel, and a planner LLM decides which plugins to call to solve a task. It's a flexible model but encourages letting the LLM drive — which is sometimes what you want and sometimes a debugging nightmare.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"logicgrid\">LogicGrid<a href=\"https://logicgrid.dev/blog/langchain-vs-semantic-kernel-vs-logicgrid#logicgrid\" class=\"hash-link\" aria-label=\"Direct link to LogicGrid\" title=\"Direct link to LogicGrid\" translate=\"no\">​</a></h3>\n<p>A .NET-native framework focused on three things: local LLMs as first-class citizens, observability built in, and zero hidden runtime dependencies. Provider-agnostic — same code runs against Ollama, OpenAI, Anthropic, Gemini, vLLM, TEI, LM Studio.</p>\n<p>LogicGrid uses an \"explicit orchestration\" model. You describe the agent graph; the LLMs fill in the steps. This is more code than a Semantic Kernel planner but vastly easier to debug.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"same-task-three-frameworks\">Same task, three frameworks<a href=\"https://logicgrid.dev/blog/langchain-vs-semantic-kernel-vs-logicgrid#same-task-three-frameworks\" class=\"hash-link\" aria-label=\"Direct link to Same task, three frameworks\" title=\"Direct link to Same task, three frameworks\" translate=\"no\">​</a></h2>\n<p>Let's compare a simple task: an agent that takes a topic, researches it, and writes a 200-word explainer with a critic loop.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"langchain-python-1\">LangChain (Python)<a href=\"https://logicgrid.dev/blog/langchain-vs-semantic-kernel-vs-logicgrid#langchain-python-1\" class=\"hash-link\" aria-label=\"Direct link to LangChain (Python)\" title=\"Direct link to LangChain (Python)\" translate=\"no\">​</a></h3>\n<div class=\"language-python codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-python codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">from</span><span class=\"token plain\"> langchain</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token plain\">chat_models </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">import</span><span class=\"token plain\"> ChatOpenAI</span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">from</span><span class=\"token plain\"> langchain</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token plain\">agents </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">import</span><span class=\"token plain\"> initialize_agent</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> AgentType</span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">from</span><span class=\"token plain\"> langchain</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token plain\">tools </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">import</span><span class=\"token plain\"> Tool</span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">llm </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> ChatOpenAI</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\">model</span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"gpt-4o\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">tools </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">[</span><span class=\"token plain\">Tool</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\">name</span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"search\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> func</span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\">search</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> description</span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"...\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">]</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">agent </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> initialize_agent</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\">tools</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> agent</span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\">AgentType</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token plain\">ZERO_SHOT_REACT_DESCRIPTION</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">print</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\">agent</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token plain\">run</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Explain Reciprocal Rank Fusion in 200 words.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><br></div></code></pre></div></div>\n<p>Concise. The framework decides the workflow under the hood.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"semantic-kernel-net\">Semantic Kernel (.NET)<a href=\"https://logicgrid.dev/blog/langchain-vs-semantic-kernel-vs-logicgrid#semantic-kernel-net\" class=\"hash-link\" aria-label=\"Direct link to Semantic Kernel (.NET)\" title=\"Direct link to Semantic Kernel (.NET)\" translate=\"no\">​</a></h3>\n<div class=\"language-csharp codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-csharp codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> builder </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> Kernel</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">CreateBuilder</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">AddOpenAIChatCompletion</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"gpt-4o\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> apiKey</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> kernel </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> builder</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">Build</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> planner </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">HandlebarsPlanner</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> plan </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> planner</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">CreatePlanAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    kernel</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Research and write 200 words about RRF.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> result </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> plan</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">InvokeAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\">kernel</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">Console</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">WriteLine</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\">result</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><br></div></code></pre></div></div>\n<p>Similar shape — you describe a goal and the planner decides how to achieve it.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"logicgrid-net\">LogicGrid (.NET)<a href=\"https://logicgrid.dev/blog/langchain-vs-semantic-kernel-vs-logicgrid#logicgrid-net\" class=\"hash-link\" aria-label=\"Direct link to LogicGrid (.NET)\" title=\"Direct link to LogicGrid (.NET)\" translate=\"no\">​</a></h3>\n<div class=\"language-csharp codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-csharp codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> llm </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> LlmClientBase</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">Ollama</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"llama3.2\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"> </span><span class=\"token comment\" style=\"color:rgb(106, 153, 85)\">// or OpenAI, Anthropic, etc.</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name\" style=\"color:rgb(78, 201, 176)\">IAgent</span><span class=\"token plain\"> researcher </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">Agent</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&lt;</span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&gt;</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Researcher\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Gathers facts on a topic.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"You research the topic and list 3 key facts.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name\" style=\"color:rgb(78, 201, 176)\">IAgent</span><span class=\"token plain\"> writer </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">Agent</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&lt;</span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&gt;</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Writer\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Writes a short article.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"You write a 200-word explainer using the researcher's facts.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name\" style=\"color:rgb(78, 201, 176)\">IAgent</span><span class=\"token plain\"> critic </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">Agent</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&lt;</span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&gt;</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Critic\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Reviews the article.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"You check the article. Reply DONE when it is publishable.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> admin </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">GroupChatAdmin</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&lt;</span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\"> </span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&gt;</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">name</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Editorial\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">llmClient</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">agents</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">[</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">]</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token plain\"> researcher</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> writer</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> critic </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">Console</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">WriteLine</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> admin</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">RunAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Explain Reciprocal Rank Fusion in 200 words.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><br></div></code></pre></div></div>\n<p>More verbose, because you explicitly name the three roles. But every agent's role is visible. When something goes wrong, you know exactly where to look.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-big-differences\">The big differences<a href=\"https://logicgrid.dev/blog/langchain-vs-semantic-kernel-vs-logicgrid#the-big-differences\" class=\"hash-link\" aria-label=\"Direct link to The big differences\" title=\"Direct link to The big differences\" translate=\"no\">​</a></h2>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"local-llm-support\">Local LLM support<a href=\"https://logicgrid.dev/blog/langchain-vs-semantic-kernel-vs-logicgrid#local-llm-support\" class=\"hash-link\" aria-label=\"Direct link to Local LLM support\" title=\"Direct link to Local LLM support\" translate=\"no\">​</a></h3>\n<table><thead><tr><th></th><th>LangChain</th><th>LangChain.NET</th><th>Semantic Kernel</th><th>LogicGrid</th></tr></thead><tbody><tr><td>Ollama</td><td>✓</td><td>Partial</td><td>Partial</td><td>✓ first-class</td></tr><tr><td>vLLM</td><td>✓</td><td>Limited</td><td>Limited</td><td>✓ first-class</td></tr><tr><td>LM Studio</td><td>✓</td><td>Partial</td><td>Partial</td><td>✓ first-class</td></tr><tr><td>TEI (HuggingFace)</td><td>✓</td><td>No</td><td>No</td><td>✓ first-class</td></tr></tbody></table>\n<p>LangChain and LogicGrid lead here. Semantic Kernel works with local LLMs but the path is rougher.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"multi-agent-patterns\">Multi-agent patterns<a href=\"https://logicgrid.dev/blog/langchain-vs-semantic-kernel-vs-logicgrid#multi-agent-patterns\" class=\"hash-link\" aria-label=\"Direct link to Multi-agent patterns\" title=\"Direct link to Multi-agent patterns\" translate=\"no\">​</a></h3>\n<table><thead><tr><th></th><th>LangChain</th><th>Semantic Kernel</th><th>LogicGrid</th></tr></thead><tbody><tr><td>Sequential</td><td>✓</td><td>✓</td><td>✓</td></tr><tr><td>Group chat</td><td>✓ (LangGraph)</td><td>Partial</td><td>✓</td></tr><tr><td>Graph (DAG)</td><td>✓ (LangGraph)</td><td>Partial</td><td>✓</td></tr><tr><td>Parallel</td><td>✓</td><td>Partial</td><td>✓</td></tr><tr><td>Map-Reduce</td><td>✓</td><td>No</td><td>✓</td></tr><tr><td>Reflexion (self-critique)</td><td>Manual</td><td>Manual</td><td>✓ built-in</td></tr></tbody></table>\n<p>LangChain's LangGraph is the gold standard for graph orchestration. LogicGrid covers the same patterns natively in .NET. Semantic Kernel is catching up but is still planner-centric.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"observability\">Observability<a href=\"https://logicgrid.dev/blog/langchain-vs-semantic-kernel-vs-logicgrid#observability\" class=\"hash-link\" aria-label=\"Direct link to Observability\" title=\"Direct link to Observability\" translate=\"no\">​</a></h3>\n<table><thead><tr><th></th><th>LangChain</th><th>Semantic Kernel</th><th>LogicGrid</th></tr></thead><tbody><tr><td>Structured events</td><td>LangSmith (paid)</td><td>OpenTelemetry (manual)</td><td>Built-in</td></tr><tr><td>Token counts</td><td>LangSmith</td><td>Manual</td><td>Built-in</td></tr><tr><td>Run tracing</td><td>LangSmith</td><td>Manual</td><td>Built-in</td></tr><tr><td>Tool call logs</td><td>LangSmith</td><td>Manual</td><td>Built-in</td></tr></tbody></table>\n<p>LangSmith is excellent but it's a paid service. LogicGrid's tracing is open and free — events are emitted to an in-process bus you can route anywhere (console, file, OTel collector).</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"deployment-posture\">Deployment posture<a href=\"https://logicgrid.dev/blog/langchain-vs-semantic-kernel-vs-logicgrid#deployment-posture\" class=\"hash-link\" aria-label=\"Direct link to Deployment posture\" title=\"Direct link to Deployment posture\" translate=\"no\">​</a></h3>\n<table><thead><tr><th></th><th>LangChain</th><th>LangChain.NET</th><th>Semantic Kernel</th><th>LogicGrid</th></tr></thead><tbody><tr><td>.NET Framework 4.7.2+</td><td>n/a</td><td>No</td><td>No</td><td>✓</td></tr><tr><td>.NET 6</td><td>n/a</td><td>✓</td><td>No</td><td>✓</td></tr><tr><td>.NET 8</td><td>n/a</td><td>✓</td><td>✓</td><td>✓</td></tr><tr><td>Air-gapped friendly</td><td>Hard</td><td>Hard</td><td>Hard</td><td>✓</td></tr><tr><td>SBOM published</td><td>No</td><td>No</td><td>Partial</td><td>✓ CycloneDX</td></tr></tbody></table>\n<p>LogicGrid is the only one that works on legacy .NET Framework — useful for enterprise teams who can't migrate everything to .NET 8 yet.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"when-each-one-wins\">When each one wins<a href=\"https://logicgrid.dev/blog/langchain-vs-semantic-kernel-vs-logicgrid#when-each-one-wins\" class=\"hash-link\" aria-label=\"Direct link to When each one wins\" title=\"Direct link to When each one wins\" translate=\"no\">​</a></h2>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"pick-langchain-python-if\">Pick LangChain (Python) if...<a href=\"https://logicgrid.dev/blog/langchain-vs-semantic-kernel-vs-logicgrid#pick-langchain-python-if\" class=\"hash-link\" aria-label=\"Direct link to Pick LangChain (Python) if...\" title=\"Direct link to Pick LangChain (Python) if...\" translate=\"no\">​</a></h3>\n<ul>\n<li class=\"\">You're already on Python</li>\n<li class=\"\">You need the broadest possible integration coverage</li>\n<li class=\"\">You're doing research / experimentation rather than shipping</li>\n<li class=\"\">You want LangSmith for production observability and you're willing to pay</li>\n</ul>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"pick-langchainnet-if\">Pick LangChain.NET if...<a href=\"https://logicgrid.dev/blog/langchain-vs-semantic-kernel-vs-logicgrid#pick-langchainnet-if\" class=\"hash-link\" aria-label=\"Direct link to Pick LangChain.NET if...\" title=\"Direct link to Pick LangChain.NET if...\" translate=\"no\">​</a></h3>\n<ul>\n<li class=\"\">You're on .NET but came from Python LangChain and want the API to feel familiar</li>\n<li class=\"\">You're prototyping, not shipping production</li>\n<li class=\"\">Coverage gaps don't bother you</li>\n</ul>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"pick-semantic-kernel-if\">Pick Semantic Kernel if...<a href=\"https://logicgrid.dev/blog/langchain-vs-semantic-kernel-vs-logicgrid#pick-semantic-kernel-if\" class=\"hash-link\" aria-label=\"Direct link to Pick Semantic Kernel if...\" title=\"Direct link to Pick Semantic Kernel if...\" translate=\"no\">​</a></h3>\n<ul>\n<li class=\"\">Your stack is fully on Azure</li>\n<li class=\"\">You need first-party Microsoft support contracts</li>\n<li class=\"\">You're building Microsoft 365 / Copilot integrations</li>\n<li class=\"\">\"Letting the LLM plan\" matches your product philosophy</li>\n</ul>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"pick-logicgrid-if\">Pick LogicGrid if...<a href=\"https://logicgrid.dev/blog/langchain-vs-semantic-kernel-vs-logicgrid#pick-logicgrid-if\" class=\"hash-link\" aria-label=\"Direct link to Pick LogicGrid if...\" title=\"Direct link to Pick LogicGrid if...\" translate=\"no\">​</a></h3>\n<ul>\n<li class=\"\">Local LLMs are a peer of hosted ones in your roadmap</li>\n<li class=\"\">You ship to enterprises who care about dependencies and SBOMs</li>\n<li class=\"\">You're targeting older .NET (Framework 4.7.2+, .NET Core)</li>\n<li class=\"\">You want observability without paying for it</li>\n<li class=\"\">You prefer \"describe the workflow explicitly\" over \"let the LLM plan\"</li>\n</ul>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-honest-take\">The honest take<a href=\"https://logicgrid.dev/blog/langchain-vs-semantic-kernel-vs-logicgrid#the-honest-take\" class=\"hash-link\" aria-label=\"Direct link to The honest take\" title=\"Direct link to The honest take\" translate=\"no\">​</a></h2>\n<p>There is no single winner. There's the right tool for your constraints.</p>\n<p>If you're a Python team running on AWS or GCP, <strong>LangChain</strong> is the obvious choice — biggest ecosystem, most learning material, most jobs.</p>\n<p>If you're a .NET team running on Azure with Azure OpenAI, <strong>Semantic Kernel</strong> is the obvious choice — first-party support beats everything.</p>\n<p>If you're a .NET team that needs local LLMs, has a serious bar for dependency hygiene, or simply wants to <em>see</em> what your agents are doing without writing telemetry plumbing, <strong>LogicGrid</strong> is built for you.</p>\n<p>Try the <a class=\"\" href=\"https://logicgrid.dev/docs/getting-started/quickstart\">Quickstart</a> — it takes five minutes. If LogicGrid fits, you'll know quickly.</p>\n<hr>\n<p><strong>Related posts:</strong></p>\n<ul>\n<li class=\"\"><a class=\"\" href=\"https://logicgrid.dev/blog/semantic-kernel-alternative-for-dotnet\">Semantic Kernel alternative for .NET</a> — deeper dive on Semantic Kernel trade-offs</li>\n<li class=\"\"><a class=\"\" href=\"https://logicgrid.dev/blog/how-to-use-ollama-with-csharp\">How to use Ollama with C#</a> — local LLMs from .NET</li>\n<li class=\"\"><a class=\"\" href=\"https://logicgrid.dev/blog/build-a-rag-pipeline-in-csharp\">Build a RAG pipeline in C#</a> — RAG end to end</li>\n</ul>",
            "url": "https://logicgrid.dev/blog/langchain-vs-semantic-kernel-vs-logicgrid",
            "title": "LangChain vs Semantic Kernel vs LogicGrid — Picking an Agent Framework in 2026",
            "summary": "An honest, feature-by-feature comparison of LangChain, Microsoft Semantic Kernel, and LogicGrid for building AI agents in 2026. With code samples and concrete decision criteria.",
            "date_modified": "2026-04-10T00:00:00.000Z",
            "author": {
                "name": "LogicGrid Team",
                "url": "https://logicgrid.dev"
            },
            "tags": [
                "langchain",
                "semantic-kernel",
                "comparison",
                "ai-agents",
                "dotnet",
                "python"
            ]
        },
        {
            "id": "https://logicgrid.dev/blog/build-a-rag-pipeline-in-csharp",
            "content_html": "<p><strong>Retrieval-Augmented Generation (RAG)</strong> is how you make an LLM answer questions about <em>your</em> data without paying to fine-tune it. You take a question, find the most relevant chunks of your documents, and stuff them into the prompt as context.</p>\n<p>This post walks through building a production-grade RAG pipeline in C# — from a flat file on disk to a working <code>Ask my docs</code> system with hybrid retrieval that beats simple semantic search on real-world queries.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"what-youre-building\">What you're building<a href=\"https://logicgrid.dev/blog/build-a-rag-pipeline-in-csharp#what-youre-building\" class=\"hash-link\" aria-label=\"Direct link to What you're building\" title=\"Direct link to What you're building\" translate=\"no\">​</a></h2>\n<p>By the end of this post you'll have a working C# program that:</p>\n<ol>\n<li class=\"\">Loads a folder of documents</li>\n<li class=\"\">Chunks them intelligently</li>\n<li class=\"\">Generates embeddings using Ollama (or OpenAI, your choice)</li>\n<li class=\"\">Stores them in a vector index</li>\n<li class=\"\">Answers questions using both <strong>dense semantic search</strong> and <strong>BM25 keyword search</strong>, fused with Reciprocal Rank Fusion</li>\n</ol>\n<p>That last piece — hybrid search — is what separates toy RAG demos from systems that actually work in production.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"why-naive-rag-fails\">Why naive RAG fails<a href=\"https://logicgrid.dev/blog/build-a-rag-pipeline-in-csharp#why-naive-rag-fails\" class=\"hash-link\" aria-label=\"Direct link to Why naive RAG fails\" title=\"Direct link to Why naive RAG fails\" translate=\"no\">​</a></h2>\n<p>The standard RAG tutorial looks like this:</p>\n<ol>\n<li class=\"\">Chunk documents</li>\n<li class=\"\">Embed chunks with OpenAI</li>\n<li class=\"\">Store in a vector DB</li>\n<li class=\"\">At query time, embed the question, find nearest neighbors, send to LLM</li>\n</ol>\n<p>This works great for queries like <em>\"how does our authentication flow work?\"</em> — questions where semantic similarity matches.</p>\n<p>It fails on queries like:</p>\n<ul>\n<li class=\"\"><em>\"What does error code SKU-4421 mean?\"</em> — the embedding for \"SKU-4421\" looks like the embedding for any other product code. Dense retrieval will find documents about <em>similar codes</em>, not the actual one.</li>\n<li class=\"\"><em>\"Who wrote RFC 2616?\"</em> — same problem with proper nouns.</li>\n<li class=\"\"><em>\"What are the requirements for ISO 27001?\"</em> — dense retrieval often surfaces documents about other ISO standards.</li>\n</ul>\n<p>For exact matches — codes, IDs, RFC numbers, error messages, function names — you need keyword retrieval. <strong>BM25</strong> is the gold-standard algorithm here. Combine BM25 with dense retrieval and you get the best of both worlds.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"step-1-install-logicgrid\">Step 1: Install LogicGrid<a href=\"https://logicgrid.dev/blog/build-a-rag-pipeline-in-csharp#step-1-install-logicgrid\" class=\"hash-link\" aria-label=\"Direct link to Step 1: Install LogicGrid\" title=\"Direct link to Step 1: Install LogicGrid\" translate=\"no\">​</a></h2>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">dotnet </span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">add</span><span class=\"token plain\"> package LogicGrid.Core</span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">dotnet </span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">add</span><span class=\"token plain\"> package LogicGrid.Memory</span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">dotnet </span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">add</span><span class=\"token plain\"> package LogicGrid.Rag</span><br></div></code></pre></div></div>\n<p>Pull an embedding model:</p>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">ollama pull nomic-embed-text</span><br></div></code></pre></div></div>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"step-2-a-minimal-rag-pipeline\">Step 2: A minimal RAG pipeline<a href=\"https://logicgrid.dev/blog/build-a-rag-pipeline-in-csharp#step-2-a-minimal-rag-pipeline\" class=\"hash-link\" aria-label=\"Direct link to Step 2: A minimal RAG pipeline\" title=\"Direct link to Step 2: A minimal RAG pipeline\" translate=\"no\">​</a></h2>\n<div class=\"language-csharp codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-csharp codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">using</span><span class=\"token plain\"> </span><span class=\"token namespace\">LogicGrid</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Memory</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Embeddings</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">using</span><span class=\"token plain\"> </span><span class=\"token namespace\">LogicGrid</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Memory</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">VectorStores</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">using</span><span class=\"token plain\"> </span><span class=\"token namespace\">LogicGrid</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Rag</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> embedder </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">OllamaEmbeddingClient</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"nomic-embed-text\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> store    </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">InMemoryVectorStore</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> pipeline </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">RagPipeline</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\">embedder</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> store</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:rgb(106, 153, 85)\">// Ingest documents — chunked and embedded automatically</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> pipeline</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">IngestAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"./docs/handbook.md\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> pipeline</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">IngestAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"./docs/architecture.md\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:rgb(106, 153, 85)\">// Search</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> hits </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> pipeline</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">SearchAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"How do I deploy the API to production?\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">topK</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(181, 206, 168)\">5</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">foreach</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> hit </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">in</span><span class=\"token plain\"> hits</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    Console</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">WriteLine</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token interpolation-string string\" style=\"color:rgb(206, 145, 120)\">$\"[</span><span class=\"token interpolation-string interpolation punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token interpolation-string interpolation expression language-csharp\">hit</span><span class=\"token interpolation-string interpolation expression language-csharp punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token interpolation-string interpolation expression language-csharp\">Score</span><span class=\"token interpolation-string interpolation format-string punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token interpolation-string interpolation format-string\">F3</span><span class=\"token interpolation-string interpolation punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token interpolation-string string\" style=\"color:rgb(206, 145, 120)\">] </span><span class=\"token interpolation-string interpolation punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token interpolation-string interpolation expression language-csharp\">hit</span><span class=\"token interpolation-string interpolation expression language-csharp punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token interpolation-string interpolation expression language-csharp\">Document</span><span class=\"token interpolation-string interpolation expression language-csharp punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token interpolation-string interpolation expression language-csharp\">Text</span><span class=\"token interpolation-string interpolation expression language-csharp punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token interpolation-string interpolation expression language-csharp function\" style=\"color:rgb(220, 220, 170)\">Substring</span><span class=\"token interpolation-string interpolation expression language-csharp punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token interpolation-string interpolation expression language-csharp number\" style=\"color:rgb(181, 206, 168)\">0</span><span class=\"token interpolation-string interpolation expression language-csharp punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token interpolation-string interpolation expression language-csharp\"> </span><span class=\"token interpolation-string interpolation expression language-csharp number\" style=\"color:rgb(181, 206, 168)\">100</span><span class=\"token interpolation-string interpolation expression language-csharp punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token interpolation-string interpolation punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token interpolation-string string\" style=\"color:rgb(206, 145, 120)\">...\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><br></div></code></pre></div></div>\n<p>That's the entire program. The <code>RagPipeline</code> handles chunking (using a sensible default — split on paragraphs, max ~500 tokens per chunk with overlap), embedding, and storage.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"step-3-adding-generation\">Step 3: Adding generation<a href=\"https://logicgrid.dev/blog/build-a-rag-pipeline-in-csharp#step-3-adding-generation\" class=\"hash-link\" aria-label=\"Direct link to Step 3: Adding generation\" title=\"Direct link to Step 3: Adding generation\" translate=\"no\">​</a></h2>\n<p>To turn search results into answers, wrap an agent around the pipeline:</p>\n<div class=\"language-csharp codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-csharp codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">using</span><span class=\"token plain\"> </span><span class=\"token namespace\">LogicGrid</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Core</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Agents</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">using</span><span class=\"token plain\"> </span><span class=\"token namespace\">LogicGrid</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Core</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> llm </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> LlmClientBase</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">Ollama</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"llama3.2\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name\" style=\"color:rgb(78, 201, 176)\">IAgent</span><span class=\"token plain\"> agent </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">RagAgent</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\">llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> pipeline</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> answer </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> agent</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">RunAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"How do I deploy the API to production?\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">AgentContext</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"deploy-question\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">Console</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">WriteLine</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\">answer</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><br></div></code></pre></div></div>\n<p><code>RagAgent</code> retrieves the top chunks, formats them into a prompt with your question, and calls the LLM. You get a coherent answer with cited sources.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"step-4-upgrade-to-hybrid-search\">Step 4: Upgrade to hybrid search<a href=\"https://logicgrid.dev/blog/build-a-rag-pipeline-in-csharp#step-4-upgrade-to-hybrid-search\" class=\"hash-link\" aria-label=\"Direct link to Step 4: Upgrade to hybrid search\" title=\"Direct link to Step 4: Upgrade to hybrid search\" translate=\"no\">​</a></h2>\n<p>The <code>InMemoryVectorStore</code> does dense retrieval only. For production you want hybrid. LogicGrid's <code>HybridVectorStore</code> is a drop-in replacement:</p>\n<div class=\"language-csharp codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-csharp codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">using</span><span class=\"token plain\"> </span><span class=\"token namespace\">LogicGrid</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Memory</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Search</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> store </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">HybridVectorStore</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">InMemoryVectorStore</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> pipeline </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">RagPipeline</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\">embedder</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> store</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> pipeline</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">IngestAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"./docs/handbook.md\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:rgb(106, 153, 85)\">// Hybrid search: dense + BM25 + RRF fusion</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> results </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> pipeline</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">HybridSearchAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"What does error code SKU-4421 mean?\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">topK</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(181, 206, 168)\">5</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">foreach</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> r </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">in</span><span class=\"token plain\"> results</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    Console</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">WriteLine</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">        </span><span class=\"token interpolation-string string\" style=\"color:rgb(206, 145, 120)\">$\"RRF=</span><span class=\"token interpolation-string interpolation punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token interpolation-string interpolation expression language-csharp\">r</span><span class=\"token interpolation-string interpolation expression language-csharp punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token interpolation-string interpolation expression language-csharp\">RrfScore</span><span class=\"token interpolation-string interpolation format-string punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token interpolation-string interpolation format-string\">F4</span><span class=\"token interpolation-string interpolation punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token interpolation-string string\" style=\"color:rgb(206, 145, 120)\">  dense=</span><span class=\"token interpolation-string interpolation punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token interpolation-string interpolation expression language-csharp\">r</span><span class=\"token interpolation-string interpolation expression language-csharp punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token interpolation-string interpolation expression language-csharp\">DenseScore</span><span class=\"token interpolation-string interpolation format-string punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token interpolation-string interpolation format-string\">F3</span><span class=\"token interpolation-string interpolation punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token interpolation-string string\" style=\"color:rgb(206, 145, 120)\">  sparse=</span><span class=\"token interpolation-string interpolation punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token interpolation-string interpolation expression language-csharp\">r</span><span class=\"token interpolation-string interpolation expression language-csharp punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token interpolation-string interpolation expression language-csharp\">SparseScore</span><span class=\"token interpolation-string interpolation format-string punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token interpolation-string interpolation format-string\">F3</span><span class=\"token interpolation-string interpolation punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token interpolation-string string\" style=\"color:rgb(206, 145, 120)\">\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    Console</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">WriteLine</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token interpolation-string string\" style=\"color:rgb(206, 145, 120)\">$\"  </span><span class=\"token interpolation-string interpolation punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token interpolation-string interpolation expression language-csharp\">r</span><span class=\"token interpolation-string interpolation expression language-csharp punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token interpolation-string interpolation expression language-csharp\">Document</span><span class=\"token interpolation-string interpolation expression language-csharp punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token interpolation-string interpolation expression language-csharp\">Text</span><span class=\"token interpolation-string interpolation expression language-csharp punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token interpolation-string interpolation expression language-csharp function\" style=\"color:rgb(220, 220, 170)\">Substring</span><span class=\"token interpolation-string interpolation expression language-csharp punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token interpolation-string interpolation expression language-csharp number\" style=\"color:rgb(181, 206, 168)\">0</span><span class=\"token interpolation-string interpolation expression language-csharp punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token interpolation-string interpolation expression language-csharp\"> </span><span class=\"token interpolation-string interpolation expression language-csharp number\" style=\"color:rgb(181, 206, 168)\">100</span><span class=\"token interpolation-string interpolation expression language-csharp punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token interpolation-string interpolation punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token interpolation-string string\" style=\"color:rgb(206, 145, 120)\">...\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><br></div></code></pre></div></div>\n<p>You'll see scores from both retrievers. Documents that score well on <strong>both</strong> rank higher than documents that score well on only one. The fusion algorithm is <strong>Reciprocal Rank Fusion (RRF)</strong> — parameter-free, well-studied, and consistently beats either retriever alone.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"what-hybrid-search-actually-does\">What hybrid search actually does<a href=\"https://logicgrid.dev/blog/build-a-rag-pipeline-in-csharp#what-hybrid-search-actually-does\" class=\"hash-link\" aria-label=\"Direct link to What hybrid search actually does\" title=\"Direct link to What hybrid search actually does\" translate=\"no\">​</a></h2>\n<p>Under the hood, <code>HybridSearchAsync</code> does this:</p>\n<ol>\n<li class=\"\">Embeds your query and runs cosine similarity over the vector index — returns the top N candidates by <strong>semantic</strong> match.</li>\n<li class=\"\">Tokenizes your query and runs BM25 over an inverted index — returns the top N candidates by <strong>keyword</strong> match.</li>\n<li class=\"\">Combines the two ranked lists using RRF: each document's score is <code>1/(60 + rank_dense) + 1/(60 + rank_sparse)</code>.</li>\n<li class=\"\">Re-sorts by RRF score and returns the top K.</li>\n</ol>\n<p>If a document appears in both lists, it gets a substantial boost. If it appears in only one, it can still rank if its position in that list is high.</p>\n<p>The implementation is pure C# — no native dependencies, no extra NuGets. See the <a class=\"\" href=\"https://logicgrid.dev/docs/rag/hybrid-search\">hybrid search docs</a> for the full math.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"real-benchmarks\">Real benchmarks<a href=\"https://logicgrid.dev/blog/build-a-rag-pipeline-in-csharp#real-benchmarks\" class=\"hash-link\" aria-label=\"Direct link to Real benchmarks\" title=\"Direct link to Real benchmarks\" translate=\"no\">​</a></h2>\n<p>We compared dense-only vs hybrid on three query types over a 10,000-document corpus of technical documentation:</p>\n<table><thead><tr><th>Query type</th><th>Dense only (recall@5)</th><th>Hybrid (recall@5)</th></tr></thead><tbody><tr><td>Conceptual (\"how do I X?\")</td><td>0.82</td><td>0.85</td></tr><tr><td>Codes / IDs (\"SKU-4421\")</td><td>0.21</td><td>0.94</td></tr><tr><td>Proper nouns</td><td>0.40</td><td>0.88</td></tr></tbody></table>\n<p>The takeaway: hybrid never hurts on conceptual queries (because the dense retriever still drives those), and it dramatically improves the hard cases.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"step-5-production-considerations\">Step 5: Production considerations<a href=\"https://logicgrid.dev/blog/build-a-rag-pipeline-in-csharp#step-5-production-considerations\" class=\"hash-link\" aria-label=\"Direct link to Step 5: Production considerations\" title=\"Direct link to Step 5: Production considerations\" translate=\"no\">​</a></h2>\n<p>The in-memory store works fine up to a few hundred thousand vectors. Past that you want a real vector database. LogicGrid's <code>IVectorStore</code> interface is small — wrap your favorite (Qdrant, pgvector, Weaviate, Pinecone) and plug it in:</p>\n<div class=\"language-csharp codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-csharp codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">public</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">sealed</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">class</span><span class=\"token plain\"> </span><span class=\"token class-name\" style=\"color:rgb(78, 201, 176)\">QdrantVectorStore</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token type-list class-name\" style=\"color:rgb(78, 201, 176)\">IVectorStore</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">public</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">async</span><span class=\"token plain\"> </span><span class=\"token return-type class-name\" style=\"color:rgb(78, 201, 176)\">Task</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">UpsertAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token class-name\" style=\"color:rgb(78, 201, 176)\">VectorDocument</span><span class=\"token plain\"> doc</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> </span><span class=\"token class-name\" style=\"color:rgb(78, 201, 176)\">CancellationToken</span><span class=\"token plain\"> ct </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">default</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token plain\"> </span><span class=\"token comment\" style=\"color:rgb(106, 153, 85)\">/* ... */</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">public</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">async</span><span class=\"token plain\"> </span><span class=\"token return-type class-name\" style=\"color:rgb(78, 201, 176)\">Task</span><span class=\"token return-type class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&lt;</span><span class=\"token return-type class-name\" style=\"color:rgb(78, 201, 176)\">IList</span><span class=\"token return-type class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&lt;</span><span class=\"token return-type class-name\" style=\"color:rgb(78, 201, 176)\">VectorSearchResult</span><span class=\"token return-type class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&gt;</span><span class=\"token return-type class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">SearchAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">        </span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">float</span><span class=\"token class-name punctuation\" style=\"color:rgb(212, 212, 212)\">[</span><span class=\"token class-name punctuation\" style=\"color:rgb(212, 212, 212)\">]</span><span class=\"token plain\"> query</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> </span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">int</span><span class=\"token plain\"> topK</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> </span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">float</span><span class=\"token plain\"> minScore</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> </span><span class=\"token class-name\" style=\"color:rgb(78, 201, 176)\">CancellationToken</span><span class=\"token plain\"> ct </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">default</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token plain\"> </span><span class=\"token comment\" style=\"color:rgb(106, 153, 85)\">/* ... */</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token comment\" style=\"color:rgb(106, 153, 85)\">// ...</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> store </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">HybridVectorStore</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">QdrantVectorStore</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token range operator\" style=\"color:rgb(212, 212, 212)\">..</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><br></div></code></pre></div></div>\n<p><code>HybridVectorStore</code> wraps any <code>IVectorStore</code> and adds BM25 indexing on top. You get hybrid retrieval over your existing vector DB without rewriting anything.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"step-6-chunking-strategies-that-matter\">Step 6: Chunking strategies that matter<a href=\"https://logicgrid.dev/blog/build-a-rag-pipeline-in-csharp#step-6-chunking-strategies-that-matter\" class=\"hash-link\" aria-label=\"Direct link to Step 6: Chunking strategies that matter\" title=\"Direct link to Step 6: Chunking strategies that matter\" translate=\"no\">​</a></h2>\n<p>The default chunker splits on paragraphs and merges to ~500 tokens. That's a reasonable starting point but rarely optimal. Things to consider:</p>\n<ul>\n<li class=\"\"><strong>Code-heavy docs</strong>: split on functions, not paragraphs. Code cares about scope.</li>\n<li class=\"\"><strong>Markdown docs</strong>: respect heading boundaries. A chunk that crosses two H2s loses semantic coherence.</li>\n<li class=\"\"><strong>Tables</strong>: never split a table across chunks. The retriever will return half a table and the LLM will hallucinate the rest.</li>\n<li class=\"\"><strong>Overlap</strong>: keep ~10–15% overlap between adjacent chunks. Prevents the case where the answer straddles a chunk boundary.</li>\n</ul>\n<p>LogicGrid lets you swap chunking strategies via <code>IChunkingStrategy</code>. See the <a class=\"\" href=\"https://logicgrid.dev/docs/rag/pipeline\">chunking docs</a> for built-in options and how to write your own.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"step-7-evaluation\">Step 7: Evaluation<a href=\"https://logicgrid.dev/blog/build-a-rag-pipeline-in-csharp#step-7-evaluation\" class=\"hash-link\" aria-label=\"Direct link to Step 7: Evaluation\" title=\"Direct link to Step 7: Evaluation\" translate=\"no\">​</a></h2>\n<p>The hardest part of RAG isn't building it — it's knowing whether it's any good. A simple eval set goes a long way:</p>\n<div class=\"language-csharp codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-csharp codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> evalQuestions </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\"> Question</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\"> </span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\"> ExpectedDocId</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">[</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">]</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"How do I deploy?\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"deployment.md#prod\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"What is SKU-4421?\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"errors.md#sku-4421\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token comment\" style=\"color:rgb(106, 153, 85)\">// ...</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">int</span><span class=\"token plain\"> hits </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(181, 206, 168)\">0</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">foreach</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\">q</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> expected</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">in</span><span class=\"token plain\"> evalQuestions</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> results </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> pipeline</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">HybridSearchAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\">q</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">topK</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(181, 206, 168)\">5</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">if</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\">results</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">Any</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\">r </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=&gt;</span><span class=\"token plain\"> r</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token plain\">Document</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token plain\">Id </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">==</span><span class=\"token plain\"> expected</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">        hits</span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">++</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">Console</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">WriteLine</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token interpolation-string string\" style=\"color:rgb(206, 145, 120)\">$\"Recall@5: </span><span class=\"token interpolation-string interpolation punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token interpolation-string interpolation expression language-csharp punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token interpolation-string interpolation expression language-csharp keyword\" style=\"color:rgb(86, 156, 214)\">double</span><span class=\"token interpolation-string interpolation expression language-csharp punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token interpolation-string interpolation expression language-csharp\">hits </span><span class=\"token interpolation-string interpolation expression language-csharp operator\" style=\"color:rgb(212, 212, 212)\">/</span><span class=\"token interpolation-string interpolation expression language-csharp\"> evalQuestions</span><span class=\"token interpolation-string interpolation expression language-csharp punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token interpolation-string interpolation expression language-csharp\">Length</span><span class=\"token interpolation-string interpolation format-string punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token interpolation-string interpolation format-string\">P0</span><span class=\"token interpolation-string interpolation punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token interpolation-string string\" style=\"color:rgb(206, 145, 120)\">\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><br></div></code></pre></div></div>\n<p>Run this on every change to your chunking, embedding model, or retrieval strategy. You'll catch regressions before users do.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"going-further\">Going further<a href=\"https://logicgrid.dev/blog/build-a-rag-pipeline-in-csharp#going-further\" class=\"hash-link\" aria-label=\"Direct link to Going further\" title=\"Direct link to Going further\" translate=\"no\">​</a></h2>\n<ul>\n<li class=\"\"><a class=\"\" href=\"https://logicgrid.dev/docs/rag/pipeline\">RAG pipeline reference</a></li>\n<li class=\"\"><a class=\"\" href=\"https://logicgrid.dev/docs/rag/hybrid-search\">Hybrid search internals</a></li>\n<li class=\"\"><a class=\"\" href=\"https://logicgrid.dev/docs/rag/document-loaders\">Document loaders</a> — markdown, PDF, code, web</li>\n<li class=\"\"><a class=\"\" href=\"https://logicgrid.dev/docs/concepts/memory-and-rag\">Memory and RAG concepts</a></li>\n</ul>\n<p>If you're new to LogicGrid, the <a class=\"\" href=\"https://logicgrid.dev/docs/getting-started/quickstart\">Quickstart</a> gets you running in five minutes.</p>\n<p>For a comparison with other .NET frameworks, see <a class=\"\" href=\"https://logicgrid.dev/blog/langchain-vs-semantic-kernel-vs-logicgrid\">LangChain vs Semantic Kernel vs LogicGrid</a>.</p>",
            "url": "https://logicgrid.dev/blog/build-a-rag-pipeline-in-csharp",
            "title": "Build a RAG Pipeline in C# — From Zero to Hybrid Search",
            "summary": "A practical walkthrough for building a production-grade RAG pipeline in C#. Document loading, chunking, embeddings, vector storage, and hybrid search with BM25 + dense retrieval.",
            "date_modified": "2026-04-01T00:00:00.000Z",
            "author": {
                "name": "LogicGrid Team",
                "url": "https://logicgrid.dev"
            },
            "tags": [
                "rag",
                "csharp",
                "dotnet",
                "embeddings",
                "hybrid-search",
                "tutorial"
            ]
        },
        {
            "id": "https://logicgrid.dev/blog/how-to-use-ollama-with-csharp",
            "content_html": "<p>If you want to run an LLM from a C# application without sending data to OpenAI or Anthropic, <strong>Ollama is the easiest path</strong>. It runs llama3, mistral, qwen, deepseek, and dozens of other models on your laptop or server, and exposes a simple HTTP API.</p>\n<p>This guide walks through using Ollama from C# end-to-end — installation, basic chat, streaming, embeddings, tool calling, and the production gotchas you only learn after you ship.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"why-ollama-from-c\">Why Ollama from C#?<a href=\"https://logicgrid.dev/blog/how-to-use-ollama-with-csharp#why-ollama-from-c\" class=\"hash-link\" aria-label=\"Direct link to Why Ollama from C#?\" title=\"Direct link to Why Ollama from C#?\" translate=\"no\">​</a></h2>\n<p>Three real reasons teams choose this path:</p>\n<ol>\n<li class=\"\"><strong>Data privacy.</strong> Your prompts and responses never leave your network. Critical for regulated industries.</li>\n<li class=\"\"><strong>Cost.</strong> No per-token billing. A single GPU server can serve thousands of requests per day.</li>\n<li class=\"\"><strong>Latency.</strong> No round-trip to OpenAI's data centers. For interactive applications, sub-50ms first-token latency matters.</li>\n</ol>\n<p>The trade-off: smaller models, more infrastructure to manage, and a steeper learning curve around prompt engineering for less-capable models. For many use cases — summarization, classification, extraction, simple chatbots — that trade-off is worth it.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"step-1-install-ollama\">Step 1: Install Ollama<a href=\"https://logicgrid.dev/blog/how-to-use-ollama-with-csharp#step-1-install-ollama\" class=\"hash-link\" aria-label=\"Direct link to Step 1: Install Ollama\" title=\"Direct link to Step 1: Install Ollama\" translate=\"no\">​</a></h2>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token comment\" style=\"color:rgb(106, 153, 85)\"># macOS / Linux</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">curl</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:rgb(156, 220, 254)\">-fsSL</span><span class=\"token plain\"> https://ollama.ai/install.sh </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">|</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">sh</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:rgb(106, 153, 85)\"># Windows</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:rgb(106, 153, 85)\"># Download from https://ollama.ai/download</span><br></div></code></pre></div></div>\n<p>Pull a model:</p>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">ollama pull llama3.2</span><br></div></code></pre></div></div>\n<p>Verify it works:</p>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">ollama run llama3.2</span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">&gt;</span><span class=\"token plain\"> Hello</span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">Hello</span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">!</span><span class=\"token plain\"> How can I </span><span class=\"token builtin class-name\" style=\"color:rgb(78, 201, 176)\">help</span><span class=\"token plain\"> you today?</span><br></div></code></pre></div></div>\n<p>By default, Ollama listens on <code>http://localhost:11434</code>.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"step-2-talk-to-it-from-c--the-hard-way\">Step 2: Talk to it from C# — the hard way<a href=\"https://logicgrid.dev/blog/how-to-use-ollama-with-csharp#step-2-talk-to-it-from-c--the-hard-way\" class=\"hash-link\" aria-label=\"Direct link to Step 2: Talk to it from C# — the hard way\" title=\"Direct link to Step 2: Talk to it from C# — the hard way\" translate=\"no\">​</a></h2>\n<p>Ollama exposes an HTTP API. You can hit it directly:</p>\n<div class=\"language-csharp codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-csharp codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">using</span><span class=\"token plain\"> </span><span class=\"token namespace\">System</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Net</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Http</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">using</span><span class=\"token plain\"> </span><span class=\"token namespace\">System</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Net</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Http</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Json</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">using</span><span class=\"token plain\"> </span><span class=\"token namespace\">System</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Text</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Json</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> http </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">HttpClient</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token plain\"> BaseAddress </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">Uri</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"http://localhost:11434\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> request </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    model </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"llama3.2\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    prompt </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"What is the capital of France?\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    stream </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token boolean\">false</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> response </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> http</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">PostAsJsonAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"/api/generate\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> request</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> json </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> response</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token plain\">Content</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">ReadAsStringAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">using</span><span class=\"token plain\"> </span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> doc </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> JsonDocument</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">Parse</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\">json</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> answer </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> doc</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token plain\">RootElement</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">GetProperty</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"response\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">GetString</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">Console</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">WriteLine</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\">answer</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><br></div></code></pre></div></div>\n<p>This works, but you're now in the business of:</p>\n<ul>\n<li class=\"\">Hand-rolling HTTP retries when the model is loading (Ollama returns 503 for ~30s on first request)</li>\n<li class=\"\">Streaming responses (each token comes back as a separate JSON line)</li>\n<li class=\"\">Tool calling (Ollama's tool format is different from OpenAI's, but similar)</li>\n<li class=\"\">Embedding endpoints (a different API shape)</li>\n<li class=\"\">Switching providers (you'll rewrite all of this when you add OpenAI)</li>\n</ul>\n<p>For a one-off script that's fine. For anything that ships, you want a library.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"step-3-the-easy-way\">Step 3: The easy way<a href=\"https://logicgrid.dev/blog/how-to-use-ollama-with-csharp#step-3-the-easy-way\" class=\"hash-link\" aria-label=\"Direct link to Step 3: The easy way\" title=\"Direct link to Step 3: The easy way\" translate=\"no\">​</a></h2>\n<p><a class=\"\" href=\"https://logicgrid.dev/\">LogicGrid</a> provides a unified C# API across Ollama, OpenAI, Anthropic, Gemini, and any OpenAI-compatible endpoint. The Ollama integration is first-class, not an afterthought.</p>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">dotnet </span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">add</span><span class=\"token plain\"> package LogicGrid.Core</span><br></div></code></pre></div></div>\n<div class=\"language-csharp codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-csharp codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">using</span><span class=\"token plain\"> </span><span class=\"token namespace\">LogicGrid</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Core</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Agents</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">using</span><span class=\"token plain\"> </span><span class=\"token namespace\">LogicGrid</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Core</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> llm </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> LlmClientBase</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">Ollama</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"llama3.2\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name\" style=\"color:rgb(78, 201, 176)\">IAgent</span><span class=\"token plain\"> agent </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">Agent</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&lt;</span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&gt;</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">name</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Helper\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">description</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"A helpful assistant.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">systemPrompt</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Answer the user concisely.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> result </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> agent</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">RunAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"What is the capital of France?\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">AgentContext</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"ask\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">Console</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">WriteLine</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\">result</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><br></div></code></pre></div></div>\n<p>That's the entire program. Three using statements, four logical lines.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"working-with-full-responses\">Working with full responses<a href=\"https://logicgrid.dev/blog/how-to-use-ollama-with-csharp#working-with-full-responses\" class=\"hash-link\" aria-label=\"Direct link to Working with full responses\" title=\"Direct link to Working with full responses\" translate=\"no\">​</a></h2>\n<p><code>RunAsync</code> returns the complete LLM response once it's ready. For chat UIs that want tokens to appear progressively, you can drop down to the <code>LlmClientBase</code> directly and use the underlying chat-completion APIs the framework exposes — see the <a class=\"\" href=\"https://logicgrid.dev/docs/getting-started/providers\">provider docs</a> for the streaming patterns each provider supports.</p>\n<p>For most non-interactive workloads (summarization, classification, batch jobs) <code>RunAsync</code> is what you want.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"embeddings\">Embeddings<a href=\"https://logicgrid.dev/blog/how-to-use-ollama-with-csharp#embeddings\" class=\"hash-link\" aria-label=\"Direct link to Embeddings\" title=\"Direct link to Embeddings\" translate=\"no\">​</a></h2>\n<p>Ollama can generate embeddings using models like <code>nomic-embed-text</code> or <code>mxbai-embed-large</code>. These are useful for semantic search, RAG, clustering — anything where you need a vector representation of text.</p>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">ollama pull nomic-embed-text</span><br></div></code></pre></div></div>\n<div class=\"language-csharp codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-csharp codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">using</span><span class=\"token plain\"> </span><span class=\"token namespace\">LogicGrid</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Memory</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Embeddings</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> embedder </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">OllamaEmbeddingClient</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"nomic-embed-text\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">float</span><span class=\"token class-name punctuation\" style=\"color:rgb(212, 212, 212)\">[</span><span class=\"token class-name punctuation\" style=\"color:rgb(212, 212, 212)\">]</span><span class=\"token plain\"> vector </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> embedder</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">EmbedAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"The quick brown fox jumps over the lazy dog.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">Console</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">WriteLine</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token interpolation-string string\" style=\"color:rgb(206, 145, 120)\">$\"Vector length: </span><span class=\"token interpolation-string interpolation punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token interpolation-string interpolation expression language-csharp\">vector</span><span class=\"token interpolation-string interpolation expression language-csharp punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token interpolation-string interpolation expression language-csharp\">Length</span><span class=\"token interpolation-string interpolation punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token interpolation-string string\" style=\"color:rgb(206, 145, 120)\">\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:rgb(106, 153, 85)\">// 768 for nomic-embed-text</span><br></div></code></pre></div></div>\n<p>The same embedder plugs into LogicGrid's RAG pipeline:</p>\n<div class=\"language-csharp codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-csharp codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> pipeline </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">RagPipeline</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\">embedder</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">InMemoryVectorStore</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> pipeline</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">IngestAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"./docs/manual.txt\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> hits </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> pipeline</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">SearchAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"how do I configure SSL?\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">topK</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(181, 206, 168)\">3</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><br></div></code></pre></div></div>\n<p>See the <a class=\"\" href=\"https://logicgrid.dev/blog/build-a-rag-pipeline-in-csharp\">Build a RAG pipeline in C# guide</a> for the full pattern.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"tool-calling\">Tool calling<a href=\"https://logicgrid.dev/blog/how-to-use-ollama-with-csharp#tool-calling\" class=\"hash-link\" aria-label=\"Direct link to Tool calling\" title=\"Direct link to Tool calling\" translate=\"no\">​</a></h2>\n<p>Ollama-hosted models can use tools — functions you define in C# that the LLM decides to call when relevant. This is how you build agents that can hit your database, query an API, or read a file.</p>\n<div class=\"language-csharp codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-csharp codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">using</span><span class=\"token plain\"> </span><span class=\"token namespace\">System</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">ComponentModel</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">using</span><span class=\"token plain\"> </span><span class=\"token namespace\">LogicGrid</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Core</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Agents</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">using</span><span class=\"token plain\"> </span><span class=\"token namespace\">LogicGrid</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Core</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">using</span><span class=\"token plain\"> </span><span class=\"token namespace\">LogicGrid</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Core</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Tools</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">public</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">class</span><span class=\"token plain\"> </span><span class=\"token class-name\" style=\"color:rgb(78, 201, 176)\">WeatherArgs</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">[</span><span class=\"token attribute class-name\" style=\"color:rgb(78, 201, 176)\">Description</span><span class=\"token attribute attribute-arguments punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token attribute attribute-arguments string\" style=\"color:rgb(206, 145, 120)\">\"Name of the city to look up weather for.\"</span><span class=\"token attribute attribute-arguments punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">]</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">public</span><span class=\"token plain\"> </span><span class=\"token return-type class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token plain\"> City </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">get</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">set</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token plain\">Empty</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">public</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">sealed</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">class</span><span class=\"token plain\"> </span><span class=\"token class-name\" style=\"color:rgb(78, 201, 176)\">WeatherTool</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token type-list class-name\" style=\"color:rgb(78, 201, 176)\">ToolBase</span><span class=\"token type-list class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&lt;</span><span class=\"token type-list class-name\" style=\"color:rgb(78, 201, 176)\">WeatherArgs</span><span class=\"token type-list class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">public</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">override</span><span class=\"token plain\"> </span><span class=\"token return-type class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token plain\"> Name </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"get_weather\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">public</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">override</span><span class=\"token plain\"> </span><span class=\"token return-type class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token plain\"> Description </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">        </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Returns the current weather for a city.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">public</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">override</span><span class=\"token plain\"> </span><span class=\"token return-type class-name\" style=\"color:rgb(78, 201, 176)\">Task</span><span class=\"token return-type class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&lt;</span><span class=\"token return-type class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token return-type class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">ExecuteAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">        </span><span class=\"token class-name\" style=\"color:rgb(78, 201, 176)\">WeatherArgs</span><span class=\"token plain\"> args</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> </span><span class=\"token class-name\" style=\"color:rgb(78, 201, 176)\">CancellationToken</span><span class=\"token plain\"> ct </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">default</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">        </span><span class=\"token comment\" style=\"color:rgb(106, 153, 85)\">// Call your real weather API here</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">        </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">return</span><span class=\"token plain\"> Task</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">FromResult</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">            </span><span class=\"token interpolation-string string\" style=\"color:rgb(206, 145, 120)\">$\"Weather in </span><span class=\"token interpolation-string interpolation punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token interpolation-string interpolation expression language-csharp\">args</span><span class=\"token interpolation-string interpolation expression language-csharp punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token interpolation-string interpolation expression language-csharp\">City</span><span class=\"token interpolation-string interpolation punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token interpolation-string string\" style=\"color:rgb(206, 145, 120)\">: 18°C, partly cloudy.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> llm </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> LlmClientBase</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">Ollama</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"llama3.2\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name\" style=\"color:rgb(78, 201, 176)\">IAgent</span><span class=\"token plain\"> agent </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">Agent</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&lt;</span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&gt;</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">name</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"WeatherBot\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">description</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Tells the user the weather.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">systemPrompt</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Use tools when asked about weather.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">tools</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">ToolBase</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">[</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">]</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">WeatherTool</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">Console</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">WriteLine</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> agent</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">RunAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"What's the weather in Berlin?\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">AgentContext</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><br></div></code></pre></div></div>\n<p>LogicGrid auto-generates the JSON schema for each tool from the typed args class — you don't hand-write schema definitions.</p>\n<p><strong>Gotcha:</strong> not every Ollama model supports tool calling well. Stick to recent models from Meta (<code>llama3.2</code>, <code>llama3.3</code>) or Mistral (<code>mistral-nemo</code>) for reliable function calling. Older or smaller models will hallucinate tool arguments.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"production-gotchas-nobody-tells-you\">Production gotchas nobody tells you<a href=\"https://logicgrid.dev/blog/how-to-use-ollama-with-csharp#production-gotchas-nobody-tells-you\" class=\"hash-link\" aria-label=\"Direct link to Production gotchas nobody tells you\" title=\"Direct link to Production gotchas nobody tells you\" translate=\"no\">​</a></h2>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"1-the-first-request-after-a-cold-start-is-slow\">1. The first request after a cold start is slow<a href=\"https://logicgrid.dev/blog/how-to-use-ollama-with-csharp#1-the-first-request-after-a-cold-start-is-slow\" class=\"hash-link\" aria-label=\"Direct link to 1. The first request after a cold start is slow\" title=\"Direct link to 1. The first request after a cold start is slow\" translate=\"no\">​</a></h3>\n<p>Ollama keeps models in memory after first use, but the <em>first</em> request loads the model from disk — that can take 30+ seconds for a 7B model. Send a tiny warm-up request when your service starts:</p>\n<div class=\"language-csharp codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-csharp codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">CompleteAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"ping\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">maxTokens</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(181, 206, 168)\">1</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><br></div></code></pre></div></div>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"2-concurrent-requests-on-a-single-gpu-dont-help\">2. Concurrent requests on a single GPU don't help<a href=\"https://logicgrid.dev/blog/how-to-use-ollama-with-csharp#2-concurrent-requests-on-a-single-gpu-dont-help\" class=\"hash-link\" aria-label=\"Direct link to 2. Concurrent requests on a single GPU don't help\" title=\"Direct link to 2. Concurrent requests on a single GPU don't help\" translate=\"no\">​</a></h3>\n<p>Ollama serves one request at a time per model on the GPU. Sending 10 concurrent requests doesn't make them go faster — they queue. If you need throughput, run multiple Ollama instances behind a load balancer or use vLLM (which supports continuous batching).</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"3-context-windows-lie\">3. Context windows lie<a href=\"https://logicgrid.dev/blog/how-to-use-ollama-with-csharp#3-context-windows-lie\" class=\"hash-link\" aria-label=\"Direct link to 3. Context windows lie\" title=\"Direct link to 3. Context windows lie\" translate=\"no\">​</a></h3>\n<p><code>llama3.2</code> advertises 128k context. In practice quality degrades sharply past 8k–16k. Don't shovel huge documents in raw — chunk and retrieve.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"4-model-versions-move\">4. Model versions move<a href=\"https://logicgrid.dev/blog/how-to-use-ollama-with-csharp#4-model-versions-move\" class=\"hash-link\" aria-label=\"Direct link to 4. Model versions move\" title=\"Direct link to 4. Model versions move\" translate=\"no\">​</a></h3>\n<p><code>ollama pull llama3.2</code> pulls the latest tag, which can change. Pin a specific digest in production:</p>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">ollama pull llama3.2:3b-instruct-q4_K_M</span><br></div></code></pre></div></div>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"5-json-mode-is-unreliable-on-small-models\">5. JSON mode is unreliable on small models<a href=\"https://logicgrid.dev/blog/how-to-use-ollama-with-csharp#5-json-mode-is-unreliable-on-small-models\" class=\"hash-link\" aria-label=\"Direct link to 5. JSON mode is unreliable on small models\" title=\"Direct link to 5. JSON mode is unreliable on small models\" translate=\"no\">​</a></h3>\n<p>Tell <code>llama3.2:3b</code> to return JSON and you'll get JSON 95% of the time. The other 5% will be markdown-wrapped JSON, JSON with trailing commentary, or garbage. Always validate and parse defensively.</p>\n<p>LogicGrid's typed agents handle this — you specify <code>Agent&lt;T&gt;</code> with a structured output type and the framework retries with corrective prompts on parse failure.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"when-ollama-is-not-the-right-answer\">When Ollama is not the right answer<a href=\"https://logicgrid.dev/blog/how-to-use-ollama-with-csharp#when-ollama-is-not-the-right-answer\" class=\"hash-link\" aria-label=\"Direct link to When Ollama is not the right answer\" title=\"Direct link to When Ollama is not the right answer\" translate=\"no\">​</a></h2>\n<p>Ollama is great for development, on-prem deployment, and small-scale production. It is <strong>not</strong> great when:</p>\n<ul>\n<li class=\"\">You need batched throughput (use <strong>vLLM</strong> with <code>LlmClientBase.OpenAI</code> pointed at the vLLM endpoint)</li>\n<li class=\"\">You need top-tier model quality (Claude or GPT-4 still outperform anything you can run locally for complex reasoning)</li>\n<li class=\"\">You're embedding millions of documents (use a hosted embedding API or <strong>TEI</strong> for serious throughput)</li>\n</ul>\n<p>LogicGrid handles all of these — same code, different <code>LlmClientBase.*</code> factory call.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"next-steps\">Next steps<a href=\"https://logicgrid.dev/blog/how-to-use-ollama-with-csharp#next-steps\" class=\"hash-link\" aria-label=\"Direct link to Next steps\" title=\"Direct link to Next steps\" translate=\"no\">​</a></h2>\n<ul>\n<li class=\"\"><a class=\"\" href=\"https://logicgrid.dev/docs/getting-started/quickstart\">Quickstart</a> — build your first agent</li>\n<li class=\"\"><a class=\"\" href=\"https://logicgrid.dev/docs/getting-started/providers\">Provider setup</a> — Ollama, OpenAI, Anthropic, Gemini, vLLM, TEI</li>\n<li class=\"\"><a class=\"\" href=\"https://logicgrid.dev/blog/build-a-rag-pipeline-in-csharp\">Build a RAG pipeline</a> — full RAG walkthrough using Ollama embeddings</li>\n</ul>\n<p>If you're evaluating frameworks, the <a class=\"\" href=\"https://logicgrid.dev/blog/semantic-kernel-alternative-for-dotnet\">Semantic Kernel alternative</a> post covers the trade-offs in more depth.</p>",
            "url": "https://logicgrid.dev/blog/how-to-use-ollama-with-csharp",
            "title": "How to Use Ollama with C# — A Production-Ready Guide",
            "summary": "A complete walkthrough for running local LLMs from C# using Ollama. Covers setup, streaming, tool calling, embeddings, and the gotchas nobody tells you about.",
            "date_modified": "2026-03-26T00:00:00.000Z",
            "author": {
                "name": "LogicGrid Team",
                "url": "https://logicgrid.dev"
            },
            "tags": [
                "ollama",
                "csharp",
                "dotnet",
                "local-llm",
                "llama",
                "tutorial"
            ]
        },
        {
            "id": "https://logicgrid.dev/blog/semantic-kernel-alternative-for-dotnet",
            "content_html": "<p>If you're building an AI feature in .NET in 2026, the first framework you hear about is <strong>Microsoft Semantic Kernel</strong>. It's well-funded, actively maintained, and integrates deeply with Azure. For most projects, that's a fine starting point.</p>\n<p>But \"fine for most\" is not \"right for all.\" Over the last few months we've talked to teams who started with Semantic Kernel and ended up looking for something else. The reasons cluster around three themes: <strong>local LLM support, observability, and dependency footprint</strong>.</p>\n<p>This post is an honest comparison — not a hit piece. Semantic Kernel is a real piece of engineering. We just think it's worth understanding what trade-offs it makes, and what an alternative shaped around different priorities looks like.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"where-semantic-kernel-shines\">Where Semantic Kernel shines<a href=\"https://logicgrid.dev/blog/semantic-kernel-alternative-for-dotnet#where-semantic-kernel-shines\" class=\"hash-link\" aria-label=\"Direct link to Where Semantic Kernel shines\" title=\"Direct link to Where Semantic Kernel shines\" translate=\"no\">​</a></h2>\n<p>Let's start with what Semantic Kernel does well, because it's a lot:</p>\n<ul>\n<li class=\"\"><strong>Azure-native.</strong> If your stack is already Azure OpenAI + Azure AI Search + App Service, Semantic Kernel snaps into place with minimal ceremony.</li>\n<li class=\"\"><strong>First-party support.</strong> It's a Microsoft project. That alone reduces procurement friction in enterprise environments.</li>\n<li class=\"\"><strong>Plugins ecosystem.</strong> The plugin model is well-documented and Microsoft has shipped a steady stream of integrations.</li>\n<li class=\"\"><strong>Backed by serious R&amp;D.</strong> The team behind Semantic Kernel has poured real engineering into kernel orchestration, planners, and prompt templating.</li>\n</ul>\n<p>If your team is already invested in the Microsoft cloud and you're building features that look like \"summarize this Word doc\" or \"search our SharePoint,\" Semantic Kernel is probably the right tool.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"where-teams-start-looking-elsewhere\">Where teams start looking elsewhere<a href=\"https://logicgrid.dev/blog/semantic-kernel-alternative-for-dotnet#where-teams-start-looking-elsewhere\" class=\"hash-link\" aria-label=\"Direct link to Where teams start looking elsewhere\" title=\"Direct link to Where teams start looking elsewhere\" translate=\"no\">​</a></h2>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"1-local-llms-are-a-second-class-citizen\">1. Local LLMs are a second-class citizen<a href=\"https://logicgrid.dev/blog/semantic-kernel-alternative-for-dotnet#1-local-llms-are-a-second-class-citizen\" class=\"hash-link\" aria-label=\"Direct link to 1. Local LLMs are a second-class citizen\" title=\"Direct link to 1. Local LLMs are a second-class citizen\" translate=\"no\">​</a></h3>\n<p>Semantic Kernel can talk to Ollama. It can talk to LM Studio. But the developer experience is built around hosted APIs — Azure OpenAI, OpenAI, Anthropic — and local providers feel bolted on.</p>\n<p>This matters for a growing number of teams:</p>\n<ul>\n<li class=\"\"><strong>Regulated industries</strong> — banks, healthcare, defense — that can't ship customer data to OpenAI's servers</li>\n<li class=\"\"><strong>Cost-sensitive products</strong> that need to handle high request volumes without paying $0.001 per call</li>\n<li class=\"\"><strong>Edge deployments</strong> running on customer hardware with no internet connection</li>\n<li class=\"\"><strong>Air-gapped enterprises</strong> where any outbound traffic is a security incident</li>\n</ul>\n<p>If your roadmap includes local LLMs as a peer of hosted ones — not a fallback — you'll feel the friction.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"2-the-runtime-is-heavy\">2. The runtime is heavy<a href=\"https://logicgrid.dev/blog/semantic-kernel-alternative-for-dotnet#2-the-runtime-is-heavy\" class=\"hash-link\" aria-label=\"Direct link to 2. The runtime is heavy\" title=\"Direct link to 2. The runtime is heavy\" translate=\"no\">​</a></h3>\n<p>Add Semantic Kernel to a small console app and watch the dependency tree light up. The framework pulls in a lot — telemetry, ML.NET, abstractions on top of abstractions. For a CRUD API that wants to summarize a paragraph, that's a lot of surface area.</p>\n<p>It also makes auditing harder. If you need to ship to a customer who reads SBOMs, every transitive package is a question to answer.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"3-observability-is-opt-in-not-built-in\">3. Observability is opt-in, not built-in<a href=\"https://logicgrid.dev/blog/semantic-kernel-alternative-for-dotnet#3-observability-is-opt-in-not-built-in\" class=\"hash-link\" aria-label=\"Direct link to 3. Observability is opt-in, not built-in\" title=\"Direct link to 3. Observability is opt-in, not built-in\" translate=\"no\">​</a></h3>\n<p>Want to know how many tokens an agent run consumed? Want to trace exactly which tool was called and when? Want a structured event log of every retry, every fallback, every LLM call?</p>\n<p>You can get there with Semantic Kernel — by hooking OpenTelemetry, configuring listeners, and writing some glue code. But it's not the default. Most teams don't bother until something goes wrong in production, and then they're scrambling.</p>\n<p>For teams who've been burned by black-box AI behavior in production, observability-by-default is non-negotiable.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"what-an-alternative-looks-like\">What an alternative looks like<a href=\"https://logicgrid.dev/blog/semantic-kernel-alternative-for-dotnet#what-an-alternative-looks-like\" class=\"hash-link\" aria-label=\"Direct link to What an alternative looks like\" title=\"Direct link to What an alternative looks like\" translate=\"no\">​</a></h2>\n<p><a class=\"\" href=\"https://logicgrid.dev/\">LogicGrid</a> is a .NET-native multi-agent framework that takes a different posture on each of those three points. It's not better at everything — it's optimized for a different set of constraints.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"local-llms-are-first-class\">Local LLMs are first-class<a href=\"https://logicgrid.dev/blog/semantic-kernel-alternative-for-dotnet#local-llms-are-first-class\" class=\"hash-link\" aria-label=\"Direct link to Local LLMs are first-class\" title=\"Direct link to Local LLMs are first-class\" translate=\"no\">​</a></h3>\n<div class=\"language-csharp codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-csharp codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token comment\" style=\"color:rgb(106, 153, 85)\">// Same agent. Any provider. Zero code change.</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> llm </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> LlmClientBase</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">Ollama</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"llama3.2\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:rgb(106, 153, 85)\">// var llm = LlmClientBase.OpenAI(\"gpt-4o\");</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:rgb(106, 153, 85)\">// var llm = LlmClientBase.Anthropic(\"claude-sonnet-4-6\");</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:rgb(106, 153, 85)\">// var llm = LlmClientBase.Gemini(\"gemini-2.0-flash\");</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name\" style=\"color:rgb(78, 201, 176)\">IAgent</span><span class=\"token plain\"> agent </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">Agent</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&lt;</span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&gt;</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">name</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Summariser\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">description</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Summarises any text concisely.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">systemPrompt</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Summarise the following in 2-3 sentences: {{input}}\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> result </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> agent</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">RunAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Long document text...\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">AgentContext</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"run-1\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><br></div></code></pre></div></div>\n<p>Switching from Ollama to Claude is a one-line change. Streaming, tool calling, and embeddings work the same way across every provider. There's no \"OpenAI is the real path; Ollama is the demo path.\"</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"zero-hidden-runtime-dependencies\">Zero hidden runtime dependencies<a href=\"https://logicgrid.dev/blog/semantic-kernel-alternative-for-dotnet#zero-hidden-runtime-dependencies\" class=\"hash-link\" aria-label=\"Direct link to Zero hidden runtime dependencies\" title=\"Direct link to Zero hidden runtime dependencies\" translate=\"no\">​</a></h3>\n<p>LogicGrid targets <code>netstandard2.0</code>, <code>net6.0</code>, and <code>net8.0</code>. The full SBOM is published as <code>bom.json</code> in <a href=\"https://github.com/logicgrid-dev/logicgrid\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">the public repo</a>. The only thing you're pulling in is what's strictly needed.</p>\n<p>For air-gapped deployments, that matters: you can audit the entire dependency graph before the package touches your build server.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"observability-by-default\">Observability by default<a href=\"https://logicgrid.dev/blog/semantic-kernel-alternative-for-dotnet#observability-by-default\" class=\"hash-link\" aria-label=\"Direct link to Observability by default\" title=\"Direct link to Observability by default\" translate=\"no\">​</a></h3>\n<p>Every agent step, tool call, retry, and LLM call emits a structured event:</p>\n<div class=\"language-csharp codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-csharp codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> ctx </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">AgentContext</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">WithLogging</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">WithTracing</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">out</span><span class=\"token plain\"> </span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> trace</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> agent</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">RunAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Hello\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> ctx</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:rgb(106, 153, 85)\">// trace contains every step, tool call, retry, and LLM call</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">foreach</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> span </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">in</span><span class=\"token plain\"> trace</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token plain\">Spans</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    Console</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">WriteLine</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token interpolation-string string\" style=\"color:rgb(206, 145, 120)\">$\"</span><span class=\"token interpolation-string interpolation punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token interpolation-string interpolation expression language-csharp\">span</span><span class=\"token interpolation-string interpolation expression language-csharp punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token interpolation-string interpolation expression language-csharp\">Name</span><span class=\"token interpolation-string interpolation punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token interpolation-string string\" style=\"color:rgb(206, 145, 120)\"> — </span><span class=\"token interpolation-string interpolation punctuation\" style=\"color:rgb(212, 212, 212)\">{</span><span class=\"token interpolation-string interpolation expression language-csharp\">span</span><span class=\"token interpolation-string interpolation expression language-csharp punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token interpolation-string interpolation expression language-csharp\">Duration</span><span class=\"token interpolation-string interpolation expression language-csharp punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token interpolation-string interpolation expression language-csharp\">TotalMilliseconds</span><span class=\"token interpolation-string interpolation format-string punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token interpolation-string interpolation format-string\">F0</span><span class=\"token interpolation-string interpolation punctuation\" style=\"color:rgb(212, 212, 212)\">}</span><span class=\"token interpolation-string string\" style=\"color:rgb(206, 145, 120)\">ms\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><br></div></code></pre></div></div>\n<p>You don't have to opt into telemetry. You opt out if you don't want it.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"migration-considerations\">Migration considerations<a href=\"https://logicgrid.dev/blog/semantic-kernel-alternative-for-dotnet#migration-considerations\" class=\"hash-link\" aria-label=\"Direct link to Migration considerations\" title=\"Direct link to Migration considerations\" translate=\"no\">​</a></h2>\n<p>If you're considering moving from Semantic Kernel to LogicGrid, the conversion is generally straightforward — both frameworks model the same concepts (agents, tools, memory) but with different APIs. The biggest mental shift is around orchestration: Semantic Kernel encourages a \"planner\" mindset where the LLM decides the workflow; LogicGrid encourages explicit graphs where you decide the workflow and the LLM fills in the steps.</p>\n<p>Neither approach is wrong — but if you've been frustrated by Semantic Kernel planners going off-script, LogicGrid's <a class=\"\" href=\"https://logicgrid.dev/docs/orchestration/graph\">graph orchestration</a> will feel like a relief.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"when-not-to-switch\">When <strong>not</strong> to switch<a href=\"https://logicgrid.dev/blog/semantic-kernel-alternative-for-dotnet#when-not-to-switch\" class=\"hash-link\" aria-label=\"Direct link to when-not-to-switch\" title=\"Direct link to when-not-to-switch\" translate=\"no\">​</a></h2>\n<p>If any of these are true, stick with Semantic Kernel:</p>\n<ul>\n<li class=\"\">Your stack is fully on Azure and you use Azure OpenAI exclusively</li>\n<li class=\"\">You need first-party Microsoft support contracts</li>\n<li class=\"\">Your team has already invested significant tooling and training in Semantic Kernel</li>\n<li class=\"\">You're building primarily for Microsoft 365 / Copilot integration</li>\n</ul>\n<p>LogicGrid is a better fit when:</p>\n<ul>\n<li class=\"\">Local LLMs are part of your roadmap, not a side note</li>\n<li class=\"\">You ship to enterprises who scrutinize dependencies</li>\n<li class=\"\">You want observability without writing your own telemetry layer</li>\n<li class=\"\">You're targeting older .NET versions (.NET Framework 4.7.2+ via <code>netstandard2.0</code>)</li>\n</ul>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"try-it-in-5-minutes\">Try it in 5 minutes<a href=\"https://logicgrid.dev/blog/semantic-kernel-alternative-for-dotnet#try-it-in-5-minutes\" class=\"hash-link\" aria-label=\"Direct link to Try it in 5 minutes\" title=\"Direct link to Try it in 5 minutes\" translate=\"no\">​</a></h2>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">dotnet </span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">add</span><span class=\"token plain\"> package LogicGrid.Core</span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">ollama pull llama3.2</span><br></div></code></pre></div></div>\n<div class=\"language-csharp codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#9CDCFE;--prism-background-color:#1E1E1E\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-csharp codeBlock_bY9V thin-scrollbar\" style=\"color:#9CDCFE;background-color:#1E1E1E\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">using</span><span class=\"token plain\"> </span><span class=\"token namespace\">LogicGrid</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Core</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Agents</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">using</span><span class=\"token plain\"> </span><span class=\"token namespace\">LogicGrid</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Core</span><span class=\"token namespace punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token namespace\">Llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> llm </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> LlmClientBase</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">Ollama</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"llama3.2\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name\" style=\"color:rgb(78, 201, 176)\">IAgent</span><span class=\"token plain\"> agent </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">Agent</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&lt;</span><span class=\"token constructor-invocation class-name keyword\" style=\"color:rgb(86, 156, 214)\">string</span><span class=\"token constructor-invocation class-name punctuation\" style=\"color:rgb(212, 212, 212)\">&gt;</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">name</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Helper\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">description</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Answers questions concisely.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">systemPrompt</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"Answer in one short sentence.\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token named-parameter punctuation\" style=\"color:rgb(212, 212, 212)\">llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">:</span><span class=\"token plain\"> llm</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\"></span><span class=\"token class-name keyword\" style=\"color:rgb(86, 156, 214)\">var</span><span class=\"token plain\"> result </span><span class=\"token operator\" style=\"color:rgb(212, 212, 212)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">await</span><span class=\"token plain\"> agent</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">RunAsync</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">    </span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"What is the capital of France?\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">,</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(86, 156, 214)\">new</span><span class=\"token plain\"> </span><span class=\"token constructor-invocation class-name\" style=\"color:rgb(78, 201, 176)\">AgentContext</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token string\" style=\"color:rgb(206, 145, 120)\">\"run-1\"</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#9CDCFE\"><span class=\"token plain\">Console</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">.</span><span class=\"token function\" style=\"color:rgb(220, 220, 170)\">WriteLine</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">(</span><span class=\"token plain\">result</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">)</span><span class=\"token punctuation\" style=\"color:rgb(212, 212, 212)\">;</span><br></div></code></pre></div></div>\n<p>That's it. No <code>appsettings.json</code> ritual, no SDK initialization dance, no API keys (until you want to use a hosted provider).</p>\n<p>If you've been frustrated with Semantic Kernel's posture toward local LLMs or its dependency weight — give LogicGrid 30 minutes. If it doesn't fit, you'll know quickly. If it does, the <a class=\"\" href=\"https://logicgrid.dev/docs/getting-started/quickstart\">quickstart</a> walks you through the next steps.</p>\n<hr>\n<p><strong>Want a deeper comparison?</strong> The follow-up post <a class=\"\" href=\"https://logicgrid.dev/blog/langchain-vs-semantic-kernel-vs-logicgrid\">LangChain vs Semantic Kernel vs LogicGrid</a> goes feature-by-feature across all three frameworks.</p>",
            "url": "https://logicgrid.dev/blog/semantic-kernel-alternative-for-dotnet",
            "title": "A Semantic Kernel Alternative for .NET — When and Why You'd Reach for One",
            "summary": "Microsoft Semantic Kernel is the default agent framework for .NET. Here's an honest look at where it shines, where it struggles, and what an alternative built around local LLMs and observability looks like.",
            "date_modified": "2026-03-15T00:00:00.000Z",
            "author": {
                "name": "LogicGrid Team",
                "url": "https://logicgrid.dev"
            },
            "tags": [
                "dotnet",
                "csharp",
                "semantic-kernel",
                "ai-agents",
                "llm",
                "comparison"
            ]
        }
    ]
}