Skip to content
WP Visibility

Working with an assistant guide

Build a WordPress Assistant Permission Matrix for One SEO Job

List the reads and writes one SEO job needs, give a dedicated user the smallest role that covers them, and test both allowed and denied calls on every route the password reaches.

Published

On this page

Give an SEO assistant the smallest WordPress role that covers one named job, then prove it. Write down the reads and writes the job needs, create a dedicated user with the matching role, and run one allowed call and one denied call through every route the credential can reach, at minimum the plugin’s assistant tools and WordPress’s own REST API. The result is a one-page matrix that says what the assistant can do, what it cannot, and what it can do outside any review step.

The reason to test instead of assume: an Application Password is not a restricted key. WordPress describes it as a password tied to a specific WordPress user account, meant for API authentication, such as the REST API and, where enabled, XML-RPC, rather than browser logins (Application Passwords, checked September 27, 2026). The core team’s Application Passwords integration guide, checked September 27, 2026, lists scoping a password to limit its access as future work. Whatever the user’s role allows over the REST API, the password allows.

Define the reads and writes the job needs

Pick one job and name it precisely. The worked example here (illustrative) is: “Propose new meta descriptions for the service pages on garden.example.”

Then list every operation that job requires, and nothing else:

Operation Why the job needs it WP Visibility 2.10.3 ability Capability it checks
Read the page body To draft from the page’s own text serialize-content edit_post on that page
Read current SEO fields To see the existing description get-post-seo edit_post on that page
Propose a description The job itself update-post-seo edit_post on that page
Audit one page Optional, to check length audit-post edit_post on that page

The job does not need settings, redirects, bulk updates, the site audit, the review queue, or the activity log. In 2.10.3 all of those check manage_options.

edit_post is a meta capability: WordPress resolves it per post into the primitive capabilities for that post type and state (map_meta_cap(), checked September 27, 2026). For pages, that means the page capabilities. WordPress’s Roles and Capabilities article, checked September 27, 2026, lists edit_pages and edit_others_pages under Editor and not under Author, and manage_options under Administrator.

From job to tested authority. Name the job: List each read and write it needs. Pick the role: Smallest default or custom role that fits. Test each route: One allowed and one denied call per route.
The order for scoping one assistant credential. The role, not the prompt, sets what the Application Password can reach, including routes outside the review queue.

Choose the smallest role that covers it

Read the job’s capability column against the default roles:

Role Can this example job run? What else the role allows
Contributor No: has no page capabilities Write and edit its own unpublished posts
Author No: has no page capabilities Publish and edit its own posts, upload files
Editor Yes Publish and manage all posts and pages, including other users’
Administrator Yes Everything on the site, including settings, plugins, and users

Editor is the smallest default role for this job. If the job only touched blog posts written by the assistant’s own user, Author would do; an Author cannot edit other users’ posts. A custom role with a narrower set of capabilities is possible with a role management plugin (the same article lists several); test it the same way.

Also note what the role adds that the job does not need. An Editor can publish, edit, and delete any post through WordPress’s own editor and REST API. That authority comes with the role and does not pass through the plugin’s review queue.

Create the user, assign the role, and add an Application Password named after the client. Create the Application Password Your Assistant Signs In With has the steps.

Test the allowed operations

Run these against a staging copy of the site first. Replace the user, password, host, and IDs.

Confirm the user and role WordPress sees for this credential:

curl -s -u 'seo-agent:xxxx xxxx xxxx xxxx xxxx xxxx' \
  'https://staging.garden.example/wp-json/wp/v2/users/me?context=edit'

The response’s roles and capabilities fields are the authority to record; the REST API users reference, checked September 27, 2026, documents both in the edit context.

Then, with the Agent module on (the endpoint does not exist while it is off), call one allowed read through the assistant tools:

curl -s -u 'seo-agent:xxxx xxxx xxxx xxxx xxxx xxxx' \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get-post-seo","arguments":{"post_id":42}}}' \
  https://staging.garden.example/wp-json/wp-visibility/mcp

