Controlled beta for Google Ads advertisersRead the update
Approval flow · Google Ads controlled beta

Review a proposed campaign change in chat. Nothing moves until you approve it.

Ask Mako to cut a budget or pause a campaign and it writes a proposal, never a change. The card carries the value now, the value proposed, the numbers it leaned on, and any warning our own code computed. You press approve. It publishes once, reads the platform back in the same request, and compares the two field by field. A disagreement is recorded as a failed verification and never as a success.

Write access is off on every new connection. You arm it one account at a time, and every single change still needs its own approval.

Product view · demo data · Gymszy sample account
  1. 01The platform, derived from the action type by the same rule the executor dispatches on
  2. 02What changes, current value beside proposed value
  3. 03Every number the claim leaned on, with its verified source, window and freshness
  4. 04Warnings our server computed, sitting directly above the button
  5. 05Approve, dismiss, and on a budget card an edit whose typed figure is re-checked

Section 01 · the three switches

Three switches stand between Mako and your money.

01

Writes are off when you connect.

Every connection is stored with write access off. While it is off, the change tools are left out of the request we send to the model, so there is nothing for it to call. It cannot propose a change it was never handed, whatever you ask it.

02

You arm one account at a time.

The switch lives on that one connection and turning it on takes a confirmation that spells out what it enables: the agent may propose live changes, and each one still needs your approval. Arming Meta does not arm Google. Turning it back off takes one click and no confirmation, and it never disconnects the read.

03

Each change needs its own approval.

There is no bulk approve, no auto-approve mode and no dry-run shortcut around it. One card, one decision. Every write tool re-checks the switch and the platform grant on its own before it will draft anything, and the endpoint that executes checks both again at the moment you press.

Which permission we ask each platform for, and why neither one has a read-only version, is on the integrations page.

Section 02 · one change, start to finish

One change, start to finish.

Six frames, in the order they happen to you. Nothing here is a rendering of a future version: every frame is a step that exists in the code today.

01 · You ask

"Prospecting is over my cost ceiling. What should I do?" Plain words, in the chat, with no form and no builder.

02 · It reads

Live reads fire at the moment you ask, and the trace above the answer shows each one: the tool, its one-line summary, and whether it succeeded. Meta campaign insights · last_14d · 11 rows. A read that failed shows as failed rather than being dropped so the answer can look cleaner.

03 · It proposes

The write tool creates a row awaiting your approval and returns a card. It does not execute. A number the agent cannot trace back to a read from that same turn blocks the proposal before a card exists.

04 · You review

The diff, the evidence, the warnings, then approve or dismiss. $420.00 → $320.00 is the whole change, written out. Leave it and nothing happens.

05 · It publishes once

On approve the endpoint re-checks your subscription and that connection's write switch, refuses anything older than 24 hours, claims the row atomically so a double click cannot fire twice, re-runs the propose-time guards against fresh platform state, then sends exactly one write.

06 · It verifies

The platform is read back in the same request and compared against what you approved. A match settles the row as verified. A mismatch settles it as a failed verification, with the discrepancy in plain words.

Product view · demo data · Gymszy sample account

Between frame 03 and frame 04 the product does nothing at all. That gap is the feature.

Section 03 · what you see before you approve

What you see before you approve.

The card above is not a mock-up of the product. It is rendered by the same function that turns a stored proposal into the card in your workspace, so every part below is the part you will actually read.

