Agent conventions
These rules hold for every tool. They ship inline in each tool’s advertised description too, so an agent sees them at call time — but they are worth reading once, in one place.
userErrors mean the write did not happen
A non-empty userErrors array is a successful tool result — isError absent or false —
reporting a domain rejection, not a crash. Read each entry’s field (an array of path segments, for
example ["input","name"]) and message, correct the input, then retry or ask the person.
{
"collection": null,
"userErrors": [
{ "field": ["input", "name"], "message": "has already been taken" }
]
} isError: true is reserved for something else entirely: authentication challenges,
workspace-authorization misses, argument-schema validation failures, rate-limit throttles, unknown
tools, and redacted unexpected server errors ("Tool execution failed").
Retry discipline
On a timeout or transport error where you cannot tell whether the write landed, read first with
the tool that verifies it, before retrying. Every write tool’s description names that read tool; a
delete is confirmed when the read returns null.
Tools annotated idempotentHint: true may be retried directly — a duplicate apply converges on the
same state.
Destructive tools
The delete* tools set annotations.destructiveHint: true. Their descriptions state what is
destroyed, what survives, and that the delete is irreversible. Confirm with the person — echoing the
entity id back to them — before calling one.
Deleting a saved view or Collection never deletes content: the items survive and simply lose that one tag or grouping. No other tool spends money or destroys creator data.
Async ingest
uploadItemFromUrl and refetchEngagementBulk are asynchronous. A success payload means
enqueued, not done. Poll the verify tool named in the description for the eventual result, and do
not expect fresh data in the write response.
Concise responses
Every list read tool accepts responseFormat, either "detailed" (the default) or "concise".
Concise trims each item node to the fields an agent needs for listing, filtering, and ranking — id,
originalUrl, provider, type, takenAt, caption, a minimal socialProfile, and
currentEngagement. On searchItems it also keeps creator { id }, the join key for creator-level
diffs such as differencing a campaign roster against that campaign’s posters; matching on
accountName is unsafe there because a workspace can hold two creator records sharing a handle.
Prefer concise while you are narrowing a result set; switch to detailed only when you actually need the fuller shape. It is materially cheaper in context, and the trimmed fields are a strict subset — nothing changes shape between the two modes.
Enum values are uppercase, and encode more than you expect
Every enum value is UPPERCASE. Item types encode platform and format together, which is the most
common source of empty result sets.
View filters — clone, do not compose
For content view, Social Profile view, and Creator View create and update, filters is an opaque
JSON blob that is not validated on write. Strongly prefer cloning an existing view’s filters
(fetch it with the matching get* tool) over composing one from scratch.
Auditing
Every write emits exactly one structured audit event, whatever the outcome, carrying the principal
identity, the auth strategy, the MCP client name, the result, and any userErrors.