--- name: launch-ads description: Launches creator ad campaigns in Lucra on Meta or TikTok from approved creator videos, checks the draft before launch, watches it go live, and applies the fixes Lucra lists when a campaign needs attention. Use when the user wants to run creator videos as ads, launch or relaunch a campaign, find out why a campaign isn't running, or fix a rejected ad or a failed launch. --- # Launch and fix creator ads in Lucra ## Before you build 1. `connections_find`: pick a `connected` ad account (Meta or TikTok). None, or `setup_needed`? Ask the user to finish it in Lucra (Settings › Integrations); `connections_create` with `body {"provider": "meta"}` gives them a sign-in link. 2. `lookup` with `view "ad_fields"` and `query {"connection": "conn_…", "objective": "conversions"}`: the settings this account takes, with limits and minimum budgets in its currency (minor units), and its pixels, conversions and apps as `options`. 3. `submissions_find` with `query {"status": "approved"}`: the creator videos to run (`sub_…`). Ask only for what you can't read or default: usually the budget and the website. Default the rest. ## Check, then launch 1. Build the draft as `campaigns_create` would take it: `name`, `connection`, `destination` (`{"type": "website", "value": "https://…"}`), `budget` (`{"daily": }`), `schedule` (`{"startDate": "YYYY-MM-DD"}`), `audience` (`{"countries": ["US"]}`), `creatives`, `ad` (`primaryText`, `callToAction`), and platform settings in `options` by their `ad_fields` keys. 2. `campaign_validations_create` with `body {"draft": {…}}`. For each `error` issue, merge its fix's `patch` into the draft (replace arrays whole) and check again until `valid` is true. An error with no `patch` needs a choice: ask the user, pointing at its `field`. 3. Check once more with `body {"draft": {…}, "preflight": true}`: the ad platform checks it too. 4. Confirm with the user: name, platform, budget and start date. Launching spends their money. 5. `campaigns_create` with the draft and an `idempotencyKey`. `"launch": false` saves it paused instead; `"status": "draft"` saves it with nothing on the platform yet, to launch later with `campaigns_update` and `status "live"`. ## Watch it go live `campaigns_find` with its `id`: - `processing`: Lucra is setting it up on the platform (`job` shows progress). Read it again in a minute; don't loop fast. - `in_review`: the platform is reviewing the ads, often for hours. Tell the user and check back later. - `live`: running. `needs_attention`: go to fixes. - A launch whose `job.status` is `partially_failed` runs the ads it created; the rest have issues. ## Fix what needs attention `campaigns_find` with `query {"status": "needs_attention"}` finds them. On each campaign, ad set and ad, read `issues` (and `deliveryState` / `deliveryReason` on ad sets and ads). For each `error` issue: 1. Say its `title` and `message` in your own words. `providerMessage` is the platform's own text, if the user wants it. 2. Offer only the fixes listed on it. Never make one up. - A fix with `request`: call the tool named by `request.operation` (`campaigns.update` is `campaigns_update`), with `request.params` as its path IDs and `request.body` as `body`, plus an `idempotencyKey`. For `campaigns_update`, add the campaign's current `version` from a fresh `campaigns_find`. - A fix with `url` (`reconnect`, `open_setup`, `open_platform`): the user opens it; it's their billing, sign-in or appeal. - `retry` re-sends the campaign's status and retries what didn't reach the platform. Never create a new campaign to retry. - `wait`: nothing to do yet. - `copy_campaign` (it never has a `request`): read the campaign with `campaigns_find`, then `campaigns_create` with its fields and `status "draft"`; on a placement issue, add a `placement` from a campaign with `compatible: true` in `outside_campaigns_find` (the connection's `id`). - A campaign copy is a draft: change what the issue names on the copy, then launch it with `campaigns_update` and `status "live"` once the user agrees (it spends). 3. Confirm first anything that removes an ad, archives, or spends more (a bigger budget). 4. Read the campaign again: the issue goes away once the platform accepts the change. `ad_change_in_progress` (409) means a change is still running: wait until `job` finishes, then send it again. ## Change a running campaign - Budget, status, options or start: `campaigns_update` with `version`. - An ad set's bidding, audience, budget or options: `ad_sets_update`. - An ad's text (`ad`), its video (`creative`, a new `sub_…`: Lucra replaces the ad) or status: `ads_update`, one change per call. - Another ad set with its ads: `ad_sets_create`. Another ad (a creator video) in an ad set: `ads_create`. - A campaign made outside Lucra in the ad account: `outside_campaigns_find` (the connection's `id`) reads it; `outside_campaigns_update` with `level` campaign, ad_set or ad pauses, resumes or re-budgets it. ## Read results `ad_results` with `from`, `to` and `query {"group": "campaign"}` (or creator, submission, ad, platform, program; several comma-separated) gives totals and days. Money is in cents: `usageFees` is `lucraFee` + `partnerFee`; `lucraFee` and `creatorRewards` are null on outside rows. `platform_metrics_list` has every metric a platform reported, per ad per day.