Table A · every part of the approval card, and where it comes from
Part of the cardWhat it showsWhere it comes from
Platform labelMeta or Google Ads.Derived from the action type by the same rule the executor dispatches on, so the label cannot disagree with where the write goes.
TitleThe change in one line.The summary stored on the proposal row, composed in code when the proposal was created.
WhyOne sentence of the agent's reasoning.The model's claim, stored with the proposal. It is the model's, and the card presents it as the model's.
Diff rowsCurrent value beside proposed value, one row per thing that changes.Read from the platform when the proposal was drafted and stored as the before state and the requested state.
EvidenceEach number the claim leaned on: the metric, the value in your account’s currency, the verified data source, the scope it applies to, the reporting window and the data freshness.The proposal's evidence list. The parse fails closed, so anything malformed renders as no claim and no receipts, never as invented ones.
Before you approveThe tradeoffs, in amber, directly above the approve button, in the awaiting state only.Computed by our server before the card exists and stored outside the model's own schema on purpose, so the model can neither write these warnings nor suppress them.
ButtonsApprove and dismiss, plus an edit on a budget card.The live card is handed an approve handler, a dismiss handler, and on a budget card an edit handler, so the edit button renders there and nowhere else.
Executing checklistWrite to the platform, then verify by re-reading. A budget move shows four rows, one pair per leg.Built per action type by the same mapper.
Table B · the diff rows you get, per change
ChangePlatformWhat the card shows
Campaign statusMeta AdsOne status row, ACTIVE to PAUSED or the reverse.
Campaign daily budgetMeta AdsOne daily budget row, both figures in your account's currency.
Budget moveMeta AdsOne row per leg, with the total held constant. The source falls by exactly what the destination rises by.
Campaign statusGoogle AdsOne status row, ENABLED to PAUSED or the reverse.
Campaign nameGoogle AdsOne exact name row for one existing campaign. Status, budget, targeting and delivery remain unchanged.
Campaign daily budgetGoogle AdsOne daily budget row, both figures in your account's currency.
Negative keywordsGoogle AdsOne row per term, each showing the term and the match type that will block it.
Remove campaign negative keywordsGoogle AdsOne row per exact existing term, including match type, before removal.
Manage positive keywordsGoogle AdsOne row per exact keyword in one ad group, showing match type and the current and requested status, or that a term will be added or removed.
Manage an existing ad groupGoogle AdsOne exact row for ad group status or name, with the current value beside the requested value.
Existing ad statusGoogle AdsOne exact status row for one existing ad, with its ad-group and campaign context. Ad text, URLs and creative remain unchanged.
A new campaign, pausedGoogle AdsNo before and after rows, because nothing exists yet. The card shows the campaign itself: budget, countries and languages, every keyword with its match type, every headline and description with its character count against the platform limit, and each image you uploaded.
New TikTok campaignTikTok AdsNo before and after rows, because nothing exists yet. The card shows the campaign itself: budget in the advertiser's own currency, objective, locations, the schedule in TikTok's own time format, which identity the ad runs under, the ad text against TikTok's character limit, and the video id it will use. It also says plainly that TikTok has not validated any of it, because TikTok publishes no way to check a campaign before creating it.
Publish the product feedGoogle Merchant CenterHow many products would be added, updated and removed, and how many are already published unchanged. On a first publish the card also names the Merchant Center account and the data source Sable Mako would replace, because that publish takes over the feed serving your Shopping ads.

The warnings are the part a model cannot touch. They are computed in our own code before the card is built and stored beside the model's reasoning rather than inside it, deliberately absent from the schema the model writes into. So a model that would rather you did not see a tradeoff has no field to put it in and no field to take it out of.

The card carries no estimated saving and no projected impact. We do not compute one, so it does not show one. A modelled figure on a money decision is the kind of number that gets quoted back at us and cannot be defended, and its absence is deliberate rather than an omission.

You can correct the number before approving. A budget card lets you type the figure you want. It runs the same magnitude, churn and cap checks the agent's figure runs, and it is recorded as a human-stated figure the model can never originate, so an edited number is re-checked rather than trusted blind.

Section 04 · what it can change

What it can change. What it cannot.

Fourteen operations across four platforms, two of them switched off. Narrow and true is worth more here than broad and vague, so this is the whole list and then everything that is missing from it.

Table C · the complete write surface
PlatformWhat Mako can propose todayWhat it cannot do today
Meta Ads
  • Pause or activate a campaign.
  • Set a campaign daily budget, at campaign level only.
  • Move daily budget between two campaigns, or between two ad sets, inside one account, with the total held constant.
