AdFlow runs client Meta accounts through the API, and keeps a person on every change
A campaign workspace built on the Meta Marketing API. An agent drafts the campaign, the ad sets, the creative and the copy, then reads the results back. Every change the agent proposes passes a guardrail, a named approver and a typed confirmation before it reaches the account, because the fastest way to lose an ad account is an automated change nobody reviewed.
Running client ad accounts by hand is where the mistakes live
Managing Meta for other people means working across five surfaces at once. Ads Manager holds the account state, a reporting view holds the trend, a spreadsheet holds the comparison, a doc holds the reasoning, and a chat thread holds the approval. The reasoning behind a change lives in whichever one the person happened to open that day.
The cost of that is account risk. A budget doubled on the wrong campaign. A paused ad set nobody meant to touch. A creative pushed live without a check. Every one of those starts as an edit made faster than it was reviewed, and every one of them can get an account restricted.
So I built the layer Ads Manager leaves out: the trail from a campaign signal to a controlled action, with the account-changing step fenced off behind its own approval.
Delivery shifted, or cost per result climbed. The account tells you that much and stops there.
no comparisonAds Manager compares two windows awkwardly, so the real comparison gets rebuilt by hand every time.
rebuilt each weekThe thinking lands in a note that forgets which campaigns produced it, and the yes arrives in a thread that is attached to a message rather than to the change.
both come unlinkedSomeone types a new budget. Six weeks later nobody can say what the number was before, who agreed to it, or what evidence it rested on.
untraceableMonitor, investigate, decide, test, control, measure
Six moves, and each one hands a named object to the next. A frozen snapshot becomes evidence, evidence becomes a finding, a finding becomes a reviewable recommendation, and only an approved plan reaches the account.
The tools that exist solve a different half of the problem
Automation for Meta is a crowded category. Every option below is good at what it was built for, and none of them keeps the reasoning attached to the change.
Free, native, and genuinely useful for the mechanical cases: pause on a cost threshold, scale on a ROAS floor.
A rule fires on a condition and leaves no record of why the condition was the right one. There is no evidence behind it, no approval on it, and no way to ask later what the value was before.
Kept, narrowlyFar richer automation than the native rules, with cross-account management and scheduled actions on top.
They automate the action and assume the decision. The judgment about whether a change is worth making, and the test that would prove it, still happens in a spreadsheet next to the tool.
RejectedComplete control over the comparison, and a place to keep the reasoning next to the numbers.
Nothing connects it to the account. The sheet cannot see that a budget changed yesterday, and the account cannot see that the sheet ever had an opinion.
Became the snapshotThe fastest path from a question to a change, and the demo everyone wants to see.
A fluent answer earns account authority it has not proved it deserves. One confident wrong write on a client account costs more than every hour the automation saved.
RejectedEight workspaces, and each one answers a different question
It builds the campaign, and it hands you a draft rather than a live ad
The agent reads performance back through the Marketing API, writes the analysis against a frozen data snapshot, and proposes what to change next. It also drafts campaign structure, ad sets, creative and copy into the same wizard a person walks, so what reaches the account was assembled once and checked twice.
What it does not get is authority. The analysis layer is read-only by construction. A recommendation is a candidate with a status, and accepting one changes the status rather than the account. Turning a recommendation into a real change means designing an experiment, validating the live setup, and generating a plan that a person approves.
Deterministic code owns the numbers. Spend, results, CPA, contribution and outliers are calculated in application code, and the model explains that evidence rather than producing it. Where the inputs support it, a confidence interval decides the winner. A language model never does.
8 analysis recipes · 50 campaigns per run · findings must cite the campaign and the evidenceSix checks stand between an agent and a client’s ad account
Every one of these exists because the alternative is an automated change that nobody reviewed, which is how ad accounts get restricted and how client trust gets spent.
A narrow write surface
The controlled route accepts explicit campaign status and daily-budget changes and rejects any shape it does not recognise. The API client can do far more than the product will let it.
Guardrails on the value
Protected campaigns cannot be paused. A budget change cannot exceed the configured maximum percentage. A plan that trips either one enters a blocked state instead of running.
Three switches, all of them
A global kill switch, an account-level switch, and an agent-execute switch that is off by default. Every one has to allow the change. Agent execution stays opt-in even when writes are generally enabled.
Typed approval, twice
An approver types the exact plan ID to approve it. The operator then types
EXECUTE <plan-id> to run it. An approved plan without that exact
confirmation does not execute.
The live value wins
Immediately before writing, AdFlow re-reads the account. If the current status or budget no longer matches what the diff was written against, the plan blocks and has to be regenerated. Stale input is dangerous when the next step mutates an account.
Failure stays inspectable
Each object keeps its own result, so a run is completed, partial or failed rather than flattened into one word. Retry covers only what failed, rollback only what succeeded, and both are new plans with their own approval.
What happens when the account moved while you were deciding
This is the case the whole structure exists for, and it is the one a rule engine cannot see.
Monday. Spend on the retargeting campaign is running ahead of plan and cost per result is holding. The analyst freezes the scope, the analysis names the campaign and cites the evidence, and the finding becomes a recommendation: raise the daily budget from $50 to $65.
The recommendation goes into an experiment so the change is measurable rather than hopeful. Control and variant are named, the isolation variable is the budget and nothing else, and the stopping rule is set before anything launches. The approver reads the diff and types the plan ID.
Tuesday morning, the operator types EXECUTE. AdFlow calls Meta before
writing anything and finds the campaign sitting at $60, not $50. Somebody edited it in
Ads Manager overnight.
The plan blocks. It does not write $65 over a number it was never reviewed against, and it does not quietly re-baseline and continue. It reports the drift and asks for a fresh diff, so the approval that gets executed is an approval of the change that is actually about to happen.
The guardrail that matters is the one between the approval and the writeEvery account I run makes the next one safer
This started as the tool I wanted for my own client work, and it is designed to hold more than one account. Today it runs one client while the write paths and the tenant keys harden. The structure I am building toward is one workspace per account, one set of guardrails, and an audit trail that survives the person who made the change.
The compounding is in the rules. Every campaign I run teaches something about what breaks a Meta account. The budget jump that trips a review. The creative that should never have gone live. The bulk edit that hits the wrong ad set. Each of those becomes a guardrail or an agent skill rather than a lesson I have to remember.
That is the difference between an agency that scales and one that just takes on more accounts. The knowledge stops living in whoever happened to be on the account, and starts living in the system that runs it.
5 roles · shared guardrails · an append-only audit the database refuses to editA test has cells, one variable and a stopping rule, or it is just a change
What it runs on
Application
Next.js 16App Router, route handlers, and the proxy boundary, running as one process.
React 19Client and server components across the eight workspaces.
TypeScript 5Data contracts, route handlers, and the shape of every workflow object.
VercelHosting for the public read-only demo.
Data
SQLite, WAL modeSettings, frozen snapshots, workflow objects, execution attempts and the append-only audit table.
Meta Graph APICampaigns, insights, breakdowns, targeting, audiences and creatives, plus the supported writes.
Models
OpenAIOptional narrative layer, low temperature, explaining evidence the code already calculated.
GeminiThe alternate provider. If either call fails, the deterministic analysis still stands.
No UI frameworkCSS modules, no Redux, no component library. Fewer dependencies, more control over the dense operator screens.
Two data policies run side by side, because they answer different questions. Analysis reads from frozen snapshots so a finding can be reproduced weeks later, with a cache key hashed from the account, the resource and a normalised scope. Execution reads live, every time, immediately before the write. Snapshots for reproducibility, live reads for correctness.
What is running, and what I am not claiming
A working product with a public demo, built to a standard I would put a client account behind. The parts that are not there yet are named rather than implied.
Running
Eight workspaces and the full object chain from scope to controlled execution. The guardrail and approval path, per-object results with retry and rollback, and an audit table the database itself refuses to update or delete.
Next
Multi-account workspaces, so one operator runs several clients side by side. Secrets move to a managed store, roles get uniform enforcement on every route, and the remaining manual write paths move behind the same plan safety model.
Not claimed
No client performance numbers. The product is a prototype running one account, and the guardrails are designed against the failure modes I have seen rather than validated against a published incident rate.
Want this pointed at your ad account?
The demo is public and read-only. Open it, walk the loop from a campaign signal to an approved change, and see where the authority lines sit.











