Meta Ads CLI skill
Use this skill when an AI agent needs to manage Meta ads from a terminal. The agent should use Meta's official CLI as the source of truth and should not reimplement the Marketing API unless the user explicitly asks for a lower-level workaround.
The command family is:
meta ads <resource> <action> [options]
Common resources include adaccount, campaign, adset, ad, creative, catalog, page, product-set, product-item, product-feed, dataset, and insights.
Install and verify
Use the pinned install spec in this skill. Do not install an unpinned CLI package for production ad-account work.
python3.12 -m pip install -r requirements-meta-ads-cli.txt
meta --help
meta ads --help
meta auth status
Expected credentials:
export ACCESS_TOKEN=<meta-access-token>
export AD_ACCOUNT_ID=act_<ad-account-id>
# Optional when needed by catalog/dataset/page/business operations:
export BUSINESS_ID=<business-id>
Use a token limited to the intended ad accounts and tasks. Use read-only access for reporting where possible. Use a token with write authority only for approved mutation work.
Default execution path
Use the guard script for all commands unless the user explicitly asks for raw CLI execution.
python3 scripts/meta_ads_agent.py doctor
python3 scripts/meta_ads_agent.py classify -- meta ads campaign list
python3 scripts/meta_ads_agent.py run -- meta ads campaign list --limit 25
The guard script:
- appends
--output jsonformeta adscommands when no output format is provided; - refuses non-
meta adscommands; - blocks token/secret arguments so credentials stay in the environment;
- blocks writes, unknown actions, budget changes, activation, and destructive actions without specific approval;
- keeps persistent logging disabled by default.
Non-negotiable operating rules
- Read before write. Inspect the relevant object, account, and recent performance before changing anything.
- Never guess IDs. Resolve account, campaign, ad set, ad, creative, page, dataset/pixel, catalog, product set, and product item IDs through the CLI or from user-provided values.
- Prefer JSON. Use machine-readable output for analysis and only present tables or summaries after parsing.
- No spend-affecting change without explicit approval. A generic “yes” is not enough; approval must name the action, object/account, and key values.
- Never activate by accident. New or modified objects should remain paused unless the user explicitly asks to activate and reviews the object.
- One write step at a time. Run one mutation, verify it, then continue. Do not batch multiple creation/update steps unless the user has approved a controlled automation plan.
- Keep secrets out of chat, commands, files, and logs. Do not print tokens,
.envcontents, cookies, app secrets, or debug output containing them. - Treat special or regulated categories conservatively. Housing, employment, credit, social issues, elections, politics, health, financial services, minors, and sensitive audiences require extra review.
Risk gates
Read-only commands may run after auth/account checks:
python3 scripts/meta_ads_agent.py run -- meta ads insights get --date-preset last_7d --fields spend,impressions,clicks,ctr
Ordinary writes require specific approval:
python3 scripts/meta_ads_agent.py run \
--approved "User approved pausing ad 120000000000000 in account act_123456" \
-- meta ads ad update 120000000000000 --status PAUSED
Budget changes require the budget flag:
python3 scripts/meta_ads_agent.py run \
--approved "User approved changing campaign 120000000000000 daily budget to 5000 minor units in account act_123456" \
--allow-budget \
-- meta ads campaign update 120000000000000 --daily-budget 5000
Activation requires the activation flag:
python3 scripts/meta_ads_agent.py run \
--approved "User approved activating campaign 120000000000000 in account act_123456 after review" \
--allow-active \
-- meta ads campaign update 120000000000000 --status ACTIVE
Delete/remove/unshare requires the destructive flag:
python3 scripts/meta_ads_agent.py run \
--approved "User approved deleting paused creative 120000000000000 in account act_123456" \
--allow-destructive \
-- meta ads creative delete 120000000000000
Agent workflow
For read-only analysis:
1. Run doctor/auth/account check if access is uncertain.
2. List or get the relevant objects.
3. Query insights with an explicit date range or date preset.
4. Summarise findings with date range, fields, caveats, and recommendations.
5. Separate recommendations from actual changes.
For any mutation:
1. Read current object state and recent performance.
2. Present the exact command, account/object IDs, before value, after value, risk, and verification command.
3. Wait for specific approval.
4. Run one guarded command.
5. Verify the changed object.
6. Report object IDs touched, before/after, what remains paused/not live, and any follow-up needed in Ads Manager.
Common tasks
Account snapshot
python3 scripts/meta_ads_agent.py run -- meta ads adaccount current
python3 scripts/meta_ads_agent.py run -- meta ads campaign list --limit 50
python3 scripts/meta_ads_agent.py run -- meta ads insights get --date-preset last_7d --fields spend,impressions,clicks,ctr,cpc,cpm,conversions
Performance triage
Fetch insights for the requested level and date range, then recommend actions. Do not pause or change budgets until the user approves a specific command.
python3 scripts/meta_ads_agent.py run -- meta ads insights get --date-preset last_7d --fields campaign_id,campaign_name,spend,impressions,clicks,ctr,cpc,cpm,conversions,cost_per_conversion
Safe pause
Before pausing, get the object and recent insights. After pausing, verify status.
python3 scripts/meta_ads_agent.py run -- meta ads ad get <AD_ID>
python3 scripts/meta_ads_agent.py run -- meta ads insights get --ad_id <AD_ID> --date-preset last_7d --fields spend,impressions,clicks,conversions
python3 scripts/meta_ads_agent.py run --approved "User approved pausing ad <AD_ID> in account <AD_ACCOUNT_ID>" -- meta ads ad update <AD_ID> --status PAUSED
python3 scripts/meta_ads_agent.py run -- meta ads ad get <AD_ID>
Paused launch
Create launch plans as reviewable commands, but execute one write at a time. Default every created object to PAUSED if the CLI supports a status flag. Do not activate the campaign, ad set, or ad unless the user approves activation separately.
Suggested sequence:
1. Verify account, page, destination URL, catalog/dataset needs, objective, budget currency/minor units, schedule, and special ad categories.
2. Create campaign as paused; verify returned ID.
3. Create ad set as paused; verify returned ID.
4. Create creative; verify returned ID and preview where possible.
5. Create ad as paused; verify returned ID.
6. Summarise all IDs and tell the user what is still paused.
Plans and templates
Plan files are JSON command lists for review. run-plan is read-only by default; for writes, lint the plan and then run one approved write command at a time.
python3 scripts/meta_ads_agent.py lint-plan templates/read-report-plan.json
python3 scripts/meta_ads_agent.py run-plan templates/read-report-plan.json
Use --allow-write-plan only in a controlled environment where the user has already reviewed the plan, the ad account is correct, and the plan contains at most one write step unless explicitly marked otherwise.
Logging
The guard does not persist a run log by default. To keep a redacted local JSONL audit trail, set a controlled path:
export META_ADS_AGENT_LOG=.meta-ads-agent/runs.jsonl
# or per command:
python3 scripts/meta_ads_agent.py run --log-file .meta-ads-agent/runs.jsonl -- meta ads campaign list
Delete or protect logs when working with sensitive accounts. Logs may contain account IDs, object IDs, command names, and redacted result metadata.
Failure handling
If a command fails:
- Do not retry mutations blindly.
- Read the object/account state before deciding whether anything changed.
- Check
meta ads <resource> <action> --helpfor the installed CLI syntax. - For auth errors, check
ACCESS_TOKEN,AD_ACCOUNT_ID, token permissions, app/business asset assignment, and token expiry. - For rate limits or API errors, reduce scope, wait, or use smaller date ranges; do not parallelise writes.
Output format for the user
For reporting, include:
- what was queried
- ad account/object IDs when relevant
- date range and attribution assumptions
- top findings with numbers
- caveats about missing, zero, delayed, or odd metrics
- recommendations separated from changes actually made
For writes, include:
- exact object IDs touched
- before/after values
- command run, with secrets redacted
- verification result
- whether anything is live or still paused
- unresolved issues or follow-up needed in Ads Manager