Skip to content
System nominalUTC --:--:--Articles 085

What AI Agents Get Wrong in WordPress, and How to Catch It

A green wp-scripts build is not a correctness signal. The agent tested its own fake WordPress functions and reported success. Here is what catches it.

Devon Parker · @dparker

APIs and integrations

Topic
WP
Section
WordPress Internals
Published
16 OCT 2026
Reading time
8 MIN
Words
1764W
Technical cover graphic for What AI Agents Get Wrong in WordPress, and How to Catch It
Generated schematic — WP series, REV 2.6.

The plugin worked. That is what makes this worth writing about. A single prompt produced a 14-file Gutenberg block plugin, it activated cleanly in real WordPress 7.1.3, the block registered, the agent's own WP-CLI command returned the correct row, and the front end rendered correctly over HTTP. Escaping held against a deliberately hostile attribute set: a CSS injection attempt was rejected, a <script> tag was stripped, and <strong> survived.

Along the way, the agent reported several green results that meant nothing at all. One of them is the difference between shipping working code and shipping a white screen, and no tool in the default WordPress workflow would have told you which one you had. These are the failure modes, in the order they will bite you.

A green build never checked that the API exists

The first failure is structural and it is the one that should change how you read build output.

@wordpress/scripts runs webpack, and webpack is configured to treat every @wordpress/* package as an external. In the generated bundle, import { PanelColorSettings } from '@wordpress/block-editor' becomes a lookup on window.wp.blockEditor. Nothing resolves that import at build time. The contract between your code and WordPress is written into the generated index.asset.php file, which lists dependencies such as wp-block-editor and wp-components, and that file is what wires your script to the page. The build itself only checks that your JavaScript is syntactically valid and that the things you imported from your own files exist.

In that run the imported component was still a real export of @wordpress/block-editor 18.1.0, and the string was present in WordPress 7.1.3's core bundle. That is luck, not verification. If the component had been removed in a WordPress release, the build would have passed exactly as it did, and the block editor would have failed at runtime for every user.

This is not a WordPress-specific quirk so much as a consequence of how WordPress ships JavaScript. The dependency is a global at runtime, so a bundler has nothing to check against. Which means the only valid question about a generated block is not "did it build" but "did it render in an editor".

What a green build does tell you

That your syntax parses, that your local imports resolve, and that SCSS compiles. Those are real signals, and they are all it has. Treat a passing npm run build the way you would treat php -l: proof the file can be read, not proof the code is right.

The agent verified itself against its own beliefs

The second failure is worse, because the agent looked thorough while doing it. Asked to verify its work, the agent wrote a test harness containing hand-rolled implementations of wp_kses_post(), get_block_wrapper_attributes() and esc_attr__(). It ran that harness, reported that hostile input was stripped and valid input preserved, and deleted the harness afterwards.

An independent check against real WordPress 7.1.3 reproduced every one of those results. The stubs happened to be faithful. That does not rescue the method. What the harness tested was whether the code does what the model believes WordPress does. If the model's belief is wrong, the harness confirms the wrong belief and reports green, and it does so with the same confidence it shows when it is right. A stub cannot detect a misconception, because the stub was generated from the same misconception.

The agent stated the limitation itself, in its own summary: it could not run the WP-CLI command it had written because no WordPress was present. It knew what it was missing and it filled the hole with an invention. That is the behaviour to watch for, and it is the most persuasive failure in this whole area, because the transcript reads like diligence.

The only fix is a real install

Verification has to happen somewhere the agent cannot author. A Playground instance, a wp-env environment or a local install with WP-CLI gives the agent something to be wrong against. WordPress published an official wp-playground agent skill on 30 January 2026 for exactly this reason: it starts WordPress, works out whether the repository holds a plugin or a theme, mounts the code, and lets the agent check its own work over HTTP. Building that loop is the subject of the second module of the course on WordPress development with AI agents.

WordPress's own scaffolder hands you a classic theme

The third failure is inherited rather than generated, and it catches people who do the sensible thing and scaffold first.

Running wp scaffold _s produces a classic PHP template theme: around 20 files, including header.php, footer.php, single.php, page.php, archive.php, sidebar.php and template-parts/content.php. There is no theme.json. The style.css header still declares "Tested up to: 5.4" and "Requires PHP: 5.6".

So a workflow that reads "scaffold a theme with WP-CLI, then ask the agent to modernise it" starts with a theme designed for the classic editor and asks the agent to convert it. That is a harder task than generating a block theme from nothing, and it is harder to review because the diff is spread across every template file. wp scaffold plugin does not have this problem and remains a fine modern baseline, producing a main plugin file, readme.txt, composer.json, .distignore and .gitignore. The theme command is the one to avoid.

Two related environment traps are worth knowing before you blame the agent. Both wp scaffold plugin and wp scaffold _s refuse to run until WordPress is installed, so "scaffold now, install later" does not work. And wp-config.php needs its require_once ABSPATH . 'wp-settings.php'; line or WP-CLI reports a strange wp-config.php file and stops. Neither is the agent's fault, and both cost time if you meet them mid-task.

Nothing in the toolchain cross-checks the small inconsistencies

The fourth failure class is cosmetic individually and expensive in aggregate: locally plausible details that are globally wrong, none of which any gate flags.

In the generated plugin, the header declared Requires at least: 6.4 and phpcs.xml.dist set minimum_supported_wp_version to 6.4, while readme.txt said "Tested up to: 6.7". WordPress was at 7.1.3. Nothing in the toolchain objects to a compatibility line that no human would have typed in 2026, and a plugin reviewer would notice it immediately.

The same class of defect shows up in hooks. A wrong hook name is a valid string. A callback that declares three required parameters on a filter that passes two is valid PHP until the filter fires on a path nobody tested. A capability name with a typo is a valid string, and WordPress resolves it at runtime against a list built from roles, quietly returning false. PHP has no opinion about any of this, which is why php -l reported "No syntax errors" on every generated file including the two *.asset.php files, and was silent about everything that mattered.

FailureWhat reports itCaught by default
Syntax error in PHPphp -lYes
JavaScript that will not parsewp-scripts buildYes
Imported core component no longer existsA running editorNo
Wrong capability nameA user hitting the screenNo
Filter arity mismatchThe hook firing on a real requestNo
Output escaping that looks rightHostile input against real WordPressNo
readme.txt version driftA human reviewerNo
Hallucinated hook or functionWPCS, PHPStan or a fatalNo

The right-hand column is the whole argument. The automated signals you get for free cover syntax and nothing else, and the failures that reach customers are all in the bottom five rows.

WordPress already wrote the rejection criteria

On 1 February 2026 the WordPress project published official AI contribution guidelines, and they name these failures in the project's own voice. Contributions require disclosure of meaningful AI assistance. They must remain GPLv2-or-later compatible, which rules out tools whose terms restrict how their output may be redistributed. And the guideline on quality over volume lists the rejectable patterns: generic pull request descriptions that do not reflect real testing, large unreviewed code dumps, over-architected code where a simple solution would do, and hallucinated references to APIs, hooks, functions or links that do not exist.

The stated consequence is blunt. Maintainers may close or reject contributions that appear to be AI slop. An FAQ names Copilot, Claude Code, Codex and ChatGPT as the common tools.

Those guidelines govern contributions to WordPress itself. The reason to read them anyway is that their failure list is accurate for client work, and it is written by the organisation that sees more contributed WordPress code than anyone else. The mental model it prescribes is the useful part: treat AI output like code from an unknown external contributor. Review it, run it, and validate it before it goes anywhere.

There is no benchmark that tells you which agent is safe

The last thing to know is what you cannot look up. Aider's polyglot benchmark, the most widely cited language-by-language agent benchmark in the ecosystem, covers C++, Go, Java, JavaScript, Python and Rust. It does not contain PHP. Aider also has not shipped a release since August 2025. No other vendor publishes a benchmark claim that survives contact with its own documentation.

So there is no number that ranks agents by WordPress competence, and anyone quoting one is either reading a vendor badge or inventing. The one published WordPress run is a single session, one model, one plugin, demonstrated once. It is genuinely encouraging and it is not a benchmark. I would rather hold both of those ideas at the same time than pretend the second one away, because the correct response to a single success is not to generalise it. It is to install WPCS and PHPStan, wire them into the loop, give the agent a real WordPress to test against, and read the diff.

What to do on Monday

  1. Add WPCS and PHPStan as Composer dev dependencies and run them on every generated change. They are the only gates in this stack that catch a wrong hook or a bad capability name, and they are opt-in.
  2. Give the agent a running WordPress. Playground or wp-env turns every claim the agent makes about its own work into something you can check in a browser.
  3. Ask what the agent did not test. The summary in that run volunteered it could not execute its own CLI command, which is the single most useful sentence in the transcript.
  4. Read readme.txt, the plugin header and phpcs.xml.dist together every time. Version drift between those three files is the cheapest defect to catch and the easiest to ship.
  5. Keep wp scaffold plugin and drop wp scaffold _s from your prompts. A classic theme is not a starting point for a block theme.

Devon Parker · @dparker

APIs and integrations

Works through REST contract design, webhook reliability, idempotency keys, retry policy and the unglamorous edge cases that appear when two systems disagree about what happened.

Continue

Related in WordPress Internals