Skip to content

Feature : Site Agent Experiment - #1214

Open
Vrishabhsk wants to merge 1 commit into
WordPress:developfrom
Vrishabhsk:feature/site-agent-develop
Open

Vrishabhsk wants to merge 1 commit into
WordPress:developfrom
Vrishabhsk:feature/site-agent-develop

Conversation

@Vrishabhsk

@Vrishabhsk Vrishabhsk commented Oct 22, 2026 •

Copy link
Copy Markdown

What?

Closes #189

Adds an opt-in Site Agent experiment under Tools → Site Agent that maps natural-language requests to reviewed WordPress Abilities, with approval-gated writes and an audit trail.

Why?

Issue #189 asks for a conversational admin agent that can perform WordPress actions with strong security, permissions, and auditability from the start, and that is opt-in and disabled by default.

This PR takes an abilities-first approach. Instead of describing every action twice (once as a REST resource table, once as a custom action class), the agent uses ordinary WordPress Abilities as the action layer. Each action keeps its own input schema, permission callback, validation, and execution hook. The agent adds only three things:

  1. A reviewed allowlist of abilities.
  2. A propose-then-approve boundary for anything that is not read-only.
  3. An audit trail.

This keeps the implementation substantially smaller than the earlier draft while preserving the security properties in the issue.

How?

Experiment and gates

  • Site_Agent registers the screen, REST routes, abilities, and audit listener only when the experiment is enabled.
  • The experiment toggle and the write gate both default to false.
  • The screen and REST routes require manage_options by default; sites can narrow or lower this with wpai_site_agent_capability.

Abilities as actions

Ability Type Capability Notes
ai/site-agent-read-site Read Section-dependent Environment, recent posts/pages, installed plugins, or a fixed settings allowlist.
ai/site-agent-create-draft Write edit_posts / edit_pages Creates a draft owned by the current user. Never publishes.
ai/site-agent-update-post Write edit_post Title, content, excerpt, draft/pending status. Cannot publish, unpublish, change author, or change type.
ai/site-agent-update-setting Write manage_options Site title or tagline only.

Read sections use their own capability (manage_options, edit_posts, edit_pages, activate_plugins) and filter object reads through read_post. The settings section never exposes URLs, email addresses, roles, or arbitrary options.

Proposal and approval flow

  1. The model receives only the reviewed catalog.
  2. An ability annotated readonly => true runs immediately.
  3. Any other ability is treated as a write. The exact ability name and arguments are stored in a user-scoped, conversation-bound transient.
  4. The transcript shows the exact stored values. Nothing has run.
  5. The browser sends only the proposal ID and conversation ID on approval.
  6. The server re-checks the proposal owner, conversation, expiry, pending status, and the ability's own check_permissions() with the stored arguments.
  7. The server calls $ability->execute( $stored_args ) as the current user. WordPress validates the input, sanitizes it, checks permissions again, and fires its hooks.
  8. The proposal is marked used and a result note is appended to the conversation.

Proposals are single-use and expire after 30 minutes. Conversations expire after two hours.

Audit

  • Every executed ability is logged through wp_after_execute_ability.
  • Proposals, approvals, denials, and declines are logged explicitly.
  • Rows use the new site_agent log type, with the ability name as the operation and the phase in context.
  • No post bodies, setting values, credentials, or package URLs are logged.
  • External audit plugins can listen to wpai_site_agent_action.

UI

  • A minimal React screen with a transcript, composer, and proposal card.
  • The proposal card renders the exact stored arguments and the Approve / Decline actions.
  • When the write gate is off, the screen clearly says it is read-only and links to the settings page.
  • No streaming in this cut; model rounds are buffered.

What is intentionally not included

  • Publishing, trash, media uploads, user writes, plugin installation, core/plugin/theme updates, theme switching, and export.
  • Each is a reviewed ability away and can be added without changing the agent loop.

Use of AI Tools

AI assistance: Yes
Tool(s): Ollama
Model(s): Deepseek-v4.1-flash:cloud
Used for: Initial implementation, the refactor to the abilities-first design, tests, documentation, and manual verification. The final code, tests, and security behaviour were reviewed and edited by the author.

Testing Instructions

Automated

npm ci
composer install
npm run build
npm run typecheck
npm run test:php

Run the Site Agent e2e spec with the AI plugin active in the wp-env test site:

npx wp-scripts test-playwright --config tests/e2e/playwright.config.ts \
  tests/e2e/specs/experiments/site-agent.spec.js

Validated locally:

  • PHP suite: 1937 tests, 5537 assertions, 42 skipped.
  • Site Agent suites: 35 tests across the abilities, agent loop, and experiment/gates.
  • phpcs and phpstan clean for the new backend code.
  • TypeScript typecheck and production build pass.

