<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ilia Sokolov</title>
    <description>The latest articles on DEV Community by Ilia Sokolov (@ilia-sokolov).</description>
    <link>https://dev.to/ilia-sokolov</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3946653%2F670f803c-9cbe-45f6-87da-a9bf8931589b.jpeg</url>
      <title>DEV Community: Ilia Sokolov</title>
      <link>https://dev.to/ilia-sokolov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ilia-sokolov"/>
    <language>en</language>
    <item>
      <title>Edit SharePoint Word Documents from Any AI Agent over MCP with OfficeAgent.NET 0.2</title>
      <dc:creator>Ilia Sokolov</dc:creator>
      <pubDate>Mon, 29 Jun 2026 11:17:11 +0000</pubDate>
      <link>https://dev.to/ilia-sokolov/edit-sharepoint-word-documents-from-any-ai-agent-over-mcp-with-officeagentnet-02-4ejm</link>
      <guid>https://dev.to/ilia-sokolov/edit-sharepoint-word-documents-from-any-ai-agent-over-mcp-with-officeagentnet-02-4ejm</guid>
      <description>&lt;p&gt;A few weeks ago I released &lt;a href="https://dev.to/ilia-sokolov/word-document-editing-for-ai-agents-introducing-officeagentnet-01-2cc"&gt;OfficeAgent.NET 0.1&lt;/a&gt;, an open-source .NET library that lets AI agents create and edit real Word documents. Instead of manipulating the Open XML themselves, they describe their intent as a typed, validated change plan, and the library turns it into the Open XML that carries it out: tracked changes, tables, comments, and content controls included. Version 0.1 shipped with an integration for Microsoft Agent Framework (MAF), so you could give those document tools to a custom .NET agent.&lt;/p&gt;

&lt;p&gt;Today I'm introducing version 0.2. It exposes the same workflow over the &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt;, so &lt;em&gt;any&lt;/em&gt; MCP-capable agent can read and edit real Word documents. This version also adds a &lt;strong&gt;SharePoint document provider&lt;/strong&gt;, so agents can work on documents where they are actually stored: directly in SharePoint, one of the most widely used cloud document stores in the enterprise, rather than on a local disk.&lt;/p&gt;

&lt;h3&gt;
  
  
  Any agent, over MCP
&lt;/h3&gt;

