A skincare brand already had the data stack. Now its AI agents read it, and scale or pause campaigns inside its rules.
The brand had done the data work: a warehouse with dbt models, a semantic layer with the KPI definitions finance signed off, dashboards everyone trusted. Its AI agents read none of it. They called the ad platforms directly, judged campaigns on platform ROAS, and suggested changes nobody dared apply. We built the context layer on the stack they already had, without redefining a metric, and added the pieces that were missing. Now an agent tells profitable campaigns apart by finance's definition and scales or pauses them inside rules the growth lead set.
The situation
- The warehouse, the dbt models and the semantic layer were in good shape. Finance trusted every number on the dashboards.
- The agents didn't read any of it. They pulled the ad platforms' APIs and the store directly, got ROAS on each platform's own window, and never saw returns, product cost or shipping. “Profitable” meant whatever the platform said.
- The warehouse refreshed overnight. A campaign that spent its day's budget by 10 AM looked fine until the next morning.
- The scaling policy lived in a doc: scale winners in steps up to a ceiling, pause anything under the margin floor for three days, never touch a launch campaign. The agent had never read it, so people checked every suggestion by hand, and then stopped reading the suggestions.
Before the agent could act, it had to know
The agent could reason and use tools from day one. It became reliable once this list was written down: which information to trust, what the terms mean, which rules apply, and what it is allowed to do.
- Margin after ad spend, by finance's definition, straight from the semantic layer
- Returns and product cost from the warehouse models
- Each platform's full attribution window, so a two-day-old campaign isn't judged yet
- Today's spend against the daily budget, as of this hour
- The step size and the ceiling from the rule
- That the campaign isn't a protected launch
- How many days it has sat under the margin floor
- Stock on the products it sells, because a pause on an out-of-stock product is a different decision
- The before state, so it can be resumed
- Nothing. It can't. It stages the plan for the growth lead.
What they already had, and what we built on it
Where a system already gave the agent what it needed, we used it as it was. We built only what was missing.
The system, layer by layer
How a campaign gets scaled, or paused
- ScheduleEvery hour the agent reads spend so far today per campaign from the platforms, and margin after ad spend per campaign from the semantic layer, on each platform's full window.
- ContextFor each campaign it loads the products it sells, their stock cover, its launch or protected status, how many days it has sat under the floor, and what the agent changed last run.
- DecisionCode applies the rule, not the model. Over the margin floor for the window, with stock cover and headroom under the ceiling: a scale candidate. Under the floor for three days, not protected, not out of stock: a pause candidate.
- ActA scale within the step and the ceiling runs. A pause runs with the before state stored. Above the ceiling, or on a protected campaign, the plan goes to the growth lead with the evidence.
- VerifyThe platform is read back. The change, its source rows with sync time, and the rule that allowed it go on the record.
- OutcomeA week later the agent checks the result against what the plan expected, and the record is updated. The growth lead sees which rules are earning their keep.
The automation, in outline
{
"automation": "profitable-pacing",
"schedule": "hourly",
"metrics": { "margin_after_ads": "semantic:…", "spend_today": "live:…" },
"context": ["campaign.products", "stock.cover", "campaign.protected", …],
"condition": { … },
"plan": ["campaign.budget.scale", "campaign.pause"],
"policy": { "step": "…", "ceiling": "…", "requires_approval": ["above_ceiling", "protected"] }
}Each stateful automation is a typed contract: a trigger, a condition, the context it may read, the registered actions in its plan, and its policy. The model fills fields. Our code validates, resolves and binds. A person approves what the policy says needs approval. The full contract carries more than we show here.
Who can do what
- The semantic layer stays the owner of every definition. When finance changes the margin formula, the agent's next run uses it. Nothing is copied into the agent.
- Scaling runs inside a step and a ceiling per campaign per day. Pausing needs three days under the floor. Both numbers live in the rule, where the growth lead can change them without touching the agent.
- Launch campaigns are protected. A pause on an out-of-stock product is a different decision and goes to a person.
- The agent's identity reads the models and writes two actions. Nothing else. Revoking it takes one change in one place.
Bring us one workflow. We’ll start there.
We connect the systems you already run, write down what the agent must know before it acts, and start with recommendations before actions. The next workflow reuses what the first one built.