Plan a campaign
Write down what you intend to run — channels, budgets, targeting, dates — as a structured Campaign Plan your agent can sum, approve, execute and record against.
The read tools tell an agent what is running. The campaign_plan_* and line_item_* tools let it write down what you intend to run — before anything is bought — in a form that adds up, that a human can approve, and that the mutation tools can then build from.
This is the document that usually lives in a spreadsheet: €120,000 across four channels and six markets, ten weeks, with an argument for the split. Here it is data, so nothing has to be retyped into an ad account by hand.
Three ideas
- A Campaign Plan is what your organization intends to run: an envelope, a currency, a window, optionally a brand, plus the
rationalefor the split and howmeasurementwill judge it. It belongs to your organization, is authored incrementally, and is approved by a person. - A Line Item is one row of that intent — a channel, an objective, an audience, an amount, a window. It holds only what stays constant across everything it spawns, which is why it carries no optimization goal and no campaign-tree shape.
- An execution record is one row per provider object a Line Item created. It is written by the agent that did the creating, and it is what later answers “which of these campaigns came from row 3?”
The workflow
Create the Campaign Plan
campaign_plan_create needs a name, a
one-line description and a currency. Everything else — the envelope, the
window, the brand — can arrive later, because every amount written
afterwards is read through that currency.
Add the Line Items
One line_item_create per intent: channel,
objective, and whatever of budget, countries, age_min / age_max,
gender and dates you have decided. A line with no dates inherits the
Campaign Plan’s.
Read it back
campaign_plan_get returns the Line Items
in full — there is no line_item_get — along with the money figures and
four facts derived per line: provider, executable, the effective window,
and unit. Read these back rather than assuming them.
Approve, or validate one line
campaign_plan_approve is the human
act: it approves the Campaign Plan and validates every draft line on it.
When only one row is ready, use
line_item_validate so your approval does
not reach somebody else’s half-written row.
Execute with the mutation tools
Creating the campaigns and ad sets is the ordinary write path —
meta_create_campaign,
meta_create_adset — against the
advertiser_id on the line, and it needs the mutation:write scope.
Record what you created
After each create, call
line_item_record_execution with
the native id. Nothing does this for you: one line may create any number of
objects and you chose the shape, so only you know which came from where.
Three money figures, not one
campaign_plan_get returns an allocation block. The numbers in it answer different questions and are allowed to disagree.
| Figure | What it is |
|---|---|
totalBudget |
The envelope — what you have. null means no declared constraint, never zero. |
allocated |
The sum of the Line Item budgets. |
unallocated |
The envelope minus the allocated sum — what is still unplaced. |
comparable |
Whether that sum means anything at all. |
Statuses you’ll see
| On | Value | Meaning |
|---|---|---|
| Campaign Plan | draft |
Being authored. Editable, and not approved by anyone. |
| Campaign Plan | approved |
A person signed off on the content at a specific revision. |
| Line Item | draft |
Not cleared to run. |
| Line Item | validated |
Cleared to run — by its own validation, or by the approval that cascaded over it. |
Before you execute
Approval is a gate on the plan, not a lock on the ad account: the Meta tools know nothing about your Campaign Plan and will happily create from a row nobody validated. Check these yourself, from the campaign_plan_get response, before you create anything:
- The line is
validated. This is the gate; walking through it is your job. executableistrue. A channel nobody has connected yet still plans, sums and approves — it simply cannot be built.- The
advertiser_idis set, owned by your organization, and on the line’sprovider. - The account currency equals the Campaign Plan’s. AdCrunch never converts — Meta reads
daily_budgetin the account’s currency, so a EUR plan built into a USD account creates the same number in dollars. A converted budget is a different plan. - The window resolves, after inheritance, and starts before it ends.
- Send the budget in the unit the line says.
totalis a lifetime budget;dailyis a rate.
Scopes
Authoring needs campaign_plan:read and campaign_plan:write; recording an execution is a write on the plan, so it needs campaign_plan:write too. Actually creating campaigns needs mutation:write, granted separately.
That separation is the point: an agent can plan an entire quarter — restructure it, re-budget it, approve nothing — without being able to move a cent. See Auth & scopes.
Channels and providers
Ten channels can be planned: meta, tiktok, snapchat, google_search, google_pmax, google_display, youtube, programmatic_display, linkedin and x. Your media plan already spans them, and a planning surface that covered one would be a planning surface you kept a spreadsheet beside.
Execution is a different question, and a narrower one: executable is true for Meta today. It is derived per request from what AdCrunch can write to, never stored — as more providers come online, the same rows become executable with nothing to migrate.