Skip to main content
Once you’ve connected an AI agent, it gets a fixed set of tools — the specific actions it’s allowed to take in Paige. This page lists all twenty-six. Two things shape what an agent can actually do with them:
  • Permissions. Every tool except one needs a scope. If the credential doesn’t carry that scope for the project it’s working on, the tool fails with insufficient_scope. See Scopes.
  • The project. One connection can cover several projects, so the agent names the project on every tool that changes something. Read-only tools fall back to your default project.
These tools are a thin wrapper over the Paige API. Anything an agent can do here, you can do yourself with an HTTP call — and every limit, permission check, rate limit and guardrail is enforced in the same place for both.

Projects

It’s the first thing a well-behaved agent calls, and the only tool that needs no permission at all. It keeps working even when the default project is paused, so an agent can always find its way back to a project that works.
If an agent says it can’t reach a project you’ve just added, ask it to look up your projects again. Adding a project takes effect immediately and never requires reconnecting.

Conversations and messaging

send_message sends a real WhatsApp message to a real person the moment the agent calls it. There is no draft step and no undo. Grant messages:send only to agents you want messaging your customers, and say who you mean rather than leaving it to guess.

Code and deploying

This is the group that lets an agent change your bot.

build_code versus edit_file

Both write code. They’re for different situations:

build_code

When you want Paige to work out the change. “Add an opening-hours reply”, “make the booking flow ask for a phone number”. It runs Paige’s Code Agent — the same one in your chat sidebar, with its knowledge of the project scaffold, your connectors, and the platform’s rules.

edit_file

When you already know the exact edit. A one-line fix, a copy change, a value you want swapped. It’s deterministic, fast, and doesn’t cost credits.
build_code uses credits. It runs a real AI build, so it draws down the project’s balance like any other Code Agent build. When the project is out of credits it fails with insufficient_credits rather than half-building something. edit_file doesn’t cost credits.
The reason build_code exists is quality. Without it, an outside agent writes Paige code from the outside, guessing at conventions it’s never seen. With it, the outside agent describes the outcome and Paige’s own agent writes the code — the same house standard you’d get from the chat sidebar.
Some files are off-limits to edit_file — the platform wiring that keeps a bot running. A write to one of those fails with protected_file. See API conventions. Flow JSON is off-limits too, for a different reason: it has its own tools.

Flows

A well-behaved agent reads before it writes. update_flow addresses a flow by name, an unknown name is rejected, and list_flows returns the only valid names — so an agent that lists first never invents one, and an agent that reads first describes a change to the flow that actually exists rather than to an assumed structure.
Read flows is a newer permission than Build flows. A connection created before it existed may be able to write flows but not read them, which shows up as insufficient_scope on list_flows. Grant Read flows for that project under Settings → API → Connected agents — no reconnect needed.
Every flow change goes through Paige’s flows sub-agent. There’s no hand-edit path — an agent that tries to edit a flow’s JSON as a file is refused. Flow definitions are strict, and a malformed one is rejected by Meta rather than degrading gracefully. See Flows.

Contacts and audiences

preview_segment saves nothing, but the agent still has to name the project when it calls it. That’s deliberate — Paige requires the target to be named on anything that isn’t a plain read, so a count is never quietly taken against the wrong project.

Broadcasts

An agent can never send a broadcast

assemble_broadcast never sends. It always leaves the campaign in pending approval, and there is no tool to send, launch, approve, cancel, or retry one. A campaign only goes out when a human approves it in the Broadcasts tab of the dashboard.This isn’t the agent being polite about it. The rule lives in Paige’s own platform layer, so it holds for a connected agent, for a raw API call, and for anything else that ever talks to Paige. Asking an agent to “just send it” cannot work.
An agent that could send a promotion to four thousand people because it misread a sentence is not a good agent. So the agent does the tedious part — the audience, the template, the variables, the schedule — and the decision stays yours.
This is a different surface from the Broadcasting Agent. Paige’s own Broadcasting Agent, in the chat sidebar of the Broadcasts tab, has its own set of tools including assemble_campaign — and it can also draft and submit templates, list button taps, and update segments, which a connected agent can’t. The two are separate: assemble_broadcast is what an outside agent gets over MCP; assemble_campaign is what Paige’s built-in agent uses. Both are held for your approval, and neither can send.

Your bot’s tables

Your bot’s own tables — bookings, orders, stock, whatever it keeps — are reachable too. The same data you see in Tools → Database, read and written programmatically.
A change or a delete must always name the rows it applies to. There’s no “update everything” and no “delete everything” — an unfiltered write is refused rather than run. And “contains”-style matching can find rows but never change or delete them, because a loose match can quietly cover a whole table while looking narrow. Read the rows first, then change them by their id.
This only ever reaches your own tables. Contacts, conversations, messages, execution logs, and broadcast records are Paige’s, not yours to open this way — an agent that tries gets platform_table_forbidden. Those have their own permissions, so giving something access to your bookings table never quietly hands it every customer’s phone number and chat history.Deleting is its own separate tool, so an agent has to ask for it deliberately and you can see it coming. It’s permanent — there’s no undo.

Media

An agent uploads by giving Paige a public URL (source_url, up to 20 MB) or by sending the bytes inline as base64 (up to 8 MB decoded). The multipart upload the API offers isn’t reachable over MCP, which speaks JSON only.
upload_media spends credits on an image. One AI vision call writes the asset’s description. Tell the agent to pass describe_image: false when you only want the file stored and sendable — it costs nothing then, and the slug works exactly the same. Non-image files use no AI at all.
The slug is the durable value — never store a media_id. media_id is WhatsApp’s id for its copy of the file and only a point-in-time snapshot: it expires after about 30 days and Paige replaces it automatically. An agent that writes a media_id into one of your table rows has written a value that will quietly stop working. It should store the slug and let the bot resolve it at send time. See Storage.
A slug is never overwritten. Uploading under a name that’s taken returns 409 SLUG_EXISTS rather than replacing a file your live bot is already sending — which is why a good agent calls list_media before upload_media.

Permissions are per project

One connection can cover several projects, and each project carries its own permissions. A project can’t borrow a scope from a sibling on the same connection — being allowed to edit code in one project never implies it in another.So when an agent tells you it doesn’t have permission, the fix is usually specific: open Settings → API → Connected agents, find the agent, and grant that permission for that project. See Connect an AI agent.

Choosing what to grant

Grant the least that gets the job done. You can change it later without reconnecting anything.
Some scopes have no MCP tool behind them — there’s no tool for templates, no tool for setting a conversation’s state, and no tool for webhooks. Granting templates:manage or webhooks:manage to a connected agent gives it nothing it can use. Those live in the API, for code you write yourself. A few tools are one-way too: an agent can upload and list media, but reading an asset’s bytes back and deleting one stay API-only.