Create or delete campaigns, ad sets or ads. Upload creative. Change targeting, bidding, schedules or objectives. Change lifetime budgets. Change account settings. Set an ad-set budget on its own: an ad-set budget moves only as one leg of a budget move.
Google Ads
  • Pause or enable a campaign.
  • Rename one exact existing campaign. Its current name and status are checked again before mutation, and only the name is changed.
  • Set a campaign daily budget, where the budget is not shared with other campaigns.
  • Add between 1 and 20 negative keywords to a campaign, as exact, phrase or broad, defaulting to exact.
  • Remove between 1 and 20 existing campaign negative keywords after binding exact text, match type and live criterion id.
  • Add, pause, enable or remove between 1 and 20 positive keywords in one ad group, with a fresh read before and after execution.
  • Pause, enable or rename one existing ad group. The exact current name and status are checked again before mutation, and enabling is checked against spending caps.
  • Pause or enable one exact existing ad. The ad, ad group and campaign are checked again before mutation, and enabling is checked against spending caps.
  • Create a new campaign, paused, with its budget, targeting, ad groups, keywords, copy and images. Off for every account today: the switch is a constant in our source, so it cannot be turned on without a code change. When on, the campaign is created PAUSED and spends nothing until you approve activation separately.
Edit existing ad text, final URLs or creative. Change bids or bid strategy. Change campaign geography, audiences or schedules. Delete campaigns, ad groups or ads. Change conversion actions or budget sharing. Move budget between campaigns: there is no Google Ads rebalance tool, and the agent is instructed to say so rather than fake one with two separate writes.
Google Merchant Center
  • Publish the product feed Mako builds from your Shopify catalog. The first publish makes Sable Mako the primary data source for that Merchant Center account, which replaces whatever feed supplies your Shopping ads today, and the card says so before you approve. Only products that changed since the last publish are sent, and a build carrying an error Google would reject cannot be published at all.
Change bids, budgets or campaigns. Change your Merchant Center account settings, shipping, tax or returns. Delete a data source. Touch an account you did not connect. Merchant Center accepts products one at a time, so a publish reports each item's outcome and can end partial; it never claims Google approved anything, because approval arrives later and the feed audit is what reports it.
ShopifyNothing. Shopify is read-only today: no write permission is requested and no write path exists in the code.It is absent from the list of providers the write switch accepts, so the switch refuses to arm for it. There is no proposal tool and the code that executes approved changes has no Shopify branch.
TikTok Ads
  • Create a new campaign, ad group and ad in one card, every object paused. Off for every account today, and held off by three separate things: the capability switch is a constant in our source, the write switch does not accept TikTok as a provider at all, and the permission check in front of every TikTok write does not recognise the grant TikTok reports back. When on, nothing is activated by the approval: you turn the campaign on yourself in TikTok Ads Manager.
Change anything that already exists: statuses, budgets, bids, targeting and schedules. Delete anything. Upload creative: the video has to be in your account already and we send its id. Touch audiences, pixels or the Events API. TikTok has no all-or-nothing create either, so campaign, ad group and ad are three separate calls; every object is created paused for that reason, and a build that fails part-way names exactly which objects exist rather than reporting a bare error.
Google Analytics 4Nothing. The permission we request is read-only.We read your property list and your traffic by source. No write permission, no mutating call.
Google Search ConsoleNothing. The permission we request is read-only.We read your site list and your search queries and pages. No write permission, no mutating call, and there is no write path.

Not built: LinkedIn Ads, Microsoft Ads, Pinterest Ads, Snapchat Ads, Klaviyo, Amazon Ads. No connector, no login flow, no API client and no agent tool for any of them. We write not built rather than planned, because that word is a delivery promise and there is no date behind one.

Two platforms can be written to. Everything else we connect is read-only by construction rather than by policy, and the bound is structural: one function in our code sends a change to Meta and it has four callers, three for the changes above and one that writes the account-level spend cap set at connect. One Google function sends bounded mutations across a closed list of six services, including exact keyword-criterion removals, ad-group name or status changes and exact existing-ad status changes, while a second can create a campaign and is switched off for every account by a constant in our source. No outbound operation can delete a campaign, ad group, ad, account or conversion action.

Where this stands today.

Meta is a reviewer-only path. Meta's read and write code is implemented, but Meta app review is still in progress. Access is limited to Meta reviewers and explicitly allowlisted test accounts, and no Meta capability is offered to ordinary beta customers.

