{"id":5512,"date":"2026-06-22T10:35:24","date_gmt":"2026-06-22T17:35:24","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/agent-framework\/?p=5512"},"modified":"2026-08-27T07:59:29","modified_gmt":"2026-08-27T14:59:29","slug":"meet-your-agent-harness-and-claw","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/agent-framework\/meet-your-agent-harness-and-claw\/","title":{"rendered":"Meet your agent harness and claw"},"content":{"rendered":"<p><em>Part 1 of <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>.<\/em><\/p>\n<p>In the <a href=\"https:\/\/devblogs.microsoft.com\/agent-framework\/build-your-own-claw-and-agent-harness-with-microsoft-agent-framework\/\">overview<\/a> we said a &#8220;claw&#8221; is really just an <em>agent harness<\/em>: a loop around a model, wired up with tools, planning, memory, and more. In this first post we stand up that loop and give our personal finance assistant its first three abilities:<\/p>\n<ol>\n<li>a <strong>custom tool<\/strong> (<code>get_stock_price<\/code>),<\/li>\n<li><strong>web search<\/strong> for market news, and<\/li>\n<li><strong>planning<\/strong> &#8211; so a vague request like <em>&#8220;Review my watchlist and recommend some stocks to add&#8221;<\/em> becomes a tracked, step-by-step<\/li>\n<\/ol>\n<p>plan.<\/p>\n<p>The remarkable part: we get almost all of this for free. Agent Framework&#8217;s harness bundles function invocation, history persistence, planning, and web search into a single call. We only supply <em>what makes our agent ours<\/em> &#8211; its instructions and its custom tool.<\/p>\n<p>Let&#8217;s build it in three steps: construct a chat client, turn it into a harness, then run it through an interactive console.<\/p>\n<h2 id=\"step-1-construct-a-chat-client\">Step 1 &#8211; Construct a chat client<\/h2>\n<p>Everything starts with a <em>chat client<\/em> &#8211; the thing that actually talks to a model. We point it at an endpoint, give it a credential for auth, and tell it which model deployment to use.<\/p>\n<p>In this example we are using <a href=\"https:\/\/ai.azure.com\/home\">Microsoft Foundry<\/a> with the <a href=\"https:\/\/ai.azure.com\/api-reference\/responses\/create-response\/\">Responses API<\/a>.<\/p>\n<p><strong>.NET<\/strong><\/p>\n<pre><code class=\"language-csharp\">\/\/ Read configuration from environment variables.\r\nvar endpoint = Environment.GetEnvironmentVariable(\"FOUNDRY_PROJECT_ENDPOINT\")\r\n    ?? throw new InvalidOperationException(\"FOUNDRY_PROJECT_ENDPOINT is not set.\");\r\nvar deploymentName = Environment.GetEnvironmentVariable(\"FOUNDRY_MODEL\") ?? \"gpt-5.4\";\r\n\r\n\/\/ Build an IChatClient backed by a Microsoft Foundry project.\r\nIChatClient chatClient =\r\n    new AIProjectClient(new Uri(endpoint), new DefaultAzureCredential())\r\n        .GetProjectOpenAIClient()\r\n        .GetResponsesClient()\r\n        .AsIChatClient(deploymentName);<\/code><\/pre>\n<ul>\n<li><strong><code>FOUNDRY_PROJECT_ENDPOINT<\/code><\/strong> &#8211; your Microsoft Foundry project endpoint.<\/li>\n<li><strong><code>FOUNDRY_MODEL<\/code><\/strong> &#8211; the model deployment to call (e.g. <code>gpt-5.4<\/code>).<\/li>\n<li><strong><code>DefaultAzureCredential<\/code><\/strong> &#8211; handles auth from your environment (e.g. run <code>az login<\/code> locally to use its session). In<\/li>\n<\/ul>\n<p>production, prefer a specific credential such as <code>ManagedIdentityCredential<\/code>.<\/p>\n<p><strong>Python<\/strong><\/p>\n<pre><code class=\"language-python\"># FoundryChatClient reads FOUNDRY_PROJECT_ENDPOINT and FOUNDRY_MODEL from the environment.\r\nclient = FoundryChatClient(credential=AzureCliCredential())<\/code><\/pre>\n<ul>\n<li><strong><code>FOUNDRY_PROJECT_ENDPOINT<\/code><\/strong> &#8211; your Microsoft Foundry project endpoint.<\/li>\n<li><strong><code>FOUNDRY_MODEL<\/code><\/strong> &#8211; the model deployment to call.<\/li>\n<li><strong><code>AzureCliCredential<\/code><\/strong> &#8211; uses your <code>az login<\/code> session; swap in any other credential you prefer.<\/li>\n<\/ul>\n<blockquote><p><strong>Many clients, one harness.<\/strong> We used a Microsoft Foundry client here, but the harness works with <em>any<\/em> chat client &#8211; Azure OpenAI, OpenAI, Anthropic, Google Gemini, Ollama, and more.<\/p>\n<p>See the provider samples for how to construct each one:<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/microsoft\/agent-framework\/tree\/main\/dotnet\/samples\/02-agents\/AgentProviders\">.NET <code>AgentProviders<\/code><\/a> \u00b7<\/li>\n<li><a href=\"https:\/\/github.com\/microsoft\/agent-framework\/tree\/main\/python\/samples\/02-agents\/providers\">Python <code>providers<\/code><\/a>.<\/li>\n<\/ul>\n<p>Also see the <a href=\"https:\/\/learn.microsoft.com\/agent-framework\/agents\/providers\">documentation for all providers<\/a>.<\/p><\/blockquote>\n<h2 id=\"step-2-turn-the-chat-client-into-a-harness\">Step 2 &#8211; Turn the chat client into a harness<\/h2>\n<p>Now we wrap that client in the harness. In .NET you call <code>AsHarnessAgent<\/code>; in Python you call <code>create_harness_agent<\/code>. For now, we supply just two things: <strong>instructions<\/strong> (what the agent is for) and a <strong>custom tool<\/strong>.<\/p>\n<h3 id=\"instructions\">Instructions<\/h3>\n<p>The harness handles <em>how<\/em> to operate; our instructions describe <em>what<\/em> the agent is for.<\/p>\n<p><strong>.NET<\/strong><\/p>\n<pre><code class=\"language-csharp\">var instructions =\r\n    \"\"\"\r\n    ## Personal Finance Assistant Instructions\r\n\r\n    You are a personal finance and investing assistant. When asked about a stock, look up its\r\n    current price with the get_stock_price tool, and use web search for recent news, earnings,\r\n    or analyst commentary.\r\n\r\n    ### Working style\r\n    - Always verify numbers with a tool rather than relying on memory. Stock prices change.\r\n    - Cite web sources inline when you use them.\r\n    - Keep the user's watchlist in a memory file called `watchlist.md`: read it when reviewing\r\n      the watchlist, and update it whenever the user adds or removes a ticker.\r\n    \"\"\";<\/code><\/pre>\n<p><strong>Python<\/strong><\/p>\n<pre><code class=\"language-python\">FINANCE_INSTRUCTIONS = \"\"\"\\\r\n## Personal Finance Assistant Instructions\r\n\r\nYou are a personal finance and investing assistant. When asked about a stock, look up its current\r\nprice with the get_stock_price tool, and use web search for recent news, earnings, or analyst\r\ncommentary.\r\n\r\n### Working style\r\n- Always verify numbers with a tool rather than relying on memory. Stock prices change.\r\n- Cite web sources inline when you use them.\r\n- Keep the user's watchlist in a memory file called `watchlist.md`: read it when reviewing the\r\n  watchlist, and update it whenever the user adds or removes a ticker.\r\n\"\"\"<\/code><\/pre>\n<h3 id=\"a-custom-tool\">A custom tool<\/h3>\n<p>A tool is just a function the model can call. We expose a <code>get_stock_price<\/code> function; the framework generates the JSON schema from its signature and parameter descriptions.<\/p>\n<p><strong>.NET<\/strong><\/p>\n<pre><code class=\"language-csharp\">[Description(\"Gets the latest (delayed, illustrative) stock price for a ticker symbol.\")]\r\npublic static StockQuote GetStockPrice(\r\n    [Description(\"The stock ticker symbol, e.g. MSFT or AAPL.\")] string symbol)\r\n{\r\n    \/\/ ... look up the price ...\r\n    return new StockQuote(symbol.ToUpperInvariant(), price, \"USD\", DateTimeOffset.UtcNow);\r\n}\r\n\r\npublic static AIFunction CreateGetStockPriceTool() =&gt; AIFunctionFactory.Create(GetStockPrice, \"get_stock_price\");<\/code><\/pre>\n<p><strong>Python<\/strong><\/p>\n<pre><code class=\"language-python\">def get_stock_price(\r\n    symbol: Annotated[str, \"The stock ticker symbol, e.g. MSFT or AAPL.\"],\r\n) -&gt; dict[str, object]:\r\n    \"\"\"Get the latest (delayed, illustrative) stock price for a ticker symbol.\"\"\"\r\n    # ... look up the price ...\r\n    return {\"symbol\": ticker, \"price\": round(price, 2), \"currency\": \"USD\", \"as_of\": ...}<\/code><\/pre>\n<blockquote><p>The samples return mock prices from an in-memory dictionary so they run with no external dependencies. In a real assistant you&#8217;d call a market-data API here.<\/p><\/blockquote>\n<h3 id=\"wire-it-together\">Wire it together<\/h3>\n<p>With the instructions and tool in hand, one call builds the agent.<\/p>\n<p><strong>.NET<\/strong><\/p>\n<pre><code class=\"language-csharp\">AIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions\r\n{\r\n    ChatOptions = new ChatOptions\r\n    {\r\n        Instructions = instructions,\r\n        Tools = [StockTools.CreateGetStockPriceTool()],\r\n    },\r\n});<\/code><\/pre>\n<p><strong>Python<\/strong><\/p>\n<pre><code class=\"language-python\">agent = create_harness_agent(\r\n    client=client,\r\n    agent_instructions=FINANCE_INSTRUCTIONS,\r\n    tools=get_stock_price,\r\n)<\/code><\/pre>\n<p>That single call gives us function invocation, per-service-call history persistence, a <code>TodoProvider<\/code> and <code>AgentModeProvider<\/code> for planning, and web search &#8211; all on by default and each configurable. We only supplied <em>what makes our agent ours<\/em>: its instructions and a custom tool.<\/p>\n<p>This is why web search and planning &#8220;just work&#8221;. We never wrote web-search code &#8211; the harness adds a hosted web-search tool by default (turn it off with <code>DisableWebSearch<\/code> \/ <code>disable_web_search<\/code>), so <em>&#8220;Any recent news on NVDA?&#8221;<\/em> works out of the box. And because the harness includes a <code>TodoProvider<\/code> and an <code>AgentModeProvider<\/code>, asking it to <em>&#8220;Review my watchlist and recommend some stocks to add&#8221;<\/em> while in <strong>plan<\/strong> mode makes it produce a plan, write a todo list, then move into <strong>execute<\/strong> mode.<\/p>\n<blockquote><p>Note that hosted web search needs to be supported by your service to work out of the box. We are using Microsoft Foundry with Responses, which fully supports web search.<\/p><\/blockquote>\n<h2 id=\"step-3-run-it-through-the-harness-console\">Step 3 &#8211; Run it through the harness console<\/h2>\n<p>Finally, we hand the agent to a shared harness console &#8211; a streaming terminal UI with <code>\/todos<\/code>, <code>\/mode<\/code>, and <code>\/exit<\/code> commands, and output colored by mode (cyan for planning, green for execution).<\/p>\n<p>The console is is provided as a sample. Both languages ship the full source, designed to be copied and adapted as a starting point for your own UX (web app, chat surface, IDE extension, \u2026):<\/p>\n<ul>\n<li>.NET: <a href=\"https:\/\/github.com\/microsoft\/agent-framework\/tree\/main\/dotnet\/samples\/02-agents\/Harness\/Harness_Shared_Console\"><code>Harness_Shared_Console<\/code><\/a><\/li>\n<li>Python: <a href=\"https:\/\/github.com\/microsoft\/agent-framework\/tree\/main\/python\/samples\/02-agents\/harness\/console\"><code>console<\/code><\/a><\/li>\n<\/ul>\n<p><strong>.NET<\/strong><\/p>\n<pre><code class=\"language-csharp\">await HarnessConsole.RunAgentAsync(\r\n    agent,\r\n    userPrompt: \"Ask about a stock or say 'review my watchlist' to get started.\",\r\n    new HarnessConsoleOptions { \/* observers + command handlers *\/ });<\/code><\/pre>\n<p><strong>Python<\/strong><\/p>\n<pre><code class=\"language-python\">await run_agent_async(\r\n    agent,\r\n    session=agent.create_session(),\r\n    observers=build_observers_with_planning(agent),\r\n    initial_mode=\"plan\",\r\n    title=\"\ud83d\udcb9 Finance Assistant\",\r\n)<\/code><\/pre>\n<p>Run the sample:<\/p>\n<p><strong>.NET<\/strong><\/p>\n<pre><code class=\"language-bash\">cd dotnet\r\ndotnet run --project samples\/02-agents\/Harness\/BuildYourOwnClaw\/Claw_Step01_MeetYourClaw<\/code><\/pre>\n<p><strong>Python<\/strong><\/p>\n<pre><code class=\"language-bash\">uv run python\/samples\/02-agents\/harness\/build_your_own_claw\/claw_step01_meet_your_claw.py<\/code><\/pre>\n<p>Then try these in order:<\/p>\n<ol>\n<li><code>\/mode execute<\/code> &#8211; switch out of the default plan mode; quick lookups don&#8217;t need a plan.<\/li>\n<li><code>What's the price of MSFT?<\/code> &#8211; watch the agent call your <code>get_stock_price<\/code> tool.<\/li>\n<li><code>Any recent news on NVDA?<\/code> &#8211; watch it use web search.<\/li>\n<li><code>Add MSFT, NVDA and SPY to my watch list<\/code><\/li>\n<li><code>\/mode plan<\/code> &#8211; switch back to plan mode for a bigger, multi-step task.<\/li>\n<li><code>Review my watchlist and recommend some stocks to add<\/code> &#8211; watch it plan, ask clarifying questions, then execute. Type <code>\/todos<\/code> to see the list of todos and <code>\/mode<\/code> to inspect the current mode.<\/li>\n<\/ol>\n<p><figure id=\"attachment_5528\" aria-labelledby=\"figcaption_attachment_5528\" class=\"wp-caption aligncenter\" ><a href=\"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2026\/06\/harness_console.webp\"><img decoding=\"async\" class=\"wp-image-5528 size-full\" src=\"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2026\/06\/harness_console.webp\" alt=\"Sample Text UI application screenshot\" width=\"1587\" height=\"1144\" srcset=\"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2026\/06\/harness_console.webp 1587w, https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2026\/06\/harness_console-300x216.webp 300w, https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2026\/06\/harness_console-1024x738.webp 1024w, https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2026\/06\/harness_console-768x554.webp 768w, https:\/\/devblogs.microsoft.com\/agent-framework\/wp-content\/uploads\/sites\/78\/2026\/06\/harness_console-1536x1107.webp 1536w\" sizes=\"(max-width: 1587px) 100vw, 1587px\" \/><\/a><figcaption id=\"figcaption_attachment_5528\" class=\"wp-caption-text\">Sample Text UI application<\/figcaption><\/figure><\/p>\n<p>The default location for memories is the <code>agent-file-memory<\/code> directory, but can be customized via options. Under this directory, you have a subdirectory for each session. Thanks to the agent instructions, the watchlist is saved to <code>watchlist.md<\/code> in the current session folder.<\/p>\n<h3 id=\"save-and-resume-a-session\">Save and resume a session<\/h3>\n<p>The console can also persist the whole session to disk. Under the hood <code>\/session-export<\/code> simply serializes the <code>AgentSession<\/code> object &#8211; conversation history <em>and<\/em> context-provider state such as the directory containing your file memory &#8211; to JSON via the agent&#8217;s <code>SerializeSessionAsync<\/code>, then writes it to a file. <code>\/session-import<\/code> reads that file back and deserializes it into a live session. Continue in order:<\/p>\n<ol>\n<li><code>\/session-export my-session.json<\/code> &#8211; saves the current session (including the watchlist memory) to a file on disk.<\/li>\n<li><code>\/exit<\/code>, then relaunch the app &#8211; you&#8217;re back to a fresh, empty session.<\/li>\n<li><code>\/session-import my-session.json<\/code> &#8211; restores the saved session from disk.<\/li>\n<li><code>\/mode execute<\/code> &#8211; switch out of the default plan mode; quick lookups don&#8217;t need a plan.<\/li>\n<li><code>What's on my watchlist?<\/code> &#8211; the agent answers from the restored memory; nothing was re-typed.<\/li>\n<\/ol>\n<h2 id=\"how-plan-mode-works\">How plan mode works<\/h2>\n<p>Why does plan mode <em>ask questions<\/em> and <em>request approval<\/em>, while execute mode just gets on with it? The trick is <strong>structured output<\/strong>.<\/p>\n<p>The harness ships with two modes out of the box &#8211; <code>plan<\/code> (the default) and <code>execute<\/code> &#8211; and the console&#8217;s planning observer treats them differently. In execute mode the model replies with ordinary prose and gets to work. In <strong>plan<\/strong> mode, the console asks the model for a structured response instead of free-form text, by setting a response format with a JSON schema:<\/p>\n<p><strong>.NET<\/strong><\/p>\n<pre><code class=\"language-csharp\">\/\/ In the console's planning observer, only while in plan mode:\r\noptions.ResponseFormat = ChatResponseFormat.ForJsonSchema&lt;PlanningResponse&gt;();<\/code><\/pre>\n<p><strong>Python<\/strong><\/p>\n<pre><code class=\"language-python\"># In the console's planning observer, only while in plan mode:\r\noptions[\"response_format\"] = PlanningResponse<\/code><\/pre>\n<p>That schema forces the model into one of exactly two shapes:<\/p>\n<p><strong>.NET<\/strong><\/p>\n<pre><code class=\"language-csharp\">class PlanningResponse\r\n{\r\n    PlanningResponseType Type;        \/\/ Clarification or Approval\r\n    List&lt;PlanningQuestion&gt; Questions; \/\/ one or more items\r\n}\r\n\r\nclass PlanningQuestion\r\n{\r\n    string Message;          \/\/ the question, or the plan summary\r\n    List&lt;string&gt;? Choices;   \/\/ suggested options (clarification only)\r\n}<\/code><\/pre>\n<p><strong>Python<\/strong><\/p>\n<pre><code class=\"language-python\">class PlanningResponse(BaseModel):\r\n    type: PlanningResponseType         # \"clarification\" or \"approval\"\r\n    questions: list[PlanningQuestion]  # one or more items\r\n\r\nclass PlanningQuestion(BaseModel):\r\n    message: str                       # the question, or the plan summary\r\n    choices: list[str] | None = None   # suggested options (clarification only)<\/code><\/pre>\n<ul>\n<li><strong>Clarification<\/strong> &#8211; the model isn&#8217;t sure what you want yet, so it returns one or more questions. Each can carry a list of <code>Choices<\/code>, which the console renders as pickable options (you can always type a free-form answer too). <em>&#8220;Which MSFT &#8211; Microsoft or another ticker?&#8221;<\/em><\/li>\n<li><strong>Approval<\/strong> &#8211; the model has a plan and returns a single item whose <code>Message<\/code> is the plan summary. The console surfaces it as an <em>&#8220;Approve and switch to execute mode&#8221;<\/em> prompt, so nothing executes until you say so.<\/li>\n<\/ul>\n<p>This is what makes planning feel deliberate: the agent gathers what it needs, shows you the plan, and only then flips to execute mode and works through the todo list. The <code>PlanningResponse<\/code> type lives in the console <strong>sample<\/strong> in both languages, so you can copy and tailor the schema &#8211; different question types, richer approvals &#8211; to fit your own UX.<\/p>\n<h2 id=\"turning-features-off\">Turning features off<\/h2>\n<p>Everything the harness gives us &#8211; todos, agent modes, web search, file memory, file access, tool approval &#8211; is <strong>on by default and individually toggleable<\/strong>. If a feature doesn&#8217;t fit your scenario, switch it off with a single option. For example, to drop the todo list and web search:<\/p>\n<p><strong>.NET<\/strong><\/p>\n<pre><code class=\"language-csharp\">AIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions\r\n{\r\n    DisableTodoProvider = true,\r\n    DisableWebSearch = true,\r\n    ChatOptions = new ChatOptions { Instructions = instructions, Tools = [\/* ... *\/] },\r\n});<\/code><\/pre>\n<p><strong>Python<\/strong><\/p>\n<pre><code class=\"language-python\">agent = create_harness_agent(\r\n    client=client,\r\n    agent_instructions=FINANCE_INSTRUCTIONS,\r\n    tools=get_stock_price,\r\n    disable_todo=True,\r\n    disable_web_search=True,\r\n)<\/code><\/pre>\n<p>The common .NET switches are <code>DisableTodoProvider<\/code>, <code>DisableAgentModeProvider<\/code>, <code>DisableWebSearch<\/code>, <code>DisableFileMemory<\/code>, <code>DisableFileAccess<\/code>, and <code>DisableToolApproval<\/code>; Python exposes the equivalent flags it supports (<code>disable_todo<\/code>, <code>disable_mode<\/code>, <code>disable_memory<\/code>, <code>disable_web_search<\/code>). Our Part 1 sample leaves everything on &#8211; we just don&#8217;t lean on file access or approvals yet; those get their own spotlight in Part 2. Start with everything on, then trim to taste.<\/p>\n<h2 id=\"the-runnable-samples\">The runnable samples<\/h2>\n<ul>\n<li><strong>.NET:<\/strong> <a href=\"https:\/\/github.com\/microsoft\/agent-framework\/tree\/main\/dotnet\/samples\/02-agents\/Harness\/BuildYourOwnClaw\/Claw_Step01_MeetYourClaw\"><code>dotnet\/samples\/02-agents\/Harness\/BuildYourOwnClaw\/Claw_Step01_MeetYourClaw<\/code><\/a><\/li>\n<li><strong>Python:<\/strong> <a href=\"https:\/\/github.com\/microsoft\/agent-framework\/tree\/main\/python\/samples\/02-agents\/harness\/build_your_own_claw\"><code>python\/samples\/02-agents\/harness\/build_your_own_claw<\/code><\/a><\/li>\n<\/ul>\n<h2 id=\"use-these-building-blocks-in-your-own-agent\">Use these building blocks in your own agent<\/h2>\n<p>The harness wires all of this up for you, but none of it is locked inside the harness. Web search is just a <strong>tool<\/strong>, and modes and todos are each a plain <strong>context provider<\/strong> \u2014 you can pick up exactly the pieces you want and add them to <em>any<\/em> agent, even without adopting the full harness. Here&#8217;s where to find them:<\/p>\n<table>\n<thead>\n<tr>\n<th>Feature<\/th>\n<th>.NET (type \u2014 namespace)<\/th>\n<th>Python (import)<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>Web search<\/strong><\/td>\n<td><code>HostedWebSearchTool<\/code> &#8211;\u00a0<code>Microsoft.Extensions.AI<\/code> (add to <code>ChatOptions.Tools<\/code>)<\/td>\n<td><code>chat_client.get_web_search_tool()<\/code><\/td>\n<\/tr>\n<tr>\n<td><strong>Planning modes<\/strong><\/td>\n<td><code>AgentModeProvider<\/code> &#8211;\u00a0<code>Microsoft.Agents.AI<\/code><\/td>\n<td><code>from agent_framework import AgentModeProvider<\/code><\/td>\n<\/tr>\n<tr>\n<td><strong>Todo lists<\/strong><\/td>\n<td><code>TodoProvider<\/code> &#8211;\u00a0<code>Microsoft.Agents.AI<\/code><\/td>\n<td><code>from agent_framework import TodoProvider<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>In <strong>.NET<\/strong>, the mode and todo providers ship in the <code>Microsoft.Agents.AI<\/code> package, while the hosted web-search tool comes from <code>Microsoft.Extensions.AI<\/code>. In <strong>Python<\/strong>, all three live in the <code>agent-framework<\/code> package. The providers plug in through an agent&#8217;s context providers and web search through its tools \u2014 the same wiring the harness does on your behalf.<\/p>\n<h2 id=\"whats-next\">What&#8217;s next<\/h2>\n<p>Our claw can look things up, search the web, and plan. But it can&#8217;t yet touch <em>your<\/em> data, and there&#8217;s nothing stopping it from taking a sensitive action. In Part 2 &#8211; Working with your data, safely we will give it <strong>file access<\/strong>, gate risky actions behind <strong>approvals<\/strong>, and add durable <strong>memory<\/strong> so it remembers your preferences.<\/p>\n<h2 id=\"the-series\">\ud83d\udcda The series<\/h2>\n<p>Part of <strong>Build your own claw with Microsoft Agent Framework<\/strong>:<\/p>\n<ul>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/agent-framework\/build-your-own-claw-and-agent-harness-with-microsoft-agent-framework\">Overview: Build your own claw and agent harness with Microsoft Agent Framework<\/a><\/li>\n<li><strong>Part 1 &#8211; Meet your agent harness and claw<\/strong> <em>(you are here)<\/em><\/li>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/agent-framework\/agent-harness-working-with-your-data-safely\/\">Part 2 &#8211; 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 &#8211; Scaling its capabilities<\/a><\/li>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/agent-framework\/agent-harness-making-your-claw-production-ready\/\">Part 4 &#8211; Production-ready<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Part 1 of Build your own claw and agent harness with Microsoft Agent Framework. In the overview we said a &#8220;claw&#8221; is really just an agent harness: a loop around a model, wired up with tools, planning, memory, and more. In this first post we stand up that loop and give our personal finance assistant [&hellip;]<\/p>\n","protected":false},"author":162052,"featured_media":5537,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[78,143,34],"tags":[],"class_list":["post-5512","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-net","category-agent-framework","category-python-2"],"acf":[],"blog_post_summary":"<p>Part 1 of Build your own claw and agent harness with Microsoft Agent Framework. In the overview we said a &#8220;claw&#8221; is really just an agent harness: a loop around a model, wired up with tools, planning, memory, and more. In this first post we stand up that loop and give our personal finance assistant [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/posts\/5512","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/users\/162052"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/comments?post=5512"}],"version-history":[{"count":1,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/posts\/5512\/revisions"}],"predecessor-version":[{"id":5841,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/posts\/5512\/revisions\/5841"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/media\/5537"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/media?parent=5512"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/categories?post=5512"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/tags?post=5512"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}