AI Systems · AdFlow · Live demo · seed data

AdFlow puts an approval gate between an agent and a Meta ad account, and keeps a person on every change

Today it runs one client account. The demo that opens here is public and read-only, and it runs on seed data.

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.

8 workspacesmonitor, investigate, decide, test, control, measure
3 write switchesall three must allow a change before it runs
Why I built it

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 shows the trend, a spreadsheet rebuilds the comparison, a doc carries the reasoning, and the approval lands in a chat thread. 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 any 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.

01 · Notice Spot the movement in Ads Manager

Delivery shifted, or cost per result climbed. The account tells you that much and stops there.

no comparison
02 · Compare Export to a spreadsheet

Ads Manager compares two windows awkwardly, so the real comparison gets rebuilt by hand every time.

rebuilt each week
03 · Agree Reason in a doc, approve in chat

The thinking lands in a note that forgets which campaigns produced it, and the yes sits on a chat message, with nothing tying it to the change.

both come unlinked
04 · Change Edit the account

Someone 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.

untraceable
5 surfaces Ads Manager, a reporting view, a spreadsheet, a doc and a chat thread. Only the change on the account lasts, and its reasoning is lost.
What I tried first

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.

OptionWhat it gaveWhere it brokeVerdict
Meta Automated Rules

Free, native, and 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, and no way to ask later what the value was before.

Kept, narrowly
Revealbot, Smartly and the rule-engine tools

Far 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.

Rejected
A reporting layer plus a spreadsheet

Complete 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 snapshot
Letting an AI agent hold the API token

The 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.

Rejected
The loop

Six named objects stand between a campaign signal and an account change

Each move hands a named object to the next. A frozen snapshot counts as evidence, and an analysis cites it for a finding. That finding becomes a reviewable recommendation, and only an approved plan reaches the account.

One campaign question, six objects each step hands the next one its context Scopecampaigns + dates Snapshotfrozen, reproducible Analysisfindings + evidence Experimentone variable, one metric Execution planapproved, then run Metathe account the green edge is where authority changes hands Everything left of it reads. Every agent-proposed change writes through the plan, and only after a person types the plan ID and then the word EXECUTE.
Analysis, recommendations and experiment design never touch the account. Write authority moves through a separate object that a person approves, and that is the precondition for pointing an automated system at a client’s ad account.
The product

Eight workspaces, and each one answers a different question

meta.hi-daniel.com/app
AdFlow campaigns dashboard listing campaigns with status, budget, conversions and spend
AdFlow performance reporting with KPI cards and campaign scope controls
AdFlow Campaign Analyst screen stating every finding must identify a campaign and evidence
AdFlow recommendations queue with review states
AdFlow execution plans screen
AdFlow experiments screen with control and variant cells
AdFlow settings screen showing the safety switches
AdFlow create campaign wizard
The agent

It builds the campaign, and it hands you a draft to approve

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 wizard, and a person checks that draft step by step before it reaches the account.

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. To make a recommendation real, you design an experiment, check the live setup, then generate a plan for someone to approve.

Deterministic code owns the numbers. The app calculates spend, results, CPA, contribution and outliers, and the model only explains them. Where the inputs support it, a confidence interval decides the winner. A language model never does.

50 campaigns per run · findings must cite the campaign and the evidence
What the agent may do
Draft campaign, ad sets, creative, copyyes
Read performance and explain ityes
Propose a recommendationyes
Change a live campaignnever
Declare an experiment winnernever
The guardrails

Six checks stand between an agent and a client’s ad account

Each one blocks a different failure: a change shape the route does not recognize, a value past the configured limit, an execution nobody approved, and a diff written against a number that already moved.

01

A narrow write surface

The controlled route accepts explicit campaign status and daily-budget changes and rejects any shape it does not recognize. The API client can do far more than the product will let it.

02

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.

03

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.

04

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.

05

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.

06

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.

One change, end to end

What happens when the account moved while you were deciding

A walkthrough of the case the whole structure exists for, and 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 can be measured. 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 reports the drift and asks for a fresh diff, so someone reviews the jump to $65 against the live $60, and whoever approves it is approving the change that runs.

The guardrail that matters is the one between the approval and the write
Latest-value check
Plan says before$50.00
Plan says after$65.00
Meta says now$60.00
Resultblocked
Built for an agency

Guardrails and agent skills are shared, campaign data and approvers stay per account

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. I am building toward one workspace per account, one set of guardrails, and an audit trail that survives the person who made the change.

The rules compound. Every campaign I have run taught me something about what breaks a Meta account, most of it from six years of media buying at ToLocal, 2015 to 2021, where I ran a $10M annual media budget at 80%+ ROI across paid social, DSP and affiliate. A budget jump trips a review, the wrong creative goes live, or a bulk edit hits the wrong ad set. Each of those becomes a guardrail or an agent skill.

5 roles · shared guardrails · an append-only audit the database refuses to edit
What compounds across clients
Guardrail thresholdsshared
Agent skills and recipesshared
Experiment templatesnext
Campaign data and auditper account
Approvers and rolesper account
Testing

A test has cells, one variable and a stopping rule, or it is just a change

meta.hi-daniel.com/marketing
AdFlow marketing page showing the four product objects and their authority
AdFlow experiments marketing page
AdFlow intelligence marketing page
AdFlow platform marketing page
Under it

What it runs on

Analysis reads frozen snapshots, so I can reproduce a finding weeks later. The cache key is hashed from the account, the resource and a normalized scope. Execution reads live, every time, immediately before the write.

Application

Next.js logoNext.js 16App Router, route handlers, and the proxy boundary, running as one process. React logoReact 19Client and server components across the eight workspaces. TypeScript logoTypeScript 5Data contracts, route handlers, and the shape of every workflow object. Vercel logoVercelHosting for the public read-only demo.

Data

SQLite, WAL modeSettings, frozen snapshots, workflow objects, execution attempts and the append-only audit table. Meta logoMeta Graph APICampaigns, insights, breakdowns, targeting, audiences and creatives, plus the supported writes.

Models

OpenAI logoOpenAIOptional narrative layer, low temperature, explaining evidence the code already calculated. Gemini logoGeminiThe alternate provider. If either call fails, the deterministic analysis still stands. No UI frameworkCSS modules, no Redux, no component library. I style the dense operator screens myself and keep the dependency list short.
Where it stands

What is running, and what I am not claiming

A working product with a public demo. I name the parts that are missing.

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, every route enforces roles the same way, and the remaining manual write paths move behind the same plan safety model.

Not claimed

No client performance numbers. I am the only person who operates it. The guardrails are designed against the failure modes I have seen rather than validated against a published incident rate.

The system, in numbers
Workspaces8
Campaigns per analysis run50 max
Roles5
Write switches, all required3
Data statescompleted, partial, failed

Want this pointed at your ad account?

The demo is public and read-only. Walk the eight workspaces, read an execution plan diff and its guardrail status, and see what the approval gate on a Meta account looks like.