<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[WPPilot]]></title><description><![CDATA[WPPilot]]></description><link>https://wppilot.hashnode.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1593680282896/kNC7E8IR4.png</url><title>WPPilot</title><link>https://wppilot.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Wed, 30 Sep 2026 05:42:01 GMT</lastBuildDate><atom:link href="https://wppilot.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Stage a Gutenberg section with an AI agent, then let WordPress finish the blocks]]></title><description><![CDATA[A PHP request can store block markup. It cannot honestly pretend it ran every block's editor script. Core blocks and third-party blocks validate attributes and write their saved HTML in the browser. I]]></description><link>https://wppilot.hashnode.dev/stage-a-gutenberg-section-with-an-ai-agent-then-let-wordpress-finish-the-blocks</link><guid isPermaLink="true">https://wppilot.hashnode.dev/stage-a-gutenberg-section-with-an-ai-agent-then-let-wordpress-finish-the-blocks</guid><category><![CDATA[mcp]]></category><dc:creator><![CDATA[WPPilot]]></dc:creator><pubDate>Tue, 29 Sep 2026 12:16:31 GMT</pubDate><content:encoded><![CDATA[<p>A PHP request can store block markup. It cannot honestly pretend it ran every block's editor script. Core blocks and third-party blocks validate attributes and write their saved HTML in the browser. If an agent skips that step, you get a page that looks fine in the database and broken in the editor.</p>
<p>This walkthrough is one job: change the intro of an About page to a Media &amp; Text block, image on the left, without touching the live page until WordPress's own block editor has serialized the tree. The tool is <a href="https://wppilot.co">WPPilot</a>, a self-hosted WordPress plugin that turns the site into an MCP server. The Gutenberg workflow is in the free plugin. There are 11 Gutenberg abilities, and none of them require WPPilot Pro.</p>
<h2>What you are actually installing</h2>
<p>WPPilot Free does not bundle a model. Claude, Cursor, ChatGPT, or another MCP client brings its own. The plugin runs on your host. There is no WPPilot relay in the middle and no per-request fee. Requirements from the docs: WordPress 6.9 or newer, PHP 8.0 or newer, and HTTPS if a remote client connects.</p>
<p>Free is distributed from GitHub releases and from the site download, not from the WordPress.org plugin directory. Install and activate it, then connect the client. The connection guides cover OAuth 2.1 with PKCE and Application Passwords. Start on the Read Only safety profile. That profile is free, and it is the right first setting because a read of the block tree cannot rewrite the page.</p>
<p>The three profiles that ship in Free are Read Only, Production Safe (the install default), and Developer Full Access. Production Safe blocks PHP, WP-CLI, the filesystem, direct database access, and plugin or theme install and delete. You do not need Developer Full Access for this Gutenberg job.</p>
<h2>Why the change is staged</h2>
<p>The free Gutenberg module does not dump a raw <code>post_content</code> string for ordinary blocks. It keeps a pending batch. A draft batch is recoverable and does not alter the saved page. Static and native blocks are finalized inside a hidden editor frame so the blocks' own JavaScript can serialize them. Only blocks that WPPilot itself owns, and that are dynamic-only, may use the direct write ability. A Media &amp; Text block is a core block, so it takes the queue.</p>
<p>Pro block-library modules (GenerateBlocks, Kadence Blocks, Spectra, and others) can expose catalogues and schemas. They still land through this same free queue. You do not need those modules to replace one core section.</p>
<h2>The six calls, in order</h2>
<p>Open the Block Editor Queue screen in wp-admin and leave that tab open. Then ask the agent to follow this sequence. Names below match the <a href="https://wppilot.co/docs/reference/gutenberg">Gutenberg ability reference</a>.</p>
<ol>
<li><p><code>gutenberg-get-finalizer-runtime</code><br />Confirms the queue page is open and heartbeating. If it is offline, the ability returns the admin URL to open. Do not queue a static block change while this reports offline.</p>
</li>
<li><p><code>gutenberg-get-content</code><br />Reads the saved content of the About page as a compact block tree, and says whether a non-finished queue item already exists for that page. It does not return the queued spec itself. Pending work is summarized separately.</p>
</li>
<li><p><code>gutenberg-create-pending-batch</code><br />Creates an empty draft batch. Draft batches cannot be finalized yet. That is intentional.</p>
</li>
<li><p><code>gutenberg-add-pending-change</code><br />Adds one replace-content target: the About page, with a block tree whose intro is a Media &amp; Text block and whose other sections you copied from the read in step 2. Queued is not live.</p>
</li>
<li><p><code>gutenberg-enable-batch-finalization</code><br />Marks the batch ready only after every target you care about is queued. A half-built batch should not be marked ready. If the queue tab is open, it can pick the batch up. The response includes status URLs an agent can poll.</p>
</li>
<li><p>Read it back<br />Use <code>gutenberg-get-pending-batch</code> until the batch reports finalized, then <code>gutenberg-get-content</code> again, and look at the editor and the front end. Do not tell anyone the intro changed because the queue accepted the spec.</p>
</li>
</ol>
<p>Two more reads help when something sticks: <code>gutenberg-list-pending-batches</code> for the compact queue, and <code>gutenberg-get-finalization-url</code> for the admin page of one ready or failed batch. Two cancels remove queued work without editing the page: <code>gutenberg-delete-pending-change</code> for one item, and <code>gutenberg-delete-pending-batch</code> for the whole batch. The eleventh ability, <code>gutenberg-write-content</code>, is the direct path and refuses a tree that contains native or static blocks.</p>
<p>That is the full set of 11. Five are reads, and the writes that replace or finalize content ask for confirmation. The product page's representative session shows <code>gutenberg-add-pending-change</code> and <code>gutenberg-enable-batch-finalization</code> as confirmed calls.</p>
<h2>A prompt that stays small</h2>
<p>Give the agent a target, a block name, and a stop rule. Something like this:</p>
<blockquote>
<p>Read the About page with the Gutenberg content ability. If the Block Editor Queue runtime is offline, stop and tell me the URL to open. Create one draft batch. Queue a replacement that changes only the intro to a Media &amp; Text block with the image on the left, and keep every other block from the current tree. Do not enable finalization until you have shown me the queued target list. After I agree, enable finalization, poll until the batch is finalized, and read the content back.</p>
</blockquote>
<p>That prompt refuses the failure mode where the model rewrites the whole page because "refresh the intro" was vague.</p>
<h2>What "done" is not</h2>
<p>A full-content replacement is still destructive even though it sits in a queue first. Read the tree, stage it, and keep a normal backup. The change ledger in Free records supported writes with a redacted before and after, and reversible operations can be rolled back. Rollback is not universal. Do not treat the ledger as a hosting backup.</p>
<p>Also do not confuse this with WPPilot Pro's approval queue. When that Pro switch is on, every write waits for a person and the admin can be emailed. Reads still run. This About-page job does not need that switch. Production Safe plus an explicit finalization step is enough for a single section.</p>
<p>If a batch fails or conflicts, cancel it with <code>gutenberg-delete-pending-batch</code> and start a new draft batch. Cancelling does not rewrite the About page.</p>
<h2>Where this sits next to the rest of the plugin</h2>
<p>The same free plugin also exposes WordPress core abilities (posts, media, comments, menus) and a free Elementor set. Deeper plugin integrations, including SEO metadata tools and the page-builder catalogues, are Pro. WooCommerce abilities are Pro and are not part of this Gutenberg flow. The free safety profiles, the preview-before-write path for ordinary post edits, and the change ledger apply around the queue. They do not replace the Block Editor Queue for static blocks.</p>
<p>The longer map of the 11 abilities, with the queue rules, is the <a href="https://wppilot.co/mcp-for-gutenberg">Gutenberg MCP guide</a>. Safety profile behaviour is documented under <a href="https://wppilot.co/docs/safety-profiles">safety profiles</a>. The free plugin source and releases are on <a href="https://github.com/wppilot-labs/wordpress-mcp-elementor-wppilot">GitHub</a>.</p>
<p>If you try this, do it on a draft or on a page you can revert, with the queue tab actually open. The interesting part is not that an agent can invent block JSON. It is that the live page stays unchanged until WordPress's own editor accepts the batch.</p>
]]></content:encoded></item><item><title><![CDATA[What "Undo" Really Means When an AI Agent Edits Your Elementor Pages]]></title><description><![CDATA[Most "AI edits my WordPress site" demos end when the page looks right. The questions that matter start afterwards. What exactly changed? Who, or which agent, changed it? And if it's wrong, can you put]]></description><link>https://wppilot.hashnode.dev/what-undo-really-means-when-an-ai-agent-edits-your-elementor-pages</link><guid isPermaLink="true">https://wppilot.hashnode.dev/what-undo-really-means-when-an-ai-agent-edits-your-elementor-pages</guid><category><![CDATA[WordPress]]></category><category><![CDATA[Elementor]]></category><category><![CDATA[AI]]></category><category><![CDATA[mcp]]></category><category><![CDATA[webdev]]></category><dc:creator><![CDATA[WPPilot]]></dc:creator><pubDate>Sun, 27 Sep 2026 23:23:56 GMT</pubDate><content:encoded><![CDATA[<p>Most "AI edits my WordPress site" demos end when the page looks right. The questions that matter start afterwards. What exactly changed? Who, or which agent, changed it? And if it's wrong, can you put it back?</p>
<p>For Elementor sites those questions are harder than they look, because Elementor doesn't store pages where most WordPress tooling expects them. This article covers why, what a safe element-level edit looks like over the Model Context Protocol (MCP), and, most importantly, where rollback does and doesn't cover you. Some of these limits surprised me when I read the documentation closely.</p>
<p>The examples use <a href="https://wppilot.co/mcp-for-elementor">WPPilot</a>, a GPL plugin that turns WordPress into an MCP server and ships Elementor editing abilities in its free edition. If you want a broader walkthrough of connecting a client and the everyday jobs you can hand to an agent, I covered that in a <a href="https://dev.to/wppilot/wordpress-mcp-for-beginners-9-real-jobs-you-can-hand-to-claude-cursor-or-chatgpt-safely-20d0">beginner's guide on DEV</a>. This article focuses on Elementor only.</p>
<h2>The silent-success problem</h2>
<p>A classic WordPress post keeps its body in <code>post_content</code>. Elementor keeps the layout in postmeta, as a typed tree of containers and widgets, and renders from that tree. Beaver Builder works the same way (<code>_fl_builder_data</code>), and so do Oxygen and Bricks with their own trees. Divi, Etch and WPBakery are different: they put their markup in <code>post_content</code>.</p>
<p>So a generic "update the page" call against an Elementor page does something odd. The REST request succeeds, the database changes, and visitors see nothing new. The builder may even overwrite your change from its own tree the next time someone saves in the editor.</p>
<p>WPPilot's changelog describes the fix it shipped: writing <code>post_content</code> to a page built with Elementor, Bricks or Beaver Builder "is now refused instead of silently doing nothing", and the refusal names the builder and the ability that owns the page. You can still force the write for feeds and search with an explicit flag, and the response then says the page itself didn't change.</p>
<p>That behaviour, an honest refusal instead of a fake success, is the first thing I'd test in any AI-for-WordPress tool.</p>
<h2>Element-level editing, not document dumps</h2>
<p>The alternative is to edit the tree itself, one element at a time. WPPilot Free registers 17 Elementor abilities (in 1.13.0) once Elementor 3.6 or newer is active. Editing has been free since 1.10.0, and the atomic-readiness audit came in 1.13.0. The abilities fall into three groups.</p>
<p><strong>Reads</strong> (safe in any profile):</p>
<ul>
<li><code>elementor-check-setup</code>: Elementor and Pro versions, and whether the v4 atomic runtime and its sub-features exist</li>
<li><code>elementor-audit-atomic-readiness</code>: how much of the site is v4 atomic vs classic v3</li>
<li><code>elementor-get-content</code>: a compact skeleton by default (ids, types, children), with one element's full settings on request</li>
<li><code>elementor-find-elements</code>: ids and paths for elements matching a widget type, a setting or text</li>
<li><code>elementor-get-widget-params</code>, <code>elementor-get-page-settings</code>, and <code>elementor-get-schema</code>, which lists the widgets and controls on <em>this</em> install</li>
</ul>
<p><strong>Targeted writes:</strong></p>
<ul>
<li><code>elementor-edit-element</code>: merges new settings into one element</li>
<li><code>elementor-add-element</code>, <code>elementor-move-element</code> (keeps id, settings and children), <code>elementor-duplicate-element</code> (fresh ids for the copy), <code>elementor-reorder-children</code></li>
<li><code>elementor-set-page-settings</code>: merged, validated page settings</li>
<li><code>elementor-clear-document-cache</code>: clears the rendered-element cache so the next view rebuilds</li>
</ul>
<p><strong>Destructive, confirmation required:</strong></p>
<ul>
<li><code>elementor-delete-element</code>: the reference says "Permanent - there is no trash for Elementor elements."</li>
<li><code>elementor-set-content</code>: replaces a whole document tree. Invalid properties are dropped and named in the response, or you can pass <code>strict</code> to refuse the write instead.</li>
</ul>
<p>The design choice here is that a typical edit never needs the whole document. An agent that reads a skeleton, finds three ids and patches those three elements uses far fewer tokens. It also can't reformat the other forty widgets while it's at it.</p>
<p>A read-first sequence looks like this:</p>
<pre><code class="language-text">elementor-check-setup        → v3, v4 atomic, or both on this site?
elementor-get-content        → compact skeleton of post 482
elementor-find-elements      → ids of every button with text "Contact us"
elementor-get-widget-params  → which settings those buttons actually use
elementor-edit-element ×3    → change only the text setting on each id
get-page-view-link           → preview URL to check at desktop / tablet / mobile
</code></pre>
<p>You don't have to spell this out in every prompt. WPPilot's discovery call returns a catalogue of the skills saved on the site, with an instruction to load a matching one before starting. The <strong>Skills</strong> module that manages them is in the free plugin, not Pro. You can also add site-wide instructions, for example "never publish", "keep our heading scale" or "always read the skeleton first".</p>
<h2>Now the part people skip: rollback</h2>
<p>Every write WPPilot makes lands in a redacted <strong>change ledger</strong>. The ledger records the ability, the target and the credential that acted: the OAuth client id (stored hashed) or the Application Password's UUID, plus the client name the agent reported. You read it with <code>list-changes</code> and <code>get-change</code>, and reverse supported entries with <code>rollback-change</code>. A rollback checks the current state against a stored before-image fingerprint, so it won't overwrite a human edit made in the meantime.</p>
<p>The key word is <em>supported</em>. For Elementor, here is the rule as the documentation states it:</p>
<blockquote>
<p>On Free alone these edits are recorded without a way back; with Pro active the ledger also keeps a copy of the document, so they can be rolled back from the entry.</p>
</blockquote>
<p>In practice:</p>
<table>
<thead>
<tr>
<th>Change</th>
<th>Free only</th>
<th>Free + Pro active</th>
</tr>
</thead>
<tbody><tr>
<td>Elementor element edit (<code>elementor-edit-element</code>, add, move, duplicate)</td>
<td>Recorded in the ledger, <strong>no rollback</strong></td>
<td>Recorded, <strong>rollback from the entry</strong></td>
</tr>
<tr>
<td><code>elementor-delete-element</code></td>
<td>Needs confirmation; permanent, no trash</td>
<td>Needs confirmation</td>
</tr>
<tr>
<td>Full tree replace (<code>elementor-set-content</code>)</td>
<td>Needs confirmation; replaces the tree</td>
<td>Needs confirmation</td>
</tr>
<tr>
<td>New draft page (<code>create-post</code>)</td>
<td>Recorded; rollback available</td>
<td>Same</td>
</tr>
<tr>
<td>Post title/content edit (<code>update-post</code>)</td>
<td>Recorded; rollback available</td>
<td>Same</td>
</tr>
</tbody></table>
<p>After a Pro rollback, the docs suggest opening the page in Elementor once to confirm the tree looks right.</p>
<p>For context, Elementor isn't the only area where "recorded" doesn't mean "reversible". WPPilot's own use-case pages say SEO metadata edits and WooCommerce product edits are logged with no rollback either. The ledger is an audit trail first and an undo button only for specific operations. It holds at most 500 records and isn't a backup.</p>
<h2>A Free-only workflow that doesn't need rollback</h2>
<p>If you're on the free plugin, plan so that you never <em>need</em> to undo an Elementor edit:</p>
<ol>
<li><strong>Work on a copy.</strong> Duplicate the page, or have the agent create a new draft, and point every edit at that. A draft can simply be deleted.</li>
<li><strong>Save the before-state yourself.</strong> Ask for <code>elementor-get-content</code> with full settings on the elements you're about to change, and keep that output. It's your manual restore point.</li>
<li><strong>Use Read Only for exploration.</strong> Setup checks, skeleton reads and element searches all work under Read Only. Switch to Production Safe only for the edit session.</li>
<li><strong>Keep writes small.</strong> Three <code>elementor-edit-element</code> calls are easy to check. One <code>elementor-set-content</code> is a full replacement that asks for confirmation for good reason.</li>
<li><strong>Attach evidence.</strong> <code>capture-page</code> stores a screenshot alongside the entry, so the record shows how the page looked at that moment.</li>
<li><strong>Verify in two places:</strong> the Elementor editor <em>and</em> the front end. A successful tool call isn't a finished page.</li>
</ol>
<h2>Guardrails that apply either way</h2>
<p>The server enforces three safety profiles on every call:</p>
<ul>
<li><strong>Read Only</strong> blocks all writes.</li>
<li><strong>Production Safe</strong>, the installation default, allows content and design edits but blocks raw PHP, WP-CLI, filesystem and database access, and plugin installs.</li>
<li><strong>Developer Full Access</strong> allows everything enabled and belongs on staging.</li>
</ul>
<p>WordPress capabilities are checked per request, so connect the agent as an Editor-level user, not your admin account. Individual abilities can be switched off, writes are rate-limited per credential, and new content defaults to draft. The details are in the <a href="https://wppilot.co/docs/safety-profiles">safety profiles documentation</a>.</p>
<h2>When Pro is worth it for Elementor work</h2>
<p>The free plugin <em>edits</em> Elementor pages. Pro adds three things that matter here:</p>
<ul>
<li>the ledger keeps a document copy, so <strong>element edits become reversible</strong></li>
<li>the <strong>authoring layer</strong>: <code>elementor-build-page</code> for whole-page composition, templates and display conditions, popups, global classes and variables</li>
<li>a <strong>human approval queue</strong> that holds every write until someone signs off, and emails the site admin</li>
</ul>
<p>If agents touch client sites while nobody is watching, the rollback and approval features are the strongest reason to upgrade. Plans differ only by site count; see <a href="https://wppilot.co/pricing">pricing</a>.</p>
<h2>Takeaways</h2>
<ul>
<li>A tool that edits Elementor through <code>post_content</code> will report success and change nothing. Insist on element-level abilities or an honest refusal.</li>
<li>Read the skeleton, patch ids, verify visually.</li>
<li>"It's in the ledger" doesn't mean "I can undo it". On Free, Elementor element edits have no rollback. With Pro active, they do.</li>
<li>Design your workflow around the undo you actually have: drafts and copies on Free, ledger rollback plus approvals on Pro.</li>
</ul>
<p>The plugin source, including the Elementor abilities and the safety model, is on <a href="https://github.com/wppilot-labs/wordpress-mcp-elementor-wppilot">GitHub</a> under GPL-2.0-or-later.</p>
]]></content:encoded></item></channel></rss>