Review the audit log for agent traffic

MaintenanceIntermediate~10 minUpdated

Before you start

Plugin version 1.7.4 or newer for the is_agent_identity flag. The Activity Log read requires the manage-options capability, so run this from an administrator connection, not from a least-privilege agent user.

The Activity Log records a lot, which is its virtue and its problem. Your own admin work is in there next to the agent’s, in one stream, and the question you usually want answered is specifically about the agents: what have they been doing, which abilities are they leaning on, and is any of it being refused.

Version 1.7.4 put a flag on every row that makes the split possible. This prompt uses it to give you an agent-only view of your own log. It reads and reports, nothing else.

The prompt
I want to know what the agents on this site have been doing. Read only, change
nothing.
Read the Activity Log newest first, 200 rows a page, and keep paging until the
created_at time (it is UTC) is older than [seven days ago]. There is no date
filter on this read, so that is the only way to bound it. If it takes more than
five pages, stop and tell me how far back you got.
Set aside rows that are not tool calls: ability "(transport)", an ability
starting with "oauth:", "aafm/write-outcome", "aafm/activity-log-cleared",
"aafm/read-only-mode", "aafm/high-risk-abilities-unlocked",
"aafm/review-publish", "aafm/review-discard", any ability that does not start
with "aafm/" or "aafm-bridge/", any row whose detail starts with "Enabled ",
"Disabled " or "Blocked " (someone switching an ability on or off in wp-admin),
and any denied row with no acting user. Count those on one line.
Leave them out of everything below.
Every other row carries an is_agent_identity flag. Split on it: agent traffic
in one group, human traffic in the other, and tell me the count on each side
before you go any further.
For the agent rows, group them by ability and give me the counts, busiest
first. Then group the same rows by status, so I can see how many succeeded,
errored, were denied, or are still marked started.
Show me every denied and every errored row in full: the ability, the acting
user, the timestamp, and whatever detail the log recorded.
Finish with a short read on the pattern. Is any single agent identity behaving
differently from the others, reaching for abilities the rest do not touch, or
collecting denials nobody else is getting? Say what you saw, and say plainly if
nothing stands out.

Why this is safe to run

One ability, and it is a read. The Activity Log reports history that has already happened, and reading it cannot rewrite a row of it.

The flag is what makes the split trustworthy. Before 1.7.4 you could filter by username and hope that told you something, but usernames answer the wrong question: they identify the account, not the kind of connection the call came through. The is_agent_identity boolean reflects either the per-user application-password marker that already existed or a per-OAuth-client flag set on the Connection tab, so a connection you deliberately created for an agent is marked as one either way, and the log says so on every row.

What the agent cannot see, and where to look instead

The read your agent runs is narrower than the Activity Log tab in wp-admin, and 1.9.0 made the gap wider. The ability filters on status and on one exact tool name, and nothing else. It returns the ability name, status, acting user, flag, argument keys, timestamp and an identifier-only detail.

Four things are only on the tab:

  • Why a call was denied. Version 1.9.0 records the reason, such as “key is not on the allowlist”, in the log. The ability leaves it out of the detail it returns, so an agent holding an administrator credential cannot map your allowlist.
  • Connection name, source IP and duration. The tab shows all three on every row, and the CSV export carries them.
  • Filters by user, connection, plugin, date and text, plus a 7-day summary card and a Live view.
  • Alert settings. Rows about your notification settings are left out of what the agent reads.

So use this prompt to find the pattern, then open the Activity Log tab to find the cause. Click Denied, add the tool or user from your agent’s answer, and read the Detail column.

The log is also bounded by your retention setting, 30 days by default, so a window longer than that comes back short.

The last thing is who runs it. The read is gated behind manage-options, a capability a well-scoped agent user has no business holding, since an agent that could read the audit log could read the record of every other agent too. So this one is an administrator’s prompt, run from your own connection.

Already connected? Skip the paste. From an admin connection, ask your agent for the “review the audit log for agent traffic” recipe, or just ask what the other agents have been up to this week, and it runs the same split against your own log.

How it works

  1. Read the Activity Log newest first, paging until the rows pass the start of your window.
  2. Set aside the rows that are not tool calls, then split the rest on the is_agent_identity flag.
  3. Group the agent rows by ability and by status.
  4. Pick out anything denied or errored and read those separately.
  5. Report the pattern, and name any agent identity behaving unlike the others.

Questions

What makes a row count as agent traffic?
The is_agent_identity boolean, added to every log row in 1.7.4. It is true when the caller is flagged as an agent identity, which comes from one of two places: the per-user application-password marker that already existed, or a per-OAuth-client flag you set on the Connection tab. So a connection is marked at whichever level it was created, and the log tells you which side of that line each call came from.
Why can't I just filter by username?
You can, and before 1.7.4 that was the only option, but it answers a different question. A username tells you which account was used; the agent flag tells you whether that call came through a connection you set up for an agent. The same account can be both, and an OAuth client can be marked as an agent without changing anything about the user behind it. The flag is the one that survives that.
Will the log tell me what the agent actually wrote?
No, on purpose. The log keeps identifier-only values: the ability name, the status, the acting user, the argument keys that were passed, the timestamp, and a short detail such as an object id, a slug, or an error code. It never stores the argument values, the content itself, or file paths. So it will tell you that a post was updated and which one, not what the new text said.
Can the agent tell me which connection or IP address a call came from?
No. Since 1.9.0 the Activity Log tab shows each call's connection name, source IP address and duration, but the ability your agent reads does not return them. Open the tab, filter by user, connection or tool, and set a date range if the log is large. Behind a proxy or CDN the IP shown is the proxy's address.
Why does this need an admin connection?
The Activity Log read is gated behind the manage-options capability, which a properly scoped agent user should not hold. That is deliberate: an agent that could read the audit log could read the record of every other agent's activity. Run this one from your own administrator connection.