Tempio Docs
Plans

The allocator

The allocator turns phases and envelopes into today's budgets. It reads what every campaign wants, funds them in order under the caps you set, and writes the moves as drafts. It moves no money itself: what it produces is change requests at the gate, like every other write in Tempio.

It is off in every workspace until somebody turns it on, in Settings → Approvals, beside the rules it is held to. The switch asks first: Turn on automatic budget moves? says Tempio will draft budget moves between campaigns each day and that the rules you wrote clear the ones they cover without you, and the switch stays where it was until you press Turn on. Turning it off is one press. The section reads:

Automatic budget moves

Once a day, at the hour you pick in this workspace's reporting time zone, the allocator reads every active campaign's envelope and the phase it is in, funds them in phase order under your daily cap, and drafts the moves as one budget batch. It drafts and never applies: the batch waits at the gate, approved by you, or by a rule you wrote.

The same section carries the hour it runs at and a link that says Write a policy that approves its batches — "A rule over update_budget, within the amounts you allow, is what makes its batches hands-off."

Before it runs: a cap somebody chose

The allocator funds everything under the workspace's daily cap, and that one number decides every throttle it makes. If the workspace has written no guardrail of its own, so the cap resolves to Tempio's default for the currency, the run refuses and writes nothing: it names the default it would have used and asks you to set a workspace guardrail in Settings → Guardrails first.

The refusal does not burn the day. Set the cap and the next run works the same hour. A dry run answers regardless — it tells you where the cap came from, which is usually how a workspace finds out it never set one.

What it reads

  • Every active campaign carrying an enabled envelope. A campaign without one has not been handed to the allocator at all.
  • The phase covering today, and its multiplier.
  • Each campaign's goals and their verdicts over their own windows.
  • The workspace's resolved daily cap, and each account's.
  • The guardrail's maximum budget movement per day.
  • Whether a campaign has at least seven days with spend, which is the floor below which its goals say nothing.

How it decides, in one pass

  1. What each campaign wants. The envelope times the multiplier of today's phase. A campaign with no phases at all wants its whole envelope; one whose phases have all ended wants nothing.
  2. What its goals do to that. A campaign missing a goal whose action is propose is held at today's budget — never raised, because a campaign missing its number is not the one to scale, and never lowered here, because throttling is the funding pass's job. A campaign beating an at_most propose goal by more than a fifth becomes raise-eligible. Below the seven-day floor nothing is said either way: a cost per acquisition computed over two days is not a measurement.
  3. The order. closing first, then launch, then custom, then hold, then a campaign with an envelope and nothing said about when it is hot. Within a kind: raise-eligible first, then priority (lower first), then goal margin (best first), then the campaign's id — that last key is what makes the pass deterministic, so the same inputs give the same answer every run.
  4. Funding. Down the order until the workspace cap runs out, holding each account under its own cap as well. Whatever is below the line is throttled to what is left. A campaign denominated in a currency the workspace cap is not in is held to its account's cap alone and named in the report; money never crosses currencies here.
  5. The clamp and the floors. Every move is held to the guardrail's maximum movement in a day, rounded to the currency's minor unit. A move smaller than one percent of what the campaign is running, or smaller than 100 minor units, is dropped — below that it costs a reviewer more attention than it can be worth, and a batch full of them teaches a workspace to approve without reading. A budget of zero is never drafted: that is a pause, and a pause is a person's act.
  6. The drafts. One update_budget batch per connection, one row per campaign that moved, at most fifty moves in a run: past that a campaign reads batch_limit and is left for tomorrow. Each batch is reviewed and applied as a unit, and it passes every guardrail and approval chain any other draft passes.

Only campaigns whose budget lives at campaign level are moved. On a campaign budgeted at ad-group level the campaign figure is a sum of its children rather than a field, and writing to it would replace every ad set's own budget — so such a campaign is loaded, named in the report under budget_not_at_campaign, and left alone.

Why a campaign ended where it did

Every campaign the allocator looked at appears in the report, moved or not, with one of these reasons.

