{"id":60832,"date":"2026-09-16T14:00:00","date_gmt":"2026-09-16T21:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/dotnet\/?p=60832"},"modified":"2026-09-16T14:00:00","modified_gmt":"2026-09-16T21:00:00","slug":"build-your-own-ai-agent-harness-in-csharp-the-maf-claw-live-series","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/build-your-own-ai-agent-harness-in-csharp-the-maf-claw-live-series\/","title":{"rendered":"Build Your Own AI Agent Harness in C#, the MafClaw Live Series"},"content":{"rendered":"<p>A few weeks ago I wrote about going <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/from-dotnet-run-to-foundry-hosted-agent-in-3-lines-of-csharp\/\">from <code>dotnet run<\/code> to a Foundry Hosted Agent in three lines of C#<\/a>. The feedback was great. Developers liked the deployment story, the managed infrastructure, and especially the part where we did <strong>not<\/strong> spend the afternoon writing a Dockerfile, a session store, a telemetry pipeline, and a small distributed system just to expose one agent \ud83d\ude05.<\/p>\n<p>But that post starts near the end of the journey. It assumes you already have an agent worth deploying.<\/p>\n<p>So the next question is:<\/p>\n<blockquote>\n<p>&#8220;What should I put inside the agent before I deploy it?&#8221;<\/p>\n<\/blockquote>\n<p>Tools. Planning. Safe file access. Human approval. Memory. Skills. Shell commands. Code execution. Background agents. Observability. Governance. Evaluations.<\/p>\n<p>That list gets big very quickly.<\/p>\n<p>The good news is that you do not need to build the runtime for all of it from scratch. Microsoft Agent Framework includes an <strong>agent harness<\/strong>, and I am building a complete C# agent with it live, one capability at a time, in a four-part series called <strong>From Model to Agent: The Agent Framework Harness, Live in C#<\/strong>.<\/p>\n<p>The series streams live simultaneously on the <strong><a href=\"https:\/\/www.youtube.com\/@dotnet\">.NET YouTube channel<\/a><\/strong> and <strong>Microsoft Reactor<\/strong>, four consecutive Thursdays in September, and every session stays available afterward on demand on both platforms. Two sessions are already available, and two more are coming. Let me show you what we are building and why the harness makes this much easier.<\/p>\n<p><div  class=\"d-flex justify-content-center\"><a class=\"cta_button_link btn-primary mb-24\" href=\"https:\/\/aka.ms\/mafclaw\" target=\"_blank\">Register for the live Agent Framework series<\/a><\/div><\/p>\n<h2>What we build across four sessions<\/h2>\n<p>We start with this:<\/p>\n<pre><code class=\"language-csharp\">AIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions\n{\n    ChatOptions = new ChatOptions\n    {\n        Instructions = instructions,\n        Tools = tools\n    }\n});<\/code><\/pre>\n<p>Then we grow the same agent through four stages:<\/p>\n<ol>\n<li>Give it tools, web search, and a plan.<\/li>\n<li>Let it work with files, approvals, and durable memory.<\/li>\n<li>Add skills, shell, CodeAct, and background agents.<\/li>\n<li>Add observability, governance, evaluations, and a hosted deployment.<\/li>\n<\/ol>\n<p>That is the complete journey: from one call around an <code>IChatClient<\/code> to a capable agent that we can inspect, evaluate, govern, and run in Microsoft Foundry.<\/p>\n<h2>First: what is an agent harness?<\/h2>\n<p>A language model can generate text. An agent needs more.<\/p>\n<p>It needs a loop that can call tools, inspect the results, update a plan, remember useful information, request approval for risky actions, manage a growing context window, and keep working until the task is complete.<\/p>\n<p>That surrounding runtime is the <strong>harness<\/strong>.<\/p>\n<p><div class=\"alert alert-success\"><p class=\"alert-divider\"><i class=\"fabric-icon fabric-icon--Lightbulb\"><\/i><strong>Where the term comes from<\/strong><\/p>The Microsoft Agent Framework team introduced the concept in the excellent <a href=\"https:\/\/devblogs.microsoft.com\/agent-framework\/build-your-own-claw-and-agent-harness-with-microsoft-agent-framework\/\">Build your own claw and agent harness with Microsoft Agent Framework<\/a> series. Their explanation is simple: a &#8220;claw&#8221; is a CLI-style agent built on top of a harness. You bring the model, instructions, and domain tools. The harness supplies the agentic machinery around them.<\/div><\/p>\n<p>In .NET, the key line is this one:<\/p>\n<pre><code class=\"language-csharp\">AIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions\n{\n    ChatOptions = new ChatOptions\n    {\n        Instructions = \"You are a personal finance education assistant.\",\n        Tools = [StockTools.GetStockPrice]\n    }\n});<\/code><\/pre>\n<p>That call gives the agent a complete pipeline with capabilities such as:<\/p>\n<ul>\n<li>automatic function invocation<\/li>\n<li>history persistence after model calls<\/li>\n<li>planning with todo and agent-mode providers<\/li>\n<li>context compaction<\/li>\n<li>file memory<\/li>\n<li>web search when the model service supports it<\/li>\n<li>tool approvals<\/li>\n<li>skills<\/li>\n<li>OpenTelemetry instrumentation<\/li>\n<\/ul>\n<p>Each capability is configurable. You can replace it, disable it, or add your own provider.<\/p>\n<p>That is the advantage of starting with the harness: you spend your time on what makes the agent useful, instead of rebuilding the same orchestration loop for every project.<\/p>\n<h2>The agent we are building<\/h2>\n<p>Across the four sessions, we build one personal finance education assistant.<\/p>\n<p>Why finance? Because it gives us realistic boundaries to discuss:<\/p>\n<ul>\n<li>Looking up a stock price is a read-only tool call.<\/li>\n<li>Reading a portfolio means accessing user data.<\/li>\n<li>Writing a report changes a file.<\/li>\n<li>Placing a simulated trade is a side effect and needs approval.<\/li>\n<li>Remembering a risk profile needs durable, user-scoped memory.<\/li>\n<li>Calculating portfolio value is better done with code than model arithmetic.<\/li>\n<li>Running shell commands requires confinement and policy.<\/li>\n<li>A production finance agent needs traces, governance, and evaluations.<\/li>\n<\/ul>\n<p><div class=\"alert alert-primary\"><p class=\"alert-divider\"><i class=\"fabric-icon fabric-icon--Info\"><\/i><strong>This is a learning scenario<\/strong><\/p>All prices and transactions in the samples are mock and illustrative. This is not financial advice. It is a useful scenario for learning how agent systems behave when tools have different levels of risk.<\/div><\/p>\n<p>The complete code is in the <a href=\"https:\/\/aka.ms\/mafclaw\/repo\">MafClaw sample repository<\/a>.<\/p>\n<h2>Session 1: turn a model into an agent<\/h2>\n<p>In <a href=\"https:\/\/www.youtube.com\/watch?v=iUs15X1v2w4\">Meet Your Claw: A Harness in Three Lines of C#<\/a>, we started with the smallest useful agent.<\/p>\n<p>First, create an <code>IChatClient<\/code> backed by a model in Microsoft Foundry:<\/p>\n<pre><code class=\"language-csharp\">IChatClient chatClient =\n    new AIProjectClient(new Uri(endpoint), new AzureCliCredential())\n        .GetProjectOpenAIClient()\n        .GetResponsesClient()\n        .AsIChatClient(model);<\/code><\/pre>\n<p>Then wrap it with the harness and give it one custom tool:<\/p>\n<pre><code class=\"language-csharp\">AIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions\n{\n    ChatOptions = new ChatOptions\n    {\n        Instructions = \"\"\"\n            You are a personal finance education assistant.\n            Use get_stock_price for stock prices.\n            Use hosted web search for recent market news and cite sources.\n            Use the todo list to track multi-step work.\n            \"\"\",\n        Tools = [StockTools.GetStockPrice]\n    }\n});<\/code><\/pre>\n<p>The custom tool is ordinary C#. Agent Framework generates its tool schema from the function signature and descriptions:<\/p>\n<pre><code class=\"language-csharp\">[Description(\"Gets the illustrative stock price for a ticker symbol.\")]\npublic static string GetStockPriceBySymbol(\n    [Description(\"Stock ticker symbol, e.g. MSFT\")] string symbol)\n{\n    var upper = symbol.Trim().ToUpperInvariant();\n    return upper switch\n    {\n        \"MSFT\" =&gt; \"MSFT: 512.34 USD (mock)\",\n        \"NVDA\" =&gt; \"NVDA: 184.72 USD (mock)\",\n        \"AMZN\" =&gt; \"AMZN: 241.18 USD (mock)\",\n        _ =&gt; $\"{upper}: not available\"\n    };\n}\n\npublic static AIFunction GetStockPrice { get; } =\n    AIFunctionFactory.Create(\n        GetStockPriceBySymbol,\n        \"get_stock_price\");<\/code><\/pre>\n<p>Now the difference between a chat application and an agent becomes visible.<\/p>\n<p>Ask:<\/p>\n<pre><code class=\"language-text\">What is the price of MSFT?<\/code><\/pre>\n<p>The model chooses the tool, the harness invokes it, the result returns to the model, and the agent produces the final answer.<\/p>\n<p>Ask something larger:<\/p>\n<pre><code class=\"language-text\">Review my watchlist and suggest what I should research next.<\/code><\/pre>\n<p>The harness can create a plan and maintain a todo list while it works. We did not write a custom planning engine for the demo. We configured the behavior that makes this finance agent ours, and the harness supplied the planning runtime.<\/p>\n<p>This first session is available now:<\/p>\n<p><iframe loading=\"lazy\" width=\"800\" height=\"450\" src=\"https:\/\/www.youtube.com\/embed\/iUs15X1v2w4\" allowfullscreen><\/iframe><\/p>\n<h2>Session 2: work with user data safely<\/h2>\n<p>An agent becomes much more useful when it can work with your data.<\/p>\n<p>It also becomes much more dangerous.<\/p>\n<p>In <a href=\"https:\/\/www.youtube.com\/watch?v=V58coa0llUo\">Working With Your Data, Safely: Files, Approvals and Memory<\/a>, we gave the finance assistant access to a portfolio CSV, but only inside an approved working directory:<\/p>\n<pre><code class=\"language-csharp\">var workingDirectory =\n    Path.Combine(AppContext.BaseDirectory, \"working\");\n\nAIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions\n{\n    FileAccessStore =\n        new FileSystemAgentFileStore(workingDirectory),\n\n    ChatOptions = new ChatOptions\n    {\n        Instructions = \"\"\"\n            The user's portfolio is in portfolio.csv.\n            Read it before answering portfolio questions.\n            Write generated reports under the approved working folder.\n            \"\"\",\n    }\n});<\/code><\/pre>\n<p>The model does not receive arbitrary filesystem access. The application supplies a file store rooted at one folder, and the harness exposes file tools against that boundary.<\/p>\n<p>This means the happy path works:<\/p>\n<pre><code class=\"language-text\">What is in my portfolio?<\/code><\/pre>\n<p>And the unsafe path is blocked:<\/p>\n<pre><code class=\"language-text\">Read C:\\some-other-folder\\outside-portfolio.csv<\/code><\/pre>\n<p>The second boundary is human approval.<\/p>\n<p>A simulated trade is wrapped in <code>ApprovalRequiredAIFunction<\/code>:<\/p>\n<pre><code class=\"language-csharp\">public static AIFunction RequestSimulatedTrade { get; } =\n    new ApprovalRequiredAIFunction(\n        AIFunctionFactory.Create(\n            RequestSimulatedTradeOrder,\n            \"request_simulated_trade\"));<\/code><\/pre>\n<p>The model can request the action, but it cannot execute it directly. Harness emits an approval request first. The host application can show exactly which tool and arguments need approval, then return the human decision to the same agent session.<\/p>\n<p>We also configured a low-friction safe path:<\/p>\n<pre><code class=\"language-csharp\">ToolApprovalAgentOptions = new ToolApprovalAgentOptions\n{\n    AutoApprovalRules =\n    [\n        FileAccessProvider.ReadOnlyToolsAutoApprovalRule\n    ],\n},<\/code><\/pre>\n<p>Read-only file operations can proceed automatically. Writes, destructive operations, and the simulated trade still cross an approval boundary.<\/p>\n<p>That distinction matters. If every harmless read interrupts the user, approval becomes noise. The goal is not to show more confirmation dialogs. The goal is to make consequential actions visible.<\/p>\n<h3>A question from the audience became a new sample<\/h3>\n<p>During the live Q&amp;A, someone asked:<\/p>\n<blockquote>\n<p>&#8220;What if the user does not answer the approval request?&#8221;<\/p>\n<\/blockquote>\n<p>Great question.<\/p>\n<p><div class=\"alert alert-primary\"><p class=\"alert-divider\"><i class=\"fabric-icon fabric-icon--Info\"><\/i><strong>Silence is not consent<\/strong><\/p>An approval flow that waits forever is not complete. So, after the session, I built a new sample with a bounded approval policy: a five-second deadline per attempt, a maximum of five attempts, retries for missing or invalid input, immediate approval for <code>y<\/code>, immediate denial for <code>n<\/code>, automatic denial after the final attempt, sticky denial for the rest of the user prompt, and a limit on repeated approval rounds from the model.<\/div><\/p>\n<p>The policy starts with a small configuration:<\/p>\n<pre><code class=\"language-csharp\">const int maxApprovalAttempts = 5;\nvar approvalTimeout = TimeSpan.FromSeconds(5);\n\nvar approvalPolicy = new TimedApprovalPolicy(\n    maxApprovalAttempts,\n    approvalTimeout);<\/code><\/pre>\n<p>You can find the complete implementation in <a href=\"https:\/\/github.com\/elbruno\/mafclaw\/tree\/main\/session-02\/samples\/22-approval-retries-timeouts\">Sample 22: approval retries and timeouts<\/a>.<\/p>\n<p>The final part of Session 2 was memory. We compared local, application-owned JSON memory with managed Foundry Memory, and discussed why the model saying &#8220;I saved that&#8221; is not proof that anything was persisted. The application needs a real storage result, a scope, and a way to surface failures.<\/p>\n<p>Session 2 is also available now:<\/p>\n<p><a href=\"https:\/\/www.youtube.com\/watch?v=V58coa0llUo\">\u25b6 Watch Session 2: Files, Approvals and Memory<\/a><\/p>\n<h2>Session 3: skills, shell, CodeAct, and background agents<\/h2>\n<p>The first two sessions make the agent useful and safe. The third makes it more capable.<\/p>\n<p>In <a href=\"https:\/\/www.youtube.com\/watch?v=dCIBza-WxUc\">Scaling the Claw: Skills, Shell, CodeAct and Background Agents<\/a>, we cover four different ways to expand an agent without turning its system prompt into a 400-page instruction manual:<\/p>\n<ul>\n<li><strong>Skills<\/strong> package domain knowledge in discoverable files. The agent sees a short description and loads the full instructions only when a request needs them, instead of stuffing every valuation and risk-scoring rule into the main prompt.<\/li>\n<li><strong>Shell<\/strong> access lets the agent perform tasks that are naturally expressed as commands, such as organizing files or inspecting a directory, inside a confined working directory with command policy, execution timeouts, and explicit approval.<\/li>\n<li><strong>CodeAct<\/strong> lets the agent write and run code in a controlled execution environment, which is more reliable and auditable than asking the model to perform arithmetic in prose.<\/li>\n<li><strong>Background agents<\/strong> let the main agent delegate independent research tasks, such as looking into MSFT, NVDA, and SPY in parallel, to separate agents that run concurrently and report back.<\/li>\n<\/ul>\n<p><div class=\"alert alert-warning\"><p class=\"alert-divider\"><i class=\"fabric-icon fabric-icon--Warning\"><\/i><strong>Confinement, not just approval<\/strong><\/p>Shell and code execution are powerful capabilities. Confinement, policy, and approval improve the experience, but they are not a substitute for isolation. That boundary still matters.<\/div><\/p>\n<p>We build all four live, with the finance assistant as the running example.<\/p>\n<p><a href=\"https:\/\/www.youtube.com\/watch?v=dCIBza-WxUc\">Watch or register for Session 3<\/a><\/p>\n<h2>Session 4: make the agent production-ready<\/h2>\n<p>At this point the claw can plan, use tools, work with files, request approvals, remember facts, load skills, execute code, and delegate research.<\/p>\n<p>That is the moment when somebody asks:<\/p>\n<blockquote>\n<p>&#8220;OK, the agent is done\u2026 now, how do I deploy this thing?&#8221;<\/p>\n<\/blockquote>\n<p>Yes, we are back to the question from my previous post \ud83d\ude04.<\/p>\n<p>In <a href=\"https:\/\/www.youtube.com\/watch?v=rMhX0-oE4aY\">Production Ready: Observability, Governance and Deployment<\/a>, we close the loop with:<\/p>\n<ol>\n<li><strong>Observability<\/strong> with OpenTelemetry traces, tool calls, model calls, and token usage, so you can see what the agent actually did.<\/li>\n<li><strong>Governance<\/strong> with Microsoft Purview policy integration, so organizational policy applies to agent behavior, not just human behavior.<\/li>\n<li><strong>Evaluations<\/strong> for repeatable quality checks, so &#8220;it felt right in the demo&#8221; becomes a measurable signal.<\/li>\n<li><strong>Deployment<\/strong> as a Foundry Hosted Agent, sharing one agent definition across a console app, a hosted endpoint, and an evaluation harness, each enabling only the capabilities appropriate for that host.<\/li>\n<\/ol>\n<p><div class=\"alert alert-info\"><p class=\"alert-divider\"><i class=\"fabric-icon fabric-icon--Info\"><\/i><strong>A production decision, not a framework limitation<\/strong><\/p>A shared hosted container should not inherit arbitrary local filesystem or shell access just because those capabilities were useful during development. Every capability the harness gives you locally has a production-appropriate equivalent, and choosing between them is a deliberate decision, not something the framework decides for you.<\/div><\/p>\n<p>The exact deployment approach follows the container-hosting setup from the Agent Framework sample. My earlier <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/from-dotnet-run-to-foundry-hosted-agent-in-3-lines-of-csharp\/\">three-lines-of-C# post<\/a> remains a useful introduction to the hosting model, but this claw has extra capabilities and therefore extra production decisions.<\/p>\n<p>We build the observability, governance, evaluation, and deployment story live in this final session.<\/p>\n<p><a href=\"https:\/\/www.youtube.com\/watch?v=rMhX0-oE4aY\">Watch or register for Session 4<\/a><\/p>\n<h2>Why start with the harness?<\/h2>\n<p>You can build every one of these pieces yourself.<\/p>\n<p>You can write a tool loop, serialize history after every service call, maintain a plan, compact context, build a memory layer, design an approval protocol, load skills, manage background workers, and instrument the whole pipeline.<\/p>\n<p>Sometimes you need that level of control.<\/p>\n<p>But most teams want to spend their time on the domain behavior that makes the agent valuable:<\/p>\n<ul>\n<li>What tools should it have?<\/li>\n<li>What data can it access?<\/li>\n<li>Which actions require approval?<\/li>\n<li>What should it remember?<\/li>\n<li>Which skills should it load?<\/li>\n<li>Which tasks can run concurrently?<\/li>\n<li>What policies apply?<\/li>\n<li>How will we evaluate whether it works?<\/li>\n<\/ul>\n<p>The harness gives those decisions a composable home.<\/p>\n<p>You still own the boundaries. You still choose the tools. You still decide what gets approved, remembered, executed, traced, and deployed.<\/p>\n<p>You just do not have to rebuild the agent runtime before answering any of those questions.<\/p>\n<h2>Join the series<\/h2>\n<p>The Microsoft Agent Framework blog has the complete written, .NET-and-Python version of this journey:<\/p>\n<ul>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/agent-framework\/build-your-own-claw-and-agent-harness-with-microsoft-agent-framework\/\">Build your own claw and agent harness with Microsoft Agent Framework<\/a><\/li>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/agent-framework\/meet-your-agent-harness-and-claw\/\">Part 1: Meet your agent harness and claw<\/a><\/li>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/agent-framework\/agent-harness-working-with-your-data-safely\/\">Part 2: Working with your data, safely<\/a><\/li>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/agent-framework\/agent-harness-scaling-the-claw-or-harness-capabilities\/\">Part 3: Scaling the claw<\/a><\/li>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/agent-framework\/agent-harness-making-your-claw-production-ready\/\">Part 4: Making your claw production-ready<\/a><\/li>\n<\/ul>\n<p>And in the series, we build the .NET version live, one capability at a time, streaming live simultaneously on the <a href=\"https:\/\/www.youtube.com\/@dotnet\">.NET YouTube channel<\/a> and Microsoft Reactor, four consecutive Thursdays in September, then staying available on demand on both platforms:<\/p>\n<ol>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=iUs15X1v2w4\">Meet Your Claw: A Harness in Three Lines of C#<\/a><\/li>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=V58coa0llUo\">Working With Your Data, Safely: Files, Approvals and Memory<\/a><\/li>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=dCIBza-WxUc\">Scaling the Claw: Skills, Shell, CodeAct and Background Agents<\/a><\/li>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=rMhX0-oE4aY\">Production Ready: Observability, Governance and Deployment<\/a><\/li>\n<\/ol>\n<p><div  class=\"d-flex justify-content-center\"><a class=\"cta_button_link btn-primary mb-24\" href=\"https:\/\/aka.ms\/mafclaw\" target=\"_blank\">Register for the live Agent Framework series<\/a><\/div>\n<div  class=\"d-flex justify-content-center\"><a class=\"cta_button_link btn-primary mb-24\" href=\"https:\/\/aka.ms\/mafclaw\/repo\" target=\"_blank\">Get the complete C# samples<\/a><\/div><\/p>\n<p>Bring your questions. The approval timeout sample exists because someone did exactly that.<\/p>\n<h2>Learn more<\/h2>\n<ul>\n<li><a href=\"https:\/\/aka.ms\/mafclaw\/blog\">Series introduction: From Model to Agent<\/a><\/li>\n<li><a href=\"https:\/\/aka.ms\/mafclaw\">Microsoft Reactor series page<\/a><\/li>\n<li><a href=\"https:\/\/www.youtube.com\/@dotnet\">.NET YouTube channel<\/a><\/li>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=iUs15X1v2w4\">Session 1: Meet Your Claw: A Harness in Three Lines of C#<\/a><\/li>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=V58coa0llUo\">Session 2: Working With Your Data, Safely: Files, Approvals and Memory<\/a><\/li>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=dCIBza-WxUc\">Session 3: Scaling the Claw: Skills, Shell, CodeAct and Background Agents<\/a><\/li>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=rMhX0-oE4aY\">Session 4: Production Ready: Observability, Governance and Deployment<\/a><\/li>\n<\/ul>\n<p>Happy coding!<\/p>\n<p>Bruno<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I am building a complete C# agent live, from a single call around an IChatClient to a production-ready, observable, governed agent, using the Microsoft Agent Framework harness in a 4-part Microsoft Reactor series.<\/p>\n","protected":false},"author":120281,"featured_media":60833,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685,7781,756,7252],"tags":[8210,58,8158,8209],"class_list":["post-60832","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-ai","category-csharp","category-cloud","tag-agent-harness","tag-csharp","tag-microsoft-agent-framework","tag-microsoft-reactor"],"acf":[],"blog_post_summary":"<p>I am building a complete C# agent live, from a single call around an IChatClient to a production-ready, observable, governed agent, using the Microsoft Agent Framework harness in a 4-part Microsoft Reactor series.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/60832","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/120281"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=60832"}],"version-history":[{"count":1,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/60832\/revisions"}],"predecessor-version":[{"id":60834,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/60832\/revisions\/60834"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/60833"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=60832"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=60832"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=60832"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}