Manual

  1. Open Settings → AI, open the settings menu, and enable Advanced settings.
  2. Enable Site Agent. Leave Allow write proposals off.
  3. Open Tools → Site Agent.
  4. Ask “What version of WordPress and PHP am I running?” and confirm a real answer from ai/site-agent-read-site.
  5. Ask “Create a draft titled ‘Site Agent test’.” and confirm the assistant says it cannot while writes are off.
  6. Enable Allow write proposals, reload, and ask again. Confirm a proposal card shows the exact title, type, and status, and that no draft exists yet.
  7. Click Decline and confirm nothing was created.
  8. Ask again, click Approve, and confirm the draft appears under Posts → Drafts.
  9. Ask to change the tagline and confirm the proposal shows blogdescription and the exact new value. Approve and verify under Settings → General.
  10. Open Tools → AI Request Logs, filter by site_agent, and confirm proposal/execute/approval/decline rows exist without content or secret values.

I also tested the above end-to-end on a real WordPress 7.1.3 site with a Google connector, including the read, proposal, approve, decline, settings update, and audit paths.

Screenshots or screencast

Screenshot 2026-10-22 at 1 27 39 PM Screenshot 2026-10-22 at 1 31 46 PM Screenshot 2026-10-22 at 1 32 44 PM

Changelog Entry

Added - New Site Agent experiment: a conversational assistant under Tools that reads site information and proposes changes through reviewed WordPress Abilities. Every write is stored as a server-side proposal and executes only after approval. The experiment and its write gate are disabled by default.

Open WordPress Playground Preview

Adds a conversational assistant under Tools that reads site information
and proposes site changes. Actions are ordinary WordPress Abilities, so
each keeps its own schema, permission callback, validation, and execution
hook. The agent adds a reviewed allowlist, a propose-then-approve boundary
for writes, and an audit trail.

Write proposals are user-scoped, conversation-bound, single-use, and
expire after 30 minutes. The experiment and its write gate are disabled
by default.

See WordPress#189.
@Vrishabhsk
Vrishabhsk requested a review from a team October 22, 2026 08:09
@Vrishabhsk
Vrishabhsk requested a review from jeffpaul as a code owner October 22, 2026 08:09
@github-actions

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs.

Unlinked Accounts

The following contributors have not linked their GitHub and WordPress.org accounts: @Vrishabhsk.

Contributors, please read how to link your accounts to ensure your work is properly credited in WordPress releases.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Unlinked contributors: Vrishabhsk.

Co-authored-by: jeffpaul <jeffpaul@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.


Props Bot commands

You can trigger Props Bot actions by commenting on this PR:

  • @propsbot add <username> to give props to a GitHub user. Requires write access.
  • @propsbot remove <username> to leave a user out of the props. Requires write access.
  • @propsbot refresh to refresh this list. Adding the props-bot label works too.

@codecov

codecov Bot commented Oct 22, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 64.54155% with 495 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.48%. Comparing base (2e930f3) to head (26b187f).

Files with missing lines Patch % Lines
includes/Abilities/Site_Agent/Read_Site.php 62.74% 95 Missing ⚠️
...ncludes/Experiments/Site_Agent/REST/Controller.php 16.16% 83 Missing ⚠️
...des/Experiments/Site_Agent/Prompt_Model_Client.php 0.00% 70 Missing ⚠️
includes/Experiments/Site_Agent/Admin_Page.php 5.17% 55 Missing ⚠️
includes/Experiments/Site_Agent/Agent.php 86.57% 38 Missing ⚠️
includes/Abilities/Site_Agent/Update_Post.php 74.48% 37 Missing ⚠️
...xperiments/Site_Agent/Function_Calling_Support.php 0.00% 22 Missing ⚠️
includes/Experiments/Site_Agent/Proposal_Store.php 67.16% 22 Missing ⚠️
includes/Experiments/Site_Agent/Site_Agent.php 65.51% 20 Missing ⚠️
...udes/Experiments/Site_Agent/Conversation_Store.php 65.30% 17 Missing ⚠️
... and 5 more
Additional details and impacted files
@@              Coverage Diff              @@
##             develop    #1214      +/-   ##
=============================================
- Coverage      84.26%   82.48%   -1.78%     
- Complexity      3723     4084     +361     
=============================================
  Files            148      164      +16     
  Lines          14099    15493    +1394     
=============================================
+ Hits           11881    12780     +899     
- Misses          2218     2713     +495     
Flag Coverage Δ
unit 82.48% <64.54%> (-1.78%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@jeffpaul jeffpaul added this to the 1.6.0 milestone Oct 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Explore an admin Site Agent for executing WordPress actions

2 participants