Automating WordPress maintenance with agents: what is worth automating and what is not
On this page, 10 sections
Run the integrity check that every WordPress maintenance guide recommends on a site with twelve plugins, five of them commercial, and this is the shape of what comes back.
The message strings, the counting and the exit code are from the WP-CLI source, which I read on 2 September 2026.
The plugin names and the counts are an illustration:

--dry-runshows what would change and changes nothing.--patchis the narrowest bar that still ships security fixes.--minortakes minor releases and holds back majors.--excludetakes everything except the plugins the whole site is built on.
$ wp plugin verify-checksums --all
Warning: Could not retrieve the checksums for version 5.9.2 of plugin acme-pro, skipping.
Warning: Could not retrieve the checksums for version 3.1.0 of plugin acme-forms, skipping.
Success: Verified 7 of 12 plugins (5 skipped).
$ echo $?
0
Exit code zero. Five plugins were never checked.
If your automation branches on the exit code, and most automation does, that site just passed an integrity check that examined fifty-eight per cent of its plugin code.
Why the exit code is zero

That is not a bug. The command downloads checksums from WordPress.org, and commercial plugins are not on WordPress.org, so there is nothing to compare against.
The handling in Checksum_Plugin_Command.php, in wp-cli/checksum-command, is four lines: when $checksums comes back false it calls WP_CLI::warning() with that skipping message, increments $skips, and continues.
And in report_batch_operation_results() in WP-CLI core, skips only affect the wording. A skip appends ({$skips} skipped) to the message.
When there are no outright failures the function calls WP_CLI::success(), which exits zero. Only the failures branch calls WP_CLI::error(), and that is the branch that exits non-zero.
The shape of the problem