&lt;p&gt;MCP is an open standard for how an AI agent discovers and calls tools. OfficeAgent.NET 0.2 ships &lt;code&gt;OfficeAgent.Mcp&lt;/code&gt;, a server (built on the official C# MCP SDK) that projects the document workflow as MCP tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;inspect_document&lt;/code&gt; - a structured map of the document: outline, paragraphs with stable ids, styles, content controls, tables, images, and revisions.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;find_in_document&lt;/code&gt; - text search that returns content-verified anchors to target.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;preview_plan&lt;/code&gt; - a dry run of a change plan; nothing is written, the agent gets a before/after report and any validation errors.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;apply_plan&lt;/code&gt; - the all-or-nothing commit, saved through the configured storage.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;register_document&lt;/code&gt; / &lt;code&gt;remove_document&lt;/code&gt; / &lt;code&gt;list_connections&lt;/code&gt; - point the agent at a document to work on, release it afterwards, and discover the connections the host configured.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Copilot Studio, Microsoft 365 Copilot, Claude and Claude Code, OpenAI's Codex, and VS Code support MCP and can use this server.&lt;/p&gt;

&lt;p&gt;The server runs in two hosting modes: stdio, used by locally running agents such as Claude Code and Codex, and an ASP.NET Core app over streamable HTTP, required by hosted agents such as Copilot Studio and Microsoft 365 Copilot.&lt;/p&gt;

&lt;h3&gt;
  
  
  Working on documents in SharePoint
&lt;/h3&gt;

&lt;p&gt;OfficeAgent works through document providers. An agent registers a document with a provider and gets back an opaque id, which it then uses to address that document in every operation. 0.2 adds a SharePoint provider alongside the filesystem provider from the initial release.&lt;/p&gt;

&lt;p&gt;The SharePoint provider reads and writes documents directly in SharePoint - the system most organizations in the Microsoft ecosystem use to store their documents. A document is registered by its URL or its Graph &lt;code&gt;driveId/itemId&lt;/code&gt; pair; from there the agent runs the same inspect → preview → apply loop it would run against a local folder.&lt;/p&gt;

&lt;p&gt;Two things make it safe to point an agent at a real document:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You review every change&lt;/strong&gt;. The agent's edits arrive as Word tracked changes - accept or reject them like a colleague's. And each change is verified against the live document, so it edits the exact place you meant or fails safely, instead of silently rewriting the wrong clause.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It's scoped to you&lt;/strong&gt;. Acting on behalf of the signed-in user (OAuth 2.0 On-Behalf-Of), the agent can only open and edit what you're already allowed to in SharePoint - not a shared account with broader reach.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try it yourself
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# the MCP server&lt;/span&gt;
dotnet tool &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--global&lt;/span&gt; OfficeAgent.Mcp &lt;span class="nt"&gt;--prerelease&lt;/span&gt;

&lt;span class="c"&gt;# the SharePoint provider&lt;/span&gt;
dotnet add package OfficeAgent.SharePoint &lt;span class="nt"&gt;--prerelease&lt;/span&gt;

&lt;span class="c"&gt;# the core library&lt;/span&gt;
dotnet add package OfficeAgent.Core &lt;span class="nt"&gt;--prerelease&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Source, samples, and the full hosting and client-setup guides are on GitHub: &lt;a href="https://github.com/ilia-sokolov/OfficeAgent.NET" rel="noopener noreferrer"&gt;https://github.com/ilia-sokolov/OfficeAgent.NET&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Version 0.2 of OfficeAgent.NET opens the document workflow to more agents and more enterprise use cases. Copilot Studio agents, Microsoft 365 Copilot, Claude Code, and Codex can now create or modify Word documents from user intent - without touching OOXML directly, without losing details, and without leaving the user to fix the document afterwards. And with the new SharePoint provider, agents can do it right where most of the documents already live.&lt;/p&gt;

&lt;p&gt;Try it out and tell me what you think - that feedback will shape 0.3. If the direction is useful to you, add a star on GitHub to help other developers find it.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>ai</category>
      <category>mcp</category>
      <category>sharepoint</category>
    </item>
    <item>
      <title>Word Document Editing for AI Agents - Introducing OfficeAgent.NET 0.1</title>
      <dc:creator>Ilia Sokolov</dc:creator>
      <pubDate>Thu, 11 Jun 2026 18:02:29 +0000</pubDate>
      <link>https://dev.to/ilia-sokolov/word-document-editing-for-ai-agents-introducing-officeagentnet-01-2cc</link>
      <guid>https://dev.to/ilia-sokolov/word-document-editing-for-ai-agents-introducing-officeagentnet-01-2cc</guid>
      <description>&lt;p&gt;A few weeks ago I wrote about &lt;a href="https://dev.to/ilia-sokolov/why-ai-agents-struggle-with-word-documents-and-what-to-do-about-it-1kni"&gt;why AI agents struggle with Word documents&lt;/a&gt;. The short version: agents produce text, Markdown, JSON, and HTML, but a .docx is an OOXML package, and most of what makes it a Word document lives in XML parts outside the visible text. Something has to translate the agent's output into a valid Word file, and the Word file back into something the agent can reason about. I called this the agent-document layer, and announced an open-source project to build it for .NET.&lt;/p&gt;

&lt;p&gt;Today the first version is available. &lt;strong&gt;OfficeAgent.NET 0.1&lt;/strong&gt; is an open-source (MIT) .NET library that lets an AI agent describe Word document changes as a typed plan, while the library handles the Open XML details.&lt;/p&gt;

&lt;p&gt;If your agents generate proposals, contracts, reports, or review packs, this layer is the missing piece of document automation between the model and the final .docx. This article is a first look at what the release contains and how it works.&lt;/p&gt;

&lt;h3&gt;
  
  
  The core idea: the agent never writes document bytes
&lt;/h3&gt;

&lt;p&gt;The design decision behind OfficeAgent.NET is simple: the language model never produces .docx content directly.&lt;/p&gt;

&lt;p&gt;Instead, the agent expresses intent as a &lt;strong&gt;plan&lt;/strong&gt;: a typed, JSON-serializable list of operations. Replace this clause as a tracked change. Fill that content control. Add a row to this table. Attach a comment to that paragraph. JSON works well here because models produce it reliably and .NET code can validate it strictly. The library translates the plan into the Open XML manipulations that carry it out.&lt;/p&gt;

&lt;p&gt;Version 0.1 ships 15 operations for text, table, image, and styling manipulations, for comments and document properties, and for accepting or rejecting existing tracked revisions.&lt;/p&gt;

&lt;h3&gt;
  
  
  The workflow: inspect → find → preview → commit
&lt;/h3&gt;

&lt;p&gt;Every edit follows the same four steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Inspect&lt;/strong&gt; - the agent gets a structured map of the document: the outline, paragraphs with stable ids, styles, content controls, tables, images, and revisions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Find&lt;/strong&gt; - the agent searches for text and gets an address back for each match.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Preview&lt;/strong&gt; - the plan is checked against the current document. Nothing is written; the caller gets a before/after report and any validation errors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Commit&lt;/strong&gt; - the plan is applied as one all-or-nothing transaction. If any step fails, nothing is written.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The addresses are called &lt;strong&gt;anchors&lt;/strong&gt;, and they are the safety mechanism. The library issues anchors from inspect and find; the agent reuses them and never invents one. Each anchor carries the content it expects to find, and at commit time the library re-checks it against the live document. If the document changed in the meantime, the operation fails safely instead of editing the wrong place.&lt;/p&gt;

&lt;h3&gt;
  
  
  Document providers: filesystem now, SharePoint and more later
&lt;/h3&gt;

&lt;p&gt;OfficeAgent.NET does not read and write files directly. Documents come from &lt;strong&gt;document providers&lt;/strong&gt;, an abstraction that lets the library work with any file source. The application registers a document with a provider (for the filesystem provider, by its path) and receives an opaque document id in return. From that point on, inspect, find, preview, and commit all address the document by that id, and the provider takes care of loading from and saving to the underlying store.&lt;/p&gt;

&lt;p&gt;Version 0.1 ships a filesystem provider. Other providers, such as SharePoint, a database, or any custom store, can implement the same interface, and more will become available in later versions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Editing Word documents from a Microsoft Agent Framework agent
&lt;/h3&gt;

&lt;p&gt;The main scenario for OfficeAgent.NET is an agent doing the editing itself. For that, the workflow is exposed as agent tools over &lt;code&gt;Microsoft.Extensions.AI&lt;/code&gt;: &lt;code&gt;inspect_document&lt;/code&gt;, &lt;code&gt;find_in_document&lt;/code&gt;, &lt;code&gt;preview_plan&lt;/code&gt;, and &lt;code&gt;apply_plan&lt;/code&gt;. Wiring them into a Microsoft Agent Framework agent looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Agents.AI&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Extensions.AI&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Extensions.DependencyInjection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;OfficeAgent.AgentFramework&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;OfficeAgent.Core&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;OfficeAgent.Core.DocumentProviders&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;OfficeAgent.Word&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ServiceCollection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddWordFormat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddFileSystemDocumentProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"workspace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/srv/officeagent/workspace"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddOfficeAgent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BuildServiceProvider&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetRequiredService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;OfficeAgentClient&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Register the document with the provider; get an opaque id back.&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;RegisterAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"workspace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/srv/officeagent/workspace/contract.docx"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;OfficeAgentTools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;AsAIFunctions&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"You are editing documentId="&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt;
           &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ItemId&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt;
           &lt;span class="s"&gt;" on connectionId=workspace.\n\n"&lt;/span&gt;
           &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;OfficeAgentTools&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SystemPromptGuidance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;AIAgent&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ChatClientAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;chatClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// any Microsoft.Extensions.AI IChatClient&lt;/span&gt;
    &lt;span class="n"&gt;instructions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;         &lt;span class="s"&gt;"OfficeAgent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;"Edits Word documents using OfficeAgent.NET."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cast&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AITool&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="nf"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From here the agent drives the document itself: it inspects, finds anchors, builds a plan, previews it, and applies it through the tools. &lt;code&gt;OfficeAgentTools.SystemPromptGuidance&lt;/code&gt; provides ready-made instructions that teach the model the inspect → plan → apply protocol. &lt;code&gt;apply_plan&lt;/code&gt; saves the result and returns an output document id rather than sending .docx bytes back through the model; the host reads the result from storage and delivers the file through its own download or attachment API. A runnable Azure OpenAI example is in the &lt;code&gt;samples/AgentEdit&lt;/code&gt; project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using OfficeAgent.NET as a .NET library
&lt;/h3&gt;

&lt;p&gt;The same workflow can also be driven directly from C# code, without a model in the loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// service registration and document setup are the same&lt;/span&gt;
&lt;span class="c1"&gt;//as in the agent example&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetRequiredService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;OfficeAgentClient&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;RegisterAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"workspace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/srv/officeagent/workspace/contract.docx"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// inspect → find → preview → commit, addressing the document by its id&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;inspect&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;InspectAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"workspace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ItemId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;hit&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FindAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"workspace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ItemId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;FindQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Acme Corp"&lt;/span&gt;&lt;span class="p"&gt;))).&lt;/span&gt;&lt;span class="nf"&gt;First&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;DocumentPlan&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Snapshot&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Snapshot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="c1"&gt;// opt in to drift detection&lt;/span&gt;
    &lt;span class="n"&gt;Operations&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;PlanOperation&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ChangeTextOp&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Target&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Anchor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;With&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Globex Inc."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Mode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ChangeMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tracked&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;preview&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;PreviewAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"workspace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ItemId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;preview&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsValid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* surface preview.Errors */&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CommitAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"workspace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ItemId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Committed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;saved&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;OpenReadAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// saved.Stream holds the edited bytes;&lt;/span&gt;
    &lt;span class="c1"&gt;//result.Document.ItemId is the new id.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tracked edit lands as a real Word revision, with insert and delete runs that show up in Word's review pane, not as flattened text. The &lt;code&gt;samples/QuickEdit&lt;/code&gt; project in the repository contains a runnable version of this flow.&lt;/p&gt;

&lt;h3&gt;
  
  
  What 0.1 covers, and what it doesn't yet
&lt;/h3&gt;

&lt;p&gt;Version 0.1 covers Word .docx documents and the full editing workflow: inspect, find, preview, and transactional commit, protected by content-verified anchors and optional snapshot-based drift detection. The release includes the 15 operations described above, the filesystem document provider together with the interface other file sources can implement, the agent tools for Microsoft Agent Framework, two runnable samples (&lt;code&gt;QuickEdit&lt;/code&gt; and &lt;code&gt;AgentEdit&lt;/code&gt;), and a documentation set.&lt;/p&gt;

&lt;p&gt;This is a 0.1 preview release. Expect rough edges, and expect some APIs to change based on feedback.&lt;/p&gt;

&lt;h3&gt;
  
  
  Try it, and tell me where it breaks
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet add package OfficeAgent.Core &lt;span class="nt"&gt;--prerelease&lt;/span&gt;
dotnet add package OfficeAgent.Word &lt;span class="nt"&gt;--prerelease&lt;/span&gt;

&lt;span class="c"&gt;# for the agent-tools path&lt;/span&gt;
dotnet add package OfficeAgent.AgentFramework &lt;span class="nt"&gt;--prerelease&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The source, samples, and documentation are on GitHub: &lt;a href="https://github.com/ilia-sokolov/OfficeAgent.NET" rel="noopener noreferrer"&gt;https://github.com/ilia-sokolov/OfficeAgent.NET&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is early work, but the direction is clear: make real Word documents usable from agent workflows without requiring every agent developer to become an OOXML expert. If your agents need to produce real Office documents and this is (or isn't) the shape you would want, open an issue and tell me what's missing. That feedback is the whole point of shipping this early. And if the direction is useful to you, a star on GitHub helps other agent developers find it.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>dotnet</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Why AI agents struggle with Word documents, and what to do about it</title>
      <dc:creator>Ilia Sokolov</dc:creator>
      <pubDate>Fri, 22 May 2026 19:07:06 +0000</pubDate>
      <link>https://dev.to/ilia-sokolov/why-ai-agents-struggle-with-word-documents-and-what-to-do-about-it-1kni</link>
      <guid>https://dev.to/ilia-sokolov/why-ai-agents-struggle-with-word-documents-and-what-to-do-about-it-1kni</guid>
      <description>&lt;p&gt;For a lot of professionals in consulting, finance, sales, HR, legal, and operations, the final product is a document: a proposal, contract, report, invoice, brief, or review pack. Nowadays AI agents help people produce these documents. Agents draft individual sections or entire documents. They produce text, Markdown, JSON, and HTML as part of document-production workflows, and they can create basic &lt;code&gt;.docx&lt;/code&gt; files from scratch. But if you ask them to modify an existing document, or to produce a new one that follows an example template - the result usually disappoints. The produced documents frequently contain one or more of these problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fonts, colors, paragraph spacing, header and footer elements silently disappear.&lt;/li&gt;
&lt;li&gt;Headings get replaced with formatted text.&lt;/li&gt;
&lt;li&gt;Numbered lists turn into literal numbers.&lt;/li&gt;
&lt;li&gt;Tables get flattened or lose formatting.&lt;/li&gt;
&lt;li&gt;Tracked changes and comments vanish from the output.&lt;/li&gt;
&lt;li&gt;Content controls are replaced with text instead of populating them.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Word documents are hard for agents
&lt;/h2&gt;

&lt;p&gt;A &lt;code&gt;.docx&lt;/code&gt; is not a text file. It's an OOXML package: a zipped set of XML files containing all document elements and metadata. Most of what makes a Word document a Word document lives in those side files, not in the visible text.&lt;/p&gt;

&lt;p&gt;Agents produce plain text, Markdown, JSON, and HTML - not formats that preserve Word's document semantics by themselves. Even when an agent uses a Word-specific library to process documents, it usually works with the visible content and misses structure and styling parts that live outside the text, so styles, numbering, tracked changes, and comments get dropped.&lt;/p&gt;

&lt;h2&gt;
  
  
  The missing translation layer
&lt;/h2&gt;

&lt;p&gt;Something has to translate the agent's output into a valid Word file - and translate the Word file back into something the agent can reason about. Call this the agent-document layer.&lt;/p&gt;

&lt;p&gt;In one direction, the layer describes the document to the agent in agent-native terms: sections, paragraphs, headings, tables, content controls, comments, and review locations. The agent sees a document model it can reason about.&lt;/p&gt;

&lt;p&gt;In the other direction, the agent responds with a typed change plan. JSON works well for this: it's structured, explicit, easy for models to produce, and easy for .NET code to validate. The agent says what it wants (e.g. insert this clause as a tracked change, attach this comment to that paragraph, add this row to that table) and the layer applies the plan to the &lt;code&gt;.docx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The Open XML manipulations are managed by the layer, not by the agent or the application developer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The .NET landscape today
&lt;/h2&gt;

&lt;p&gt;If you operate in the .NET landscape, several categories of tools are available for working with Word documents:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Raw OOXML control&lt;/strong&gt;. Tools like Microsoft Open XML SDK give full access to the &lt;code&gt;.docx&lt;/code&gt; internals, but developers still have to manage Word structure manually.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rich-text conversion&lt;/strong&gt;. HTML or Markdown-to-Word pipelines are useful for simple generation, but often fail to preserve numbering, comments, tracked changes, and review structure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Template filling&lt;/strong&gt;. Placeholder tools work well for fixed templates, but are too limited for clauses, tables, redlines, or comments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Word object models&lt;/strong&gt;. Libraries like DocX, OfficeIMO, and NPOI make Word editing easier, but the application still decides every structural change.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full document platforms&lt;/strong&gt;. Aspose.Words, GemBox.Document, and TX Text Control provide broad document automation, but they are not designed to act as a contract between an AI agent and a Word file.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All these tools can be building blocks for the agent-document layer, but none of them are the layer itself. They don't let an agent express document intent and receive back a valid, reviewable .docx that preserves the user's template or sample document.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing OfficeAgent.NET
&lt;/h2&gt;

&lt;p&gt;I'm starting OfficeAgent.NET to build this layer for .NET: &lt;a href="https://github.com/ilia-sokolov/OfficeAgent.NET" rel="noopener noreferrer"&gt;https://github.com/ilia-sokolov/OfficeAgent.NET&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The goal is to give AI agents and .NET applications a simple way to describe Word document changes in structured terms, then let the library handle the OOXML details. The first focus is Word: opening existing &lt;code&gt;.docx&lt;/code&gt; templates, filling content controls, inserting structured tables, producing tracked-change suggestions, adding comments, and saving documents that preserve the user's template.&lt;/p&gt;

&lt;p&gt;This is early work, but the direction is clear: make real Word documents usable from agent workflows without requiring every agent developer to become an OOXML expert.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>dotnet</category>
      <category>ooxml</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
