=== Agent Toolbelt – Safe Site Operations for AI Agents === Contributors: kostyatereshchuk Tags: ai agent, mcp, abilities, maintenance mode, audit log Requires at least: 6.9 Tested up to: 7.0 Requires PHP: 7.4 Stable tag: 1.0.0 Donate link: https://tutori.org/donate/ License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html Safe hands for your site's AI agent: guarded maintenance operations with dry-run, confirm tokens, a full audit log, and automatic rollback. == Description == AI agents can now operate WordPress sites — through the WordPress Abilities API, MCP, and WP-CLI. That's powerful, and it's also exactly how a confused or manipulated agent breaks a site. Agent Toolbelt gives your agent a small set of maintenance operations it can use **safely**: every operation can be previewed without changing anything, the dangerous one requires an explicit look-then-act confirmation, everything is recorded in an audit log you can read later, and the riskiest ability is off until you personally turn it on. = The abilities = * **Site status** *(read-only)* — WordPress/PHP/database versions, environment, active theme, plugin counts, pending updates, the latest Site Health summary, and which toolbelt abilities are enabled. The agent's natural first call. * **Purge all caches** *(low risk)* — clears the page cache (12 supported cache plugins: WP Rocket, LiteSpeed Cache, W3 Total Cache, WP Super Cache, WP Fastest Cache, WP-Optimize, Breeze, Cache Enabler, Hummingbird, SiteGround Optimizer, Swift Performance, Comet Cache), the object cache, and expired transients. * **Flush rewrite rules** *(low risk)* — fixes pretty permalinks returning 404 after plugins or post types change. * **Maintenance mode** *(medium risk)* — turns the visitor-facing maintenance page on or off. **It always auto-expires** (5 minutes by default, 60 max): even if the agent forgets to turn it off, your site can never stay locked. Logged-in administrators keep seeing the normal site, and the REST API and wp-admin stay reachable the whole time. * **Read audit log** *(read-only)* — what ran, when, by which caller, and the result. Lets the agent (or you) review and explain past actions. * **Update plugin** *(high risk, disabled by default)* — updates one plugin with a safety net; see below. = Safe plugin updates with automatic rollback = The flagship ability. When you enable it, an agent can update a plugin like this — and only like this: 1. **Dry-run first (forced).** The ability defaults to preview mode: it reports the installed and available versions and returns a one-time confirm token. Nothing changes. 2. **Confirm to execute.** The real update requires that token back. It is bound to the exact plugin, the exact user, and expires in 15 minutes. A single injected prompt cannot one-shot an update — the agent must look, then act. 3. **Backup, update, health check.** The update runs on WordPress core's own upgrader, which keeps a temporary backup of the current version. Afterwards the plugin checks that your site still responds: it fetches the home page and the REST API as an anonymous visitor and scans for fatal errors. 4. **Automatic rollback.** If the site broke, the previous version is restored automatically — and the audit log records `rolled_back` so everyone knows what happened. The ability refuses to update Agent Toolbelt itself, refuses single-file plugins (WordPress core cannot back them up, so the rollback promise can't be kept), refuses when no update is available, and refuses on multisite. = Built for the prompt-injection era = The canonical agent-security failure is indirect prompt injection: malicious content on a page tricks your own agent into calling destructive tools (see OWASP LLM Top 10, LLM01). No plugin can make a gullible agent smart — what it can do is shrink the blast radius: * **Non-destructive by default.** Read-only and low-risk operations only, until you opt in to more. * **Dry-run everywhere.** Every mutating ability accepts a preview mode; the high-risk one defaults to it. * **Look-then-act confirmation** for the destructive ability — one-time, input-bound, expiring tokens. * **Least privilege.** Every call requires a logged-in user with `manage_options`; plugin updates additionally require `update_plugins`. Anonymous callers can't even see the abilities. * **Disabled means invisible.** An ability you turn off is not registered at all — agents don't see a "forbidden" tool, they see no tool. * **Everything audited.** Each execution writes who called (REST, WP-CLI, admin), as what user, with what input digest, and the result — kept 90 days, capped at 2,000 rows. * **Kill switch.** Add `define( 'AGENT_TOOLBELT_DISABLED', true );` to `wp-config.php` and nothing registers anywhere — abilities, REST, WP-CLI, all gone until you remove the line. = Connect your AI agent = The abilities are standard WordPress Abilities, so anything that speaks the Abilities API can use them. The fastest path, with no extra plugins, is the WordPress REST API: 1. Create an application password for an administrator (Users → Profile → Application Passwords). 2. List the available abilities: `curl -u "admin:APP_PASSWORD" https://example.com/wp-json/wp-abilities/v1/abilities` 3. Run one. Read-only abilities use GET: `curl -u "admin:APP_PASSWORD" "https://example.com/wp-json/wp-abilities/v1/abilities/agent-toolbelt/site-status/run"` Mutating abilities use POST with an `input` object: `curl -u "admin:APP_PASSWORD" -X POST -H "Content-Type: application/json" -d '{"input":{"dry_run":true}}' https://example.com/wp-json/wp-abilities/v1/abilities/agent-toolbelt/purge-all-caches/run` Give those three lines to your agent (Claude, ChatGPT, or any tool-calling model) as its instructions for operating the site — the ability descriptions and JSON schemas tell it the rest. Using MCP? Any MCP bridge that exposes WordPress Abilities will automatically expose exactly the abilities you enabled here — nothing else. (The official WordPress `ai` plugin lists MCP support as upcoming; several community MCP plugins already bridge the Abilities API.) = WP-CLI = The same operations, same guardrails, for deploy scripts and humans: * `wp agent-toolbelt list` — abilities with risk level and enabled state. * `wp agent-toolbelt run [--input=] [--porcelain]` — run one; the dry-run/confirm flow applies exactly as over REST. * `wp agent-toolbelt log [--limit=20] [--ability=]` — read the audit log. = Good to know = * On sites with a static page cache, visitors may keep seeing cached pages while maintenance mode is on — purge the page cache first (the agent can call purge-all-caches) if the maintenance page must be visible immediately. * The only HTTP requests the plugin ever makes are the post-update health checks — to your own site. **Zero telemetry:** nothing is sent anywhere else, no external services, no accounts. * Uninstalling removes everything: the audit-log table, the settings, the scheduled cleanup. == Frequently Asked Questions == = Is it really safe to let an AI agent update plugins? = "Safe" here means: previewed, confirmed, backed up, health-checked, and rolled back automatically if the site breaks — with an audit trail. That's more protection than a human clicking "Update now" gets. It's still a change to your site, which is why the ability ships disabled and you must enable it deliberately. = What stops a prompt-injected agent from wrecking my site? = Three layers: the destructive ability is off by default; if you enabled it, execution needs a fresh one-time confirm token from a prior dry-run of the same request (a single malicious instruction can't do both steps blindly); and every call needs an authenticated administrator — content on your pages can't call anything by itself. The honest part: if your agent has admin credentials and is fully compromised, no plugin can save you — the toolbelt's job is to make the destructive path narrow, slow, and visible. = Why does update-plugin refuse single-file plugins like Hello Dolly? = WordPress core's temporary-backup mechanism skips plugins that live in a single file, so there would be no backup to roll back to. Rather than update without a safety net, the ability refuses and tells the agent to use wp-admin or WP-CLI instead. = Does it work on multisite? = Everything except plugin updates. Network-wide update semantics deserve their own careful design, so on multisite the update ability refuses with a clear reason instead of guessing. = Can visitors or logged-out agents see or call the abilities? = No. Every ability requires a logged-in user with `manage_options` (updates also need `update_plugins`). Anonymous REST calls get a 401, and the abilities don't even appear in the listing for unauthorized users. = How do I turn everything off in an emergency? = Two ways: untick abilities on the Tools → Agent Toolbelt page (they unregister instantly), or add `define( 'AGENT_TOOLBELT_DISABLED', true );` to wp-config.php — the kill switch unregisters everything: abilities, REST exposure, and the WP-CLI command. = Why don't I see maintenance mode when I turn it on? = If you are logged in as an administrator, that's on purpose — administrators always see the normal site. Open a private/incognito window to see what visitors get. Otherwise, a static page cache is probably serving visitors a cached copy: purge the page cache (there's an ability for that) and reload. Maintenance mode always auto-expires, so a forgotten "on" can never lock the site permanently. = Does the plugin send any data anywhere? = No. The only HTTP requests it makes are health-check requests to your own site after a plugin update. There is no telemetry, no phoning home, no external service. == Screenshots == 1. The ability checklist with risk badges — enable exactly what your agent may do. 2. The audit log — every operation with caller, user, input digest and result. 3. A dry-run → confirm-token → execute round-trip for a safe plugin update. == Changelog == = 1.0.0 = * Initial release. * Six abilities: site-status, purge-all-caches, flush-rewrite-rules, maintenance-mode (auto-expiring), read-audit-log, and update-plugin (opt-in) with backup, loopback health check and automatic rollback. * Guardrails: dry-run on every mutating ability, one-time confirm tokens for high-risk execution, per-ability enable/disable (disabled = invisible), audit log with 90-day/2,000-row retention, kill-switch constant. * Surfaces: WordPress Abilities API (REST `wp-abilities/v1`, MCP-ready), WP-CLI (`wp agent-toolbelt`), and an admin page under Tools. == Upgrade Notice == = 1.0.0 = First release.