Google Ads is the ordinary controlled-beta path. Account reads and recommendations are available to beta customers. Its bounded write operations require approval of the exact action and remain under supervised validation while we assemble a sanitized production acceptance record.

Every field we read from each platform, and the permission behind it, are on the integrations page.

Section 05 · the limits, in code

The limits live in code, not in a prompt.

Two kinds of rule. A block means no approval card is ever created, so there is nothing to press. A warning means the card is created and carries the tradeoff above the button.

Table D · every block and every warning
RuleWhat happensWhere it applies
A budget increase larger than 300%Block Blocked. No card is ever created.Meta campaign, Meta ad set, Google Ads campaign
A budget change larger than 20%, up or downWarning Allowed, with the tradeoff printed on the card above the approve button.Meta campaign, Meta ad set, Google Ads campaign
A Google Ads budget shared with other campaignsBlock Blocked when the proposal is drafted, and blocked again by the executor before it sends, because changing it would move money in campaigns you did not review.Google Ads campaign budget
A Meta campaign whose budget lives on its ad sets, or that runs on a lifetime budget, or an amount of zero or lessBlock Blocked.Meta campaign budget
A campaign already in the state being asked for, or deleted, or archivedBlock Blocked, with the campaign's real current state named.Meta status changes
A Google Ads campaign that has been removed, or cannot be read from the accountBlock Blocked when drafted, and re-checked against live state before the write is sent.Google Ads changes
A budget move whose two sides sit in different ad accountsBlock Blocked, failing closed, because two accounts can bill in two currencies. It is blocked the same way when the account cannot be confirmed at all.Meta budget move
A budget move that would take the source to zero or belowBlock Blocked. Turning a campaign off has to be proposed as a pause and approved as one.Meta budget move
A campaign covered by a lock rule you wroteBlock Blocked in code, and the refusal quotes your own words back at you.Meta and Google Ads status changes
A number in the proposal that cannot be traced to a live read from that same turnBlock Blocked before a card exists, with strict matching, so a hundredfold unit error cannot pass as a rounding difference.Every change
A proposal older than 24 hoursBlock Refused at approve time. Nothing transitions and nothing is sent. Ask again and the account is read afresh.Every change
Writes switched off after the proposal was draftedBlock Refused at approve time. The card stays pending with the reason on it.Every change
A Google Ads change that could apply to more than one connected accountBlock Blocked. Mako asks which account you mean instead of guessing.Google Ads changes
Negative keywords per proposalWarning Bounded between 1 and 20, in the schema the model is offered and again at runtime.Google Ads negative keywords
Pressing approve twiceWarning An atomic claim on the row means exactly one write goes out. The second press loses the race and is answered with the first one's result.Every change

These are not instructions in a prompt the model could talk itself out of. They run in our own code, before the model's output ever reaches a card, and the ones that guard money run again at the moment you press.

Section 06 · the second you press approve

What happens the second you press approve.

Seven steps, in one request. There is no queue, no worker and no callback: the write and the check that proves it are the same round trip.

  1. 01Your subscription and that connection's write switch are re-checked at the moment you press, not at the moment the proposal was written.
  2. 02Anything older than 24 hours is refused, and nothing transitions.
  3. 03The row is claimed atomically, moving from proposed to executing. A second press loses the race and replays the same answer.
  4. 04Inside the claim, the propose-time guards re-run against fresh platform state. If the account moved underneath, the row settles as failed with the reason and nothing is sent.
  5. 05Exactly one write goes to the platform.
  6. 06The platform is read back, in the same request.
  7. 07The re-read is compared against what you approved, field by field. A match settles as verified. A mismatch settles as a failed verification with the discrepancy stored in plain words, for example "Re-read shows 420 USD, not 320."

A proposal is a claim about a moment. Past 24 hours the numbers on the card describe an account that has moved, so the honest answer is to ask again rather than to execute on a snapshot nobody re-checked.

Activating a Meta campaign counts as done only when the re-read shows it delivering. Meta reports a campaign's own status and its effective status separately, and a campaign can be ACTIVE in name while gated by review, by budget or by an account issue. The check reads the effective one, so accepted is not treated as live.