This is the shape of almost every honest answer about automating WordPress maintenance. The task is automatable.
The thing you wanted to know is one layer behind the output, and an agent that reads only the summary line will confidently tell you the site is fine.
The split I actually use
Everything below assumes the agent has wp-cli over SSH and read access, set up the way I described in running Claude Code against WordPress, and the credential limits from the guardrails post.
The split is not about capability. An agent can run every command here. It is about which decisions have bounded consequences.
| Task | Automate? | Why |
|---|---|---|
| Gathering update, integrity and cron state | Yes | Read-only, and the output is what a human needs to decide |
| Reading changelogs and classifying risk | Yes | Language work with a written artefact you can check |
| Detecting file drift against WordPress.org | Yes, with the skip caveat handled | Deterministic comparison |
| Post-change verification sweeps | Yes | Cheap, repeatable, catches the thing you did not think of |
| Deciding whether to apply a major update | No | Unbounded consequence on a page-builder site |
| Fleet-wide scheduled updates | No, use a fleet tool | Already solved, with rollback and reporting you would rebuild badly |
| Restoring a backup | No | One shot, and the failure mode is losing the good copy |
| Cleaning a compromised site | No | Requires knowing what normal looked like before |
| Renewing or dropping a plugin licence | No | Commercial decision with a client attached |
Worth automating: the state-gathering pass
This is the highest-value thing an agent does with a WordPress site, and it is entirely read-only.
One script, one JSON blob, and the agent reasons over it instead of running twenty commands and losing the earlier output to context pressure.
Mine runs six things and prints one object.
wp plugin list --format=json --fields=name,status,update,version, and the same forwp theme list.wp core check-update --format=json, falling back to an empty array when it writes nothing.wp plugin verify-checksums --all, with stdout and stderr sent to two different files, because the warnings are the finding.wp core verify-checksums --include-root, which is the one that reports files sitting in the WordPress root that do not belong to WordPress.- A count of the skip warnings:
grep -c 'skipping\.$'over the warning file, stored asplugins_not_verifiable. - One
jq -ncall that slurps the three JSON files and the count into a single object keyed by site.
The one field that changes behaviour
The field that changes behaviour is plugins_not_verifiable.
Any number above zero means the integrity check has a hole in it exactly the size of your commercial plugins, which are also the plugins most likely to have been nulled, patched by hand, or installed from a marketplace that is not the vendor.
Feed that number to the agent and tell it to treat a non-zero value as a finding rather than a footnote.
The root-file check nobody runs
The other half of that gap is wp core verify-checksums --include-root, which warns about files in the WordPress root that do not belong to WordPress.
That is a genuinely useful signal and it is one of the few automated checks that would have caught the situation I wrote about when a scanner reported a site clean while it served spam to Googlebot.
Worth automating: update triage, which is not the same as updating
The distinction that makes this safe: the agent produces the plan, a human approves it, then the agent executes the approved plan. WP-CLI gives you four flags to do that properly.
wp plugin update --all --dry-run
wp plugin update --all --patch
wp plugin update --all --minor
wp plugin update --all --exclude=elementor,elementor-pro
--dry-run, --patch, --minor and --exclude are all documented options on wp plugin update.
The --exclude flag is the one that turns this from a gamble into a policy: the plugins your layout depends on go on the exclusion list permanently and get handled by a human with a staging copy.
Where the agent earns its keep
Where the agent earns its keep is the layer above the flags.
Given the dry-run output, it can pull each plugin’s changelog, sort the updates into security, bug fix, feature and breaking, and tell you which three of the eighteen you actually need to think about.
That is language work with a written artefact you can check, which is the shape of task agents are reliably good at.
Do not stack an agent on a broken auto-update setup
If auto-updates are meant to be handling this and are not, that is a separate diagnosis with its own set of causes, and I have written it up in fixing WordPress automatic updates that are not working.
Do not stack an agent on top of a broken auto-update setup and assume the agent is the fix.
Worth automating: the verification sweep after a change
Updates rarely fail loudly. They fail by turning one template into a blank section, or by dropping a widget that only appears on the pricing page.
The check is boring, repeatable and exactly what you should hand to a machine.
Capture the status code and the byte size of every page that matters before the update, do it again after, then join the two files and print any row where the status changed or the size dropped below ninety per cent of what it was.
What this catches and what it does not
Byte size within ten per cent is a crude proxy and it will produce false positives on anything with a rotating element.
It also catches the failure that matters most, which is a page that still returns 200 while rendering a fraction of its content.
Pair it with a real render check on a handful of templates and you have covered most of what goes wrong.
Not worth automating: the update go/no-go on a site you did not build
The mechanism is worth stating plainly, because it explains several of the rows in that table at once.
Retrievable evidence against evidence that is nowhere
An agent is good at tasks where the evidence is retrievable and the consequence of being wrong is a bad paragraph.
It is bad at tasks where the evidence lives in a place nothing can query.
Whether a major update to a page-builder addon breaks a client’s homepage depends on which of forty widgets that homepage uses, which of them the addon rewrote, and whether the site has custom CSS targeting the old markup.
None of that is in the changelog. Some of it is not written down anywhere.
So the agent gathers, classifies and recommends. A human with the site open decides. On sites where a broken layout means a phone call, that division has never felt like a limitation to me.
Not worth automating: the fleet update loop, because it already exists
This is the part where I will argue against building the thing.
If you manage twenty client sites, the job of pushing updates across them with a rollback point, a per-site log and a report the client can read is a solved problem, and the solutions have had years of edge cases beaten out of them.
Where the fleet tools actually differ
I have run the feature comparisons across this category in detail. The short version of where the differences actually land:
- The eight WordPress site management tools worth looking at is the starting point if you have not picked one.
- MainWP against ManageWP is the self-hosted-dashboard versus hosted-service decision, and it changes where your agent can reach.
- WP Remote against MainWP and MainWP against InfiniteWP cover the rest of the self-hosted side.
- ManageWP against WP Umbrella and WP Umbrella against UpdraftCentral are the ones to read if update safety and backup handling are what you care about.
The arrangement that works
The useful pattern is not agent instead of fleet tool.
It is the fleet tool doing the mechanical push, and the agent doing the reading and the reporting that the fleet tool does not do: reading changelogs, correlating an error spike with a specific update, drafting the client-facing note.
The commercial side of that arrangement, including who pays for which licence, is its own conversation and I covered it in managing WordPress plugin subscriptions for clients.
Not worth automating: restores, and cleanups
A restore is one shot with an unbounded downside. The realistic failure is not a wrong command, it is a right command against the wrong snapshot, and by the time anyone notices, the good copy has been written over. A human runs restores.
Why cleanup is worse than a restore
Cleaning a compromised site fails for a different reason. Removing malware requires knowing what the file was supposed to contain, and on a site with a decade of plugins and a hand-edited theme, nothing has that baseline.
wp core verify-checksums gives it to you for core. wp plugin verify-checksums gives it to you for WordPress.org plugins and, as established at the top, silently gives you nothing for the rest.
An agent asked to clean a site with an incomplete baseline will delete things that were supposed to be there.
What the agent can do in an incident
What the agent can do in an incident is collect evidence fast: modified file timestamps, the checksum diff, admin users created in the last month, scheduled events that do not belong to any installed plugin, and the raw access log lines around the first modified file.
That is a triage pack, and it makes the human faster without giving the machine a delete button.

The one number to check on your own fleet this week
Run this on every site you maintain:
wp plugin verify-checksums --all 2>&1 \
| grep -c 'skipping\.$'
That count is how many plugins on that site have no integrity baseline at all.
Not how many are compromised. How many you could not tell either way. On most agency fleets it is not zero, and until now the number was probably invisible because the command exited zero and printed the word Success.
The fix is a policy
Once you have the number, the fix is a policy rather than a script: keep a known-good copy of every commercial plugin zip you install, checksum it yourself at install time, and compare against that.
It is the same idea WordPress.org gives you for free, applied to the half of your site that WordPress.org does not cover.
If you are doing this across client sites, the process side matters as much as the tooling, and how to manage WordPress websites for clients covers how I structure that.
And if you want the underlying detail on what an agent can reach over HTTP rather than over SSH, including why there is no plugin update route in core at all, that is in the post on the REST API as an agent surface.
Resources
- wp plugin verify-checksums
- wp-cli/checksum-command, including wp core verify-checksums –include-root
- wp plugin update and its dry-run, patch, minor and exclude options
- wp plugin auto-updates
- report_batch_operation_results() in WP-CLI core
- The full WP-CLI command reference
Disclosure: I am CMO at POSIMYTH, which ships WordPress plugins across 500,000+ installs, and our commercial plugins are exactly the kind that verify-checksums skips. That is the honest reason I know the gap is there.
More on agents on wordpress
- MCP servers for WordPress: what actually exists and what each one can do
- The WordPress REST API as an agent surface: what you can and cannot automate
- Guardrails for running an agent against a production WordPress site