Build Your Own AI Agent Harness in C#, the MafClaw Live Series

Wait 5 sec.

A few weeks ago I wrote about going from dotnet run to a Foundry Hosted Agent in three lines of C#. The feedback was great. Developers liked the deployment story, the managed infrastructure, and especially the part where we did not spend the afternoon writing a Dockerfile, a session store, a telemetry pipeline, and a small distributed system just to expose one agent .But that post starts near the end of the journey. It assumes you already have an agent worth deploying.So the next question is:“What should I put inside the agent before I deploy it?”Tools. Planning. Safe file access. Human approval. Memory. Skills. Shell commands. Code execution. Background agents. Observability. Governance. Evaluations.That list gets big very quickly.The good news is that you do not need to build the runtime for all of it from scratch. Microsoft Agent Framework includes an agent harness, and I am building a complete C# agent with it live, one capability at a time, in a four-part series called From Model to Agent: The Agent Framework Harness, Live in C#.The series streams live simultaneously on the .NET YouTube channel and Microsoft Reactor, 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.Register for the live Agent Framework seriesWhat we build across four sessionsWe start with this:AIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions{ ChatOptions = new ChatOptions { Instructions = instructions, Tools = tools }});Then we grow the same agent through four stages:Give it tools, web search, and a plan.Let it work with files, approvals, and durable memory.Add skills, shell, CodeAct, and background agents.Add observability, governance, evaluations, and a hosted deployment.That is the complete journey: from one call around an IChatClient to a capable agent that we can inspect, evaluate, govern, and run in Microsoft Foundry.First: what is an agent harness?A language model can generate text. An agent needs more.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.That surrounding runtime is the harness.Where the term comes fromThe Microsoft Agent Framework team introduced the concept in the excellent Build your own claw and agent harness with Microsoft Agent Framework series. Their explanation is simple: a “claw” 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.In .NET, the key line is this one:AIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions{ ChatOptions = new ChatOptions { Instructions = "You are a personal finance education assistant.", Tools = [StockTools.GetStockPrice] }});That call gives the agent a complete pipeline with capabilities such as:automatic function invocationhistory persistence after model callsplanning with todo and agent-mode providerscontext compactionfile memoryweb search when the model service supports ittool approvalsskillsOpenTelemetry instrumentationEach capability is configurable. You can replace it, disable it, or add your own provider.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.The agent we are buildingAcross the four sessions, we build one personal finance education assistant.Why finance? Because it gives us realistic boundaries to discuss:Looking up a stock price is a read-only tool call.Reading a portfolio means accessing user data.Writing a report changes a file.Placing a simulated trade is a side effect and needs approval.Remembering a risk profile needs durable, user-scoped memory.Calculating portfolio value is better done with code than model arithmetic.Running shell commands requires confinement and policy.A production finance agent needs traces, governance, and evaluations.This is a learning scenarioAll 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.The complete code is in the MafClaw sample repository.Session 1: turn a model into an agentIn Meet Your Claw: A Harness in Three Lines of C#, we started with the smallest useful agent.First, create an IChatClient backed by a model in Microsoft Foundry:IChatClient chatClient = new AIProjectClient(new Uri(endpoint), new AzureCliCredential()) .GetProjectOpenAIClient() .GetResponsesClient() .AsIChatClient(model);Then wrap it with the harness and give it one custom tool:AIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions{ ChatOptions = new ChatOptions { Instructions = """ You are a personal finance education assistant. Use get_stock_price for stock prices. Use hosted web search for recent market news and cite sources. Use the todo list to track multi-step work. """, Tools = [StockTools.GetStockPrice] }});The custom tool is ordinary C#. Agent Framework generates its tool schema from the function signature and descriptions:[Description("Gets the illustrative stock price for a ticker symbol.")]public static string GetStockPriceBySymbol( [Description("Stock ticker symbol, e.g. MSFT")] string symbol){ var upper = symbol.Trim().ToUpperInvariant(); return upper switch { "MSFT" => "MSFT: 512.34 USD (mock)", "NVDA" => "NVDA: 184.72 USD (mock)", "AMZN" => "AMZN: 241.18 USD (mock)", _ => $"{upper}: not available" };}public static AIFunction GetStockPrice { get; } = AIFunctionFactory.Create( GetStockPriceBySymbol, "get_stock_price");Now the difference between a chat application and an agent becomes visible.Ask:What is the price of MSFT?The model chooses the tool, the harness invokes it, the result returns to the model, and the agent produces the final answer.Ask something larger:Review my watchlist and suggest what I should research next.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.This first session is available now:Session 2: work with user data safelyAn agent becomes much more useful when it can work with your data.It also becomes much more dangerous.In Working With Your Data, Safely: Files, Approvals and Memory, we gave the finance assistant access to a portfolio CSV, but only inside an approved working directory:var workingDirectory = Path.Combine(AppContext.BaseDirectory, "working");AIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions{ FileAccessStore = new FileSystemAgentFileStore(workingDirectory), ChatOptions = new ChatOptions { Instructions = """ The user's portfolio is in portfolio.csv. Read it before answering portfolio questions. Write generated reports under the approved working folder. """, }});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.This means the happy path works:What is in my portfolio?And the unsafe path is blocked:Read C:\some-other-folder\outside-portfolio.csvThe second boundary is human approval.A simulated trade is wrapped in ApprovalRequiredAIFunction:public static AIFunction RequestSimulatedTrade { get; } = new ApprovalRequiredAIFunction( AIFunctionFactory.Create( RequestSimulatedTradeOrder, "request_simulated_trade"));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.We also configured a low-friction safe path:ToolApprovalAgentOptions = new ToolApprovalAgentOptions{ AutoApprovalRules = [ FileAccessProvider.ReadOnlyToolsAutoApprovalRule ],},Read-only file operations can proceed automatically. Writes, destructive operations, and the simulated trade still cross an approval boundary.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.A question from the audience became a new sampleDuring the live Q&A, someone asked:“What if the user does not answer the approval request?”Great question.Silence is not consentAn 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 y, immediate denial for n, 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.The policy starts with a small configuration:const int maxApprovalAttempts = 5;var approvalTimeout = TimeSpan.FromSeconds(5);var approvalPolicy = new TimedApprovalPolicy( maxApprovalAttempts, approvalTimeout);You can find the complete implementation in Sample 22: approval retries and timeouts.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 “I saved that” is not proof that anything was persisted. The application needs a real storage result, a scope, and a way to surface failures.Session 2 is also available now: Watch Session 2: Files, Approvals and MemorySession 3: skills, shell, CodeAct, and background agentsThe first two sessions make the agent useful and safe. The third makes it more capable.In Scaling the Claw: Skills, Shell, CodeAct and Background Agents, we cover four different ways to expand an agent without turning its system prompt into a 400-page instruction manual:Skills 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.Shell 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.CodeAct 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.Background agents 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.Confinement, not just approvalShell 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.We build all four live, with the finance assistant as the running example.Watch or register for Session 3Session 4: make the agent production-readyAt this point the claw can plan, use tools, work with files, request approvals, remember facts, load skills, execute code, and delegate research.That is the moment when somebody asks:“OK, the agent is done… now, how do I deploy this thing?”Yes, we are back to the question from my previous post .In Production Ready: Observability, Governance and Deployment, we close the loop with:Observability with OpenTelemetry traces, tool calls, model calls, and token usage, so you can see what the agent actually did.Governance with Microsoft Purview policy integration, so organizational policy applies to agent behavior, not just human behavior.Evaluations for repeatable quality checks, so “it felt right in the demo” becomes a measurable signal.Deployment 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.A production decision, not a framework limitationA 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.The exact deployment approach follows the container-hosting setup from the Agent Framework sample. My earlier three-lines-of-C# post remains a useful introduction to the hosting model, but this claw has extra capabilities and therefore extra production decisions.We build the observability, governance, evaluation, and deployment story live in this final session.Watch or register for Session 4Why start with the harness?You can build every one of these pieces yourself.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.Sometimes you need that level of control.But most teams want to spend their time on the domain behavior that makes the agent valuable:What tools should it have?What data can it access?Which actions require approval?What should it remember?Which skills should it load?Which tasks can run concurrently?What policies apply?How will we evaluate whether it works?The harness gives those decisions a composable home.You still own the boundaries. You still choose the tools. You still decide what gets approved, remembered, executed, traced, and deployed.You just do not have to rebuild the agent runtime before answering any of those questions.Join the seriesThe Microsoft Agent Framework blog has the complete written, .NET-and-Python version of this journey:Build your own claw and agent harness with Microsoft Agent FrameworkPart 1: Meet your agent harness and clawPart 2: Working with your data, safelyPart 3: Scaling the clawPart 4: Making your claw production-readyAnd in the series, we build the .NET version live, one capability at a time, streaming live simultaneously on the .NET YouTube channel and Microsoft Reactor, four consecutive Thursdays in September, then staying available on demand on both platforms:Meet Your Claw: A Harness in Three Lines of C#Working With Your Data, Safely: Files, Approvals and MemoryScaling the Claw: Skills, Shell, CodeAct and Background AgentsProduction Ready: Observability, Governance and DeploymentRegister for the live Agent Framework seriesGet the complete C# samplesBring your questions. The approval timeout sample exists because someone did exactly that.Learn moreSeries introduction: From Model to AgentMicrosoft Reactor series page.NET YouTube channelSession 1: Meet Your Claw: A Harness in Three Lines of C#Session 2: Working With Your Data, Safely: Files, Approvals and MemorySession 3: Scaling the Claw: Skills, Shell, CodeAct and Background AgentsSession 4: Production Ready: Observability, Governance and DeploymentHappy coding!BrunoThe post Build Your Own AI Agent Harness in C#, the MafClaw Live Series appeared first on .NET Blog.