If the guards cannot be re-run, nothing runs. An action type with no re-checkable guard is refused rather than allowed through on a pass that was a claim about nothing, and a read failure before the write settles the row as failed with the reason instead of executing blind.

Section 07 · the record it leaves

Every change leaves a record you can read.

One row in our database per proposal, approved or not, written as the change moves through its states. This is what the row holds.

Table E · the record, field by field
FieldWhat it holds
Summary and action typeWhat was proposed, in words, and which of the fourteen operations it was.
Target and connectionThe campaign, ad set or campaign target, and which connected account it belongs to.
Conversation and messageThe exact turn of chat the proposal came out of.
DecisionThe agent's claim, its confidence, its evidence list, and the warnings our server computed and showed you.
Before stateWhat the platform said before, at propose time.
Requested stateWhat you were asked to approve.
Executor resultWhat the platform returned.
Verified stateWhat the platform said when we read it back.
Verification resultWhether those two matched, and the discrepancy where they did not.
API errorThe provider error or host safety reason, mapped into a title, a detail and a suggested fix.
TimestampsCreated, decided, executed.

The states a change can be in

proposeddeniedexpiredexecutingverifiedverification failedfailedrolled backrollback failed

Only finished rows become receipts. A proposal still waiting on you is not a receipt, because nothing has happened. The ledger on your Today screen is built from rows that reached a decision, so it is a record of what was done rather than a list of what was suggested.

One thing we will not claim. The record stores that a change was approved, when, on which account, and which signed-in person pressed the button. Workspaces can include an Owner and Members, so that person-level record is what makes each approval accountable. A proposal that expires because a newer one replaced it records no approver, because nobody approved it.

How long we keep all of this, and how to have it deleted, is in the privacy policy.

Section 08 · when something goes wrong

When something goes wrong, it says so.

The second fear about letting anything touch a live account is not that it refuses. It is that it fails halfway and nobody tells you. Here is every way this can end badly and what you see in each case.

Table F · the failure matrix
What went wrongWhat you seeWhat we do
The platform rejects the writefailed Failed, not confirmed live, with the provider's own reason translated into a sentence and a suggested fix.Nothing changed. The row settles as failed.
The write applied and the re-read disagreesverification failed A failed verification, with the discrepancy written out.It is not marked done and it does not go green. The mismatch is stored on the row so a reload shows the real difference rather than a generic sentence.
A budget move fails after its first legrolled back Which legs applied, and that the account was put back.Compensation runs on its own: applied legs are restored in reverse order and re-read to confirm they landed. The row settles as rolled back.
The compensation itself failsrollback failed Could not fully undo, action needed, naming the exact entities and the value each should be back at.We say the true thing rather than the comfortable one: a step failed, we could not fully undo it, and your account may be changed. Check these in Ads Manager.
Something throws after the write was sentfailed Failed, with the real error.The write may or may not have applied, so we say exactly that and tell you to re-check the campaign before retrying. The row is never left stuck mid-flight.
The guards refuse before anything is sentfailed The account changed since this was proposed, with the blocker named.Nothing was sent. The row settles as failed and says so, which is a different sentence from the one above on purpose.

There is no undo button. Automatic reversal exists in one place only, inside a Meta budget move, where two legs are one approvable action and a failed second leg puts the first back. There is no rollback route in the product and no automatic retry. To reverse a budget or a pause you ask for the opposite change and approve that too, and because every value the change started from is stored, the number to go back to is on the record.

A mismatch is never recorded as a success. The status a card shows is derived from the re-read, not from the platform's own reply, so a partial cannot be presented as a completion. That is why the verified footer says the change was confirmed live by re-read rather than saying the platform accepted it.

Section 09 · the questions worth asking

The questions worth asking.

Can Mako change my campaigns without asking me?

No, and two separate gates stand in the way. A connection is read-only until you switch writes on for that specific account, and while it is off the change tools are never handed to the model. With writes on, every individual change still creates a card that waits for you. There is no auto-approve mode in the product.

What if I never approve anything?

Nothing changes. Proposals sit there and are refused after 24 hours. Read-only features can continue without enabling writes, but repeat audits, monitoring, alerts and Mako require an active trial or plan.

