Knowledge & tools

Meta Ads tool

The Meta Ads tool lets an agent manage Meta advertising through the Marketing API — discover ad accounts, create and edit campaigns, ad sets, creatives and ads, build and target audiences, upload creative assets, pull performance insights, and pause, archive or activate objects. Set it up once as a tool configuration with a token, then assign it to a bot.

This tool spends money and deletes objects. Setting an object's status to ACTIVE can start real ad spend. Give it a token scoped to the ad accounts it should manage, and read Safety in autonomous runs before scheduling a bot that touches ads on its own.

Mental model

One action per call. CRUD actions take an object_type (campaign, ad set, ad, creative, audience). Because Meta's ad objects have hundreds of nested fields, write bodies go in a flexible params object that passes straight through to Meta rather than being flattened into fixed arguments — so anything the Marketing API accepts, the agent can send. One access token drives one or many ad accounts.

Budgets are always in the account currency's minor units (cents) — a $10.00 daily budget is 1000.

What it can do

The agent chooses an action per call. Available actions:

  • Accountslist_ad_accounts, get_ad_account to discover and inspect accounts.
  • CRUDlist, get, create, update, delete on object_type = campaign / adset / ad / adcreative / custom_audience.
  • Statusset_status to move an object to ACTIVE / PAUSED / ARCHIVED.
  • Audiencescreate_lookalike (a lookalike audience) and manage_audience_users (add/remove hashed members).
  • Targetingsearch_targeting (interests, behaviours, locations) and estimate_reach (audience size for a targeting spec).
  • Insightsget_insights for performance metrics (by level, with breakdowns and a date range).
  • Assetsupload_image (via URL → bytes) and upload_video (via file URL); generate_preview renders a creative preview iframe; delete with object_type: image / video removes an uploaded asset by hash / video id.

Configuration

The tool has four fields:

  • Access token (required) — a Meta token with ads_management (plus ads_read). A long-lived System User token from Business Manager is best. Stored encrypted and never shown again after saving. See How to get a token.
  • Ad account ID (optional) — e.g. act_1234567890 (the act_ prefix is optional). Set it to lock this configuration to one account; leave it blank for multi-account mode.
  • Default Page ID (optional) — a Facebook Page ID auto-filled into ad creatives when the agent doesn't supply one.
  • Graph API version (optional) — the Marketing API version, e.g. v23.0.

How to get an access token

Meta changes this UI periodically, so treat the concepts as authoritative and the exact button labels as approximate.

A long-lived System User token from Business Manager is the right credential for production — it doesn't expire the way a personal user token does.

  1. In Business Manager → Business Settings → System Users, create a System User.
  2. Assign the target ad account (and the Page, if the agent will build creatives) to that System User.
  3. Generate a token with ads_management, ads_read, and business_management.
  4. Paste the token into the tool's Access token field and save.

Verify a token's scopes any time with Meta's debug_token endpoint.

The main blocker: your Meta app needs Advanced Access to ads_management, ads_read and business_management. Advanced Access requires App Review and Business verification. Plan for this — it's the step that most often holds up going live.

Single-account vs multi-account mode

  • Single-account — set the Ad account ID. The bot is locked to that account and can't act on any other. Safest for an account-specific bot. When pinned, the account is removed from the agent's parameter set entirely.
  • Multi-account — leave the Ad account ID blank. One configuration then drives every account the token manages; the agent supplies the account per action and can call list_ad_accounts to discover them.

You can also create multiple separate configurations (one per account) — fully supported; each just needs a distinct name.

Building a campaign

A working ad is a small hierarchy: campaign → ad set → creative → ad. Each step is a create call with the object's fields in params.

  1. Campaigncreate with object_type: campaign. Objectives are the ODAX OUTCOME_* family (e.g. OUTCOME_TRAFFIC, OUTCOME_LEADS). Campaign create needs is_adset_budget_sharing_enabled and special_ad_categories (an empty array [] is fine when no special category applies).
  2. Ad setcreate with object_type: adset: the budget (in cents), schedule, optimization goal, billing event, and a targeting spec. Use search_targeting to resolve interests/behaviours/locations and estimate_reach to size the audience first.
  3. Creativeupload_image / upload_video for the asset, then create with object_type: adcreative. Give the creative an explicit image (picture or image_hash) — see the creative image gotcha.
  4. Adcreate with object_type: ad, referencing the ad set and creative. New objects are typically created PAUSED; use set_status: ACTIVE to launch when you're ready (this starts spend).
  5. Previewgenerate_preview renders the creative in an iframe so you can eyeball it before activating.

Audiences

  • Custom audiencescreate / update / delete with object_type: custom_audience, and manage_audience_users to add or remove members. Member data must be hashed before it's sent.
  • Lookalikescreate_lookalike from a source audience. A source needs to be large enough — Meta rejects a lookalike whose seed has fewer than ~100 people.
  • The first time you use custom audiences on an account you must accept Meta's custom-audience terms once at business.facebook.com → Audiences; until then, audience calls fail with a terms error.

Insights

get_insights returns performance metrics. Choose the level (account, campaign, ad set, ad), optional breakdowns (age, placement, and so on), and a date range. Large result sets paginate — the response carries an after cursor to fetch the next page.

Behavior to expect

  • Budgets are cents — all budgets and bid amounts are in the account currency's minor units. $10.00 = 1000.
  • Objectives are ODAX — use the OUTCOME_* objective family; the older campaign objectives are no longer accepted.
  • Campaign create requires is_adset_budget_sharing_enabled and special_ad_categories ([] is acceptable).
  • Creatives need an explicit image — supply picture or image_hash. If you don't, Meta scrapes the link's Open Graph image, which is unreliable and can fail the creative.
  • Activating spendsset_status: ACTIVE can start real ad spend immediately. Prefer creating objects PAUSED and activating deliberately.
  • Paginationlist and get_insights paginate via an after cursor.

Error reference

Failures come back with the real HTTP status and a rich Meta error envelope. The tool surfaces Meta's error_user_title / error_user_msg, so you'll see the operator-facing reason directly. Common ones:

  • "No Payment Method" — add a billing method to the ad account.
  • "Custom audience terms not accepted" — accept once at business.facebook.com → Audiences.
  • Lookalike "needs ≥100 people" — the seed audience is too small.
  • Permissions errors — the token is missing a scope or the app lacks Advanced Access; re-check with debug_token and see the token steps.

Safety in autonomous runs

Like any tool, the Meta Ads tool carries a safety classification (mutating / destructive / sends-data-externally) that governs scheduled or triggered (autonomous) runs. Because this tool deletes objects and can activate real spend, a new configuration is created with Mutating and Destructive switched on — so destructive actions are gated in autonomous runs unless the bot's "Allow destructive actions in autonomous runs" is enabled. Keep those on, and prefer the tighter control: scope the token (a single ad account, only the permissions you need) so a limit is enforced by Meta rather than only by an app-layer flag. Interactive chat is never gated by these flags.

Security

The access token is stored AES-encrypted at rest and is never returned by the API — the console shows only whether a token is set. Editing a configuration without retyping the token preserves the stored one, so you must retype it to replace it.