ReasonWhat happened
fundedIt got what it wanted, and the budget moved
throttledThe cap ran out above it, so it got less
phases_endedEvery phase has ended, so it wants nothing
goal_missedA propose goal is being missed; held at today's budget
unchangedIt wants what it is already running
below_floorThe move was smaller than one percent, or than 100 minor units
clampedThe movement guardrail left it where it was
no_current_budgetNo daily budget on the platform to move
no_account_capIts account resolved no cap, so there is no ceiling to fund it under
cannot_zeroFunding it would mean drafting a budget of zero
batch_limitBeyond the run's fifty-move limit
budget_not_at_campaignIts budget does not live at campaign level

Alongside them the report carries the cap and where it came from, the sum desired against the sum funded, the funding order itself, and per campaign the phase, the multiplier, the goal that decided it and its priority.

A day, in numbers

A workspace whose daily cap is A$1,000.00, with a movement guardrail of 100 % and two campaigns on one account whose own cap is A$1,200.00.

CampaignPhase todayEnvelopeWantsRunning at
Autumn DropClosing, 160 %A$400.00A$640.00A$400.00
EvergreenHold, 40 %A$900.00A$360.00A$500.00

Closing funds before hold, so Autumn Drop takes A$640.00 of the A$1,000.00 and Evergreen is funded at A$360.00 out of the A$360.00 remaining — both get what they wanted. The moves are A$400.00 → A$640.00 and A$500.00 → A$360.00; both are inside the 100 % movement clamp and well above the floors, so both are drafted, in one batch against that connection.

Raise Autumn Drop's envelope to A$700.00 and the closing push wants A$1,120.00. It is funded at A$1,000.00 — the whole workspace cap — and reads throttled. The row that is actually drafted is A$800.00, not A$1,000.00: the movement guardrail allows 100 % of what the campaign is running today, so A$400.00 can at most double in a day, and funding and drafting are two different numbers whenever the clamp binds. Nothing is left for Evergreen, and funding it at nothing would mean drafting a budget of zero, which is a pause rather than a budget move: no row is written for it and the report reads cannot_zero.

Back at the first pair, give Autumn Drop a cost-per-acquisition goal it is missing with the action propose. It is held at the A$400.00 it is already running rather than raised to A$640.00, so there is no move to draft and the report reads goal_missed — the reason it wanted less, kept over the reason nothing happened.

The record of a run

The allocator is its own ledger, on the audit log:

RowWhen it is written
planner.runOnce, before any drafting, claiming the day. A second run the same day is refused against it
planner.draftedOnce per batch that landed, with its correlation id and how many moves it carried
planner.blockedOnce per connection whose batch the gate refused, with the refusal. The run carries on to the other connections
planner.run_completeLast, with what the run actually drafted

The claim says what the run intended; the terminal row says what it produced. A day that planned twelve moves and drafted none is a state the claim alone could never describe, which is why both are written. The report lives on the planner.run row and in the answer propose_reallocation gives — a batch of drafts carries the moves, not the reasoning.

Making it hands-off, and turning it off

Autonomy here is a dial, not a switch. The allocator drafts; what clears those drafts is an approval policy you write over update_budget, within the amounts and on the accounts you name. Inside those bounds a batch clears on its own and the record says a rule cleared it; outside them it waits for a person. Either way it is a change request first, and either way it is reversible.

Turning it off is the same switch that turned it on. Its drafts are ordinary drafts: anything already at the gate stays there, to approve or reject.

Over MCP

RouteCapabilityScope
allocation.proposepropose_reallocationdraft

propose_reallocation runs the same pass on demand. With dryRun it answers the batch it would draft — the moves, the throttles and the whole report — and writes nothing at all; without it, it drafts, under the same day ledger as the scheduled run. Neither form applies anything.

An agent asked to review the pace is best pointed at the pace_review prompt, which reads the timeline, expands the campaigns that are off pace and ends at this capability in dry run. The MCP reference has both.