What happens if a change fails halfway through?

Two cases. A single change either lands or does not, and the re-read tells you which. A budget move has two legs, so if the second fails the first is put back automatically and the row is marked rolled back. If a leg cannot be put back, we say so and name the exact campaigns to check in Ads Manager instead of pretending it resolved.

Can I undo a change?

Not with a button. Compensation is automatic inside a budget move and that is the only automatic reversal we have. For everything else you ask for the opposite change and approve it. Every before-value is on the record, so you always know the number to go back to.

What are the hard limits?

A budget increase larger than 300% is blocked outright and never becomes a card. A change larger than 20% carries a warning on the card, because a swing that size restarts the platform's learning. Shared Google Ads budgets are blocked. Budget moves across two ad accounts are blocked. Any campaign you have told Mako to lock is blocked in code, and the refusal quotes your own rule back at you.

Can it invent a number to justify a change?

Structurally, no. Every figure on a proposal has to trace back to a live read from that same turn, the check runs before the card is built, and the metric it can cite is a closed list of the metrics our read tools actually return. A proposal with an untraceable number is refused rather than softened.

Which platforms can it actually change?

Google Ads is the ordinary controlled-beta connection. Its bounded changes require approval of the exact action and remain under supervised validation. Meta has implemented change operations but is reviewer-only while app review completes. Merchant Center publishing is supervised-only. TikTok write actions are unavailable. Shopify, GA4 and Search Console have no customer write path.

What if I click approve twice?

The row is claimed atomically, so exactly one write goes out. The second press gets the same answer as the first, because the endpoint is idempotent rather than because the browser stopped you.

Do you record which of us approved it?

Yes. We record that a change was approved, when, on which account, and which signed-in person pressed the button. Workspaces can include an Owner and Members, so each approval is attributed to the person who made it. A proposal that expires because a newer one replaced it records no approver, because nobody approved it.

Do I need a paid plan to publish?

Google Ads connection and one initial audit need no card. Repeat audits, monitoring, alerts and Mako require an active trial or plan. Merchant Center publishing is not an ordinary beta capability; it remains restricted to supervised validation. Approving a permitted change draws no credits, but the conversation that produced it does.

Controlled beta

Start read-only. Turn writes on only when you trust the evidence.

Apply with one active Google Ads account. Invited partners review the first recommendation before any write capability is considered.

  • writes off until you switch them on, per account
  • one card, one decision, no bulk approve
  • every figure on this page: one demo account

Invited partners connect read-only first. Every exact platform change requires separate approval.

Receipts

  1. Write access is off on every new connection. While it is off, the agent's change tools are left out of the request sent to the model, so it is never handed them.
  2. Write access is granted per connected account and can be withdrawn without disconnecting the read. Arming one platform never arms another.
  3. Every product view and every figure on this page is the Gymszy sample account, labelled as demo data where it appears. Nothing here is presented as a customer result, because there are none to present yet.
  4. Warnings on a proposal are computed by our server and stored beside the model's reasoning rather than inside it, deliberately outside the schema the model writes into, so it can neither author them nor remove them.
  5. Google Ads is the ordinary controlled-beta connection, with bounded writes under exact approval and supervised validation. Meta is reviewer-only while app review completes. Merchant Center publishing is supervised-only. TikTok writes are unavailable. Shopify, GA4 and Search Console have no customer write path.
  6. A budget increase larger than 300% is blocked before a proposal is created. A change larger than 20% in either direction is shown as a warning on the card.
  7. A proposal older than 24 hours is refused at approve time and has to be asked for again against a fresh read.
  8. Every approved change executes exactly once and is verified by reading the platform back in the same request and comparing it, field by field, against what you approved. A mismatch is recorded as a failed verification, never as a success.
  9. The record stores that a change was approved, on which account, and which signed-in person pressed the button. Workspaces can include an Owner and Members, so each approval remains attributable to the person who made it.
  10. Automatic reversal exists only inside a Meta budget move, where two legs are one approvable action. There is no general undo, no rollback route and no automatic retry, and reversing anything else means approving the opposite change.