Expect the page’s SEO fields. Then, with the Autopilot module on and Assistant changes left at Hold for my review (the default), ask the assistant, in the client, to propose one description, and confirm a proposal appears in WP Visibility → Review queue. With Autopilot off, or with that setting at Apply immediately, the same call writes the description directly.

Test the denials on every route

A permission matrix without denials is a guess. Pick calls the job must not be able to make and confirm each one fails.

Through the assistant tools, call an administrator ability:

curl -s -u 'seo-agent:xxxx xxxx xxxx xxxx xxxx xxxx' \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"get-settings","arguments":{}}}' \
  https://staging.garden.example/wp-json/wp-visibility/mcp

An Editor should get a tool result marked "isError": true rather than settings, inside an HTTP 200 response. From the built-in endpoint its text starts with ability_invalid_permissions, the refusal WordPress core’s Abilities API returns when an ability’s permission check fails (WP_Ability source, checked September 27, 2026).

Through core REST, try a read that needs manage_options:

curl -s -o /dev/null -w '%{http_code}\n' -u 'seo-agent:xxxx xxxx xxxx xxxx xxxx xxxx' \
  https://staging.garden.example/wp-json/wp/v2/settings

An Editor should get 403: the route checks manage_options (get_item_permissions_check(), checked September 27, 2026), and WordPress answers a signed-in user who fails a check with 403 (rest_authorization_required_code(), checked September 27, 2026). An Administrator gets 200, which is the point: the same password that holds proposals in the queue can read and change site settings directly.

Do not test destructive routes on a live site. On staging, if you want to see the authority outside the queue, create and then trash a throwaway draft through /wp-json/wp/v2/posts with the same credential. If that succeeds, the credential can change content without any proposal.

Document authority outside the proposal path

Record the results in a matrix like this one (illustrative results; fill in your own):

Operation Route Expected Observed Held for review?
Read page SEO fields Assistant tools Allowed No, reads are not held
Propose a description Assistant tools Allowed Yes, with Hold for my review
Read plugin settings Assistant tools Denied Not applicable
Read site settings Core REST /wp/v2/settings Denied Not applicable
Create or edit a post Core REST /wp/v2/posts Allowed for Editor No
Publish a post Core REST or editor Allowed for Editor No

The “Held for review?” column is where most assumptions break. In WP Visibility 2.10.3, only seven of the plugin’s write abilities, update-post-seo among them, are held as proposals (others, such as create-draft, run directly), and only with the Agent and Autopilot modules on and Assistant changes set to Hold for my review. Core WordPress routes the user can reach are not held and are not recorded in the plugin’s activity log. WordPress’s Application Passwords section on the user profile shows usage metadata such as last used time and IP, per the Application Passwords documentation above, which helps confirm which credential was active.

Add three lines under the matrix: who owns the credential, when it should be revoked, and how to stop it quickly. Pause all agent access in the settings (or Pause agent on the Review queue) stops the plugin’s tools; revoking the password ends the connection everywhere. Stop the Assistant Now covers both. Editors cannot pause the assistant through its tools in 2.10.3, because pause-agent checks manage_options, so the pause is an administrator’s action in this setup.

Checklist

  • One job named, with its operations and capabilities listed.
  • Smallest role chosen, and the extra authority it grants written down.
  • Dedicated user and a named Application Password.
  • users/me?context=edit output saved.
  • At least one allowed and one denied call per route, run on staging.
  • Matrix records which operations are held for review and which are not.
  • Owner, revocation date, and stop procedure written under the matrix.

For the general case for scoping access, see How to Control an Assistant’s SEO Changes.

Read next

WordPress SEO with your own assistant.

WP Visibility is $99 a year for unlimited sites, client sites included, with a 30-day refund. Use its SEO tools in WordPress or connect a supported assistant. Read how proposal review and permissions work.