Skip to content

Budget guardrails

Budget guardrails cap the monetary cost of AI usage. They price every agent run from its token counts. They accumulate the spend of each scope over a period. When a run reaches a hard limit, they veto it before it starts.

  1. Prices live in uc_ai_model_pricing, as a cost per million tokens for each provider and model. You can therefore keep them current when a price changes.

  2. Budgets in uc_ai_budgets define a limit (limit_amount) for a scope over a period, plus an enforcement mode.

  3. Before a run, the budget hook sums current spend for every applicable budget. If a hard budget is at or over its limit, it raises ORA-20401 and the run never starts.

  4. After a run, the hook prices the whole execution tree: the top-level run and the nested agents. It writes one row for each run to the uc_ai_budget_exec_cost ledger.

UC AI knows the cost only for a model with a price row. UC AI Pro delivers a generated snapshot in budget/seed_pricing.sql. You can add a model, or overwrite one:

insert into uc_ai_model_pricing (
provider, model, input_cost_per_mtok, output_cost_per_mtok, reasoning_cost_per_mtok
) values (
'openai', 'gpt-5.6-terra', 2.00, 12.00, null -- USD per 1,000,000 tokens; reasoning falls back to output
);
commit;

For each (provider, model), the latest row with effective_from <= today wins. To prepare a price change, insert a row with a future date.

The snapshot covers the models of anthropic, openai, google, xai, mistral, and openrouter. It has no row for an OCI model, and no row for a local Ollama model. It also has no row for a model that the public model catalogs no longer list, for example claude-3-opus-latest or gemini-2.0-flash. For one of these models, you must add a price row yourself.

A budget is a row in uc_ai_budgets. This example is a hard $100 monthly cap for one APEX app. It warns at 80%:

insert into uc_ai_budgets (
code, description, scope_type, scope_value, period,
limit_amount, enforcement_mode, warn_threshold_pct
) values (
'APP100_MONTH', 'Monthly cap for the support app',
'app', '512', -- scope_value is the APEX application id
'month', 100, 'hard', 80
);
commit;

A few more shapes:

-- Per-user daily soft cap (warns, never blocks)
insert into uc_ai_budgets (code, scope_type, scope_value, audience, period, limit_amount, enforcement_mode)
values ('USER_DAY_SOFT', 'user', 'ANNA', 'any', 'day', 5, 'soft');
-- Track total spend for one agent, no enforcement
insert into uc_ai_budgets (code, scope_type, scope_value, audience, period, limit_amount, enforcement_mode)
values ('TRANSLATOR_TOTAL', 'agent', 'translator', 'any', 'total', 999999, 'advisory');
-- Organization-wide hard monthly cap
insert into uc_ai_budgets (code, scope_type, scope_value, audience, period, limit_amount, enforcement_mode)
values ('ORG_MONTH', 'global', null, 'any', 'month', 2000, 'hard');
-- Each anonymous visitor can spend $0.10 a day (one bucket per browser session)
insert into uc_ai_budgets (code, scope_type, audience, period, limit_amount, enforcement_mode)
values ('PUB_SESSION_DAY', 'apex_session', 'public', 'day', 0.10, 'hard');
-- ...and anonymous traffic together can spend $20 a day across the app
insert into uc_ai_budgets (code, scope_type, scope_value, audience, period, limit_amount, enforcement_mode)
values ('PUB_APP_DAY', 'app', '512', 'public', 'day', 20, 'hard');
-- Each logged-in user can spend $5 a day (one row covers everybody)
insert into uc_ai_budgets (code, scope_type, audience, period, limit_amount, enforcement_mode)
values ('AUTH_USER_DAY', 'each_user', 'authenticated', 'day', 5, 'hard');
commit;
periodWindow
dayCalendar day (from midnight)
weekISO week (from Monday)
monthCalendar month (from the 1st)
totalAll time — no reset

When a run exceeds a hard budget, the caller of execute_agent gets this error:

ORA-20401: Budget "APP100_MONTH" exceeded: spent 100.4213 of 100

A per-caller budget also names the bucket that it denied:

ORA-20401: Budget "PUB_SESSION_DAY" exceeded: spent .1042 of .1 (apex_session 40218...)

uc_ai_budgets has the same audience column and the same per-caller scopes apex_session and each_user as the rate limits. You therefore configure the money side of “anonymous visitors get a little, logged-in users get more” in the same way. The shared recipe has the reasons and the traps.

A public budget prices only anonymous runs. The PUB_APP_DAY row above is therefore a $20 daily ceiling on anonymous spend. Employees in the same app cannot consume it, and visitors cannot consume the allowance of the company.

The budget API answers spend and forecast questions without running an agent.

-- Current spend and projected period-end spend for a scope
select uc_ai_budget_api.spend('user', 'ANNA', 'month') as spent_so_far,
uc_ai_budget_api.forecast('user', 'ANNA', 'month') as projected_month_end
from dual;
-- How much have anonymous visitors cost this month, in total?
select uc_ai_budget_api.spend('app', '512', 'month', systimestamp, 'public') as anonymous_spend
from dual;
-- ...and one specific visitor?
select uc_ai_budget_api.spend('apex_session', '40218...', 'day') as this_visitor_today
from dual;
-- Estimate a rollout before you build it:
-- 10,000 calls averaging 1,500 in / 500 out tokens on gpt-5.6-terra
select uc_ai_budget_api.estimate('openai', 'gpt-5.6-terra', 10000, 1500, 500) as projected_cost
from dual;

Ready-made views drive dashboards and chargeback reports:

ViewShows
uc_ai_v_budget_statusEvery active budget: spend, forecast, % of limit, remaining, and ok/warn/over/per_caller state
uc_ai_v_budget_bucketsPer-caller budgets, with one row for each visitor or user
uc_ai_v_execution_costsCost detail of each run, joined to the run rows (with audience and apex_session_id)
uc_ai_v_usage_by_userDaily token + cost rollup per user
uc_ai_v_usage_by_agentDaily token + cost rollup per agent
uc_ai_v_usage_by_appDaily token + cost rollup per APEX app
-- The "plan ahead" screen: which budgets are close to their limit?
select code, audience, scope_type, scope_value, is_dynamic, period,
spend, limit_amount, pct, forecast_period_end, state
from uc_ai_v_budget_status
order by pct desc nulls last;
-- Which individual visitors / users have spent their allowance?
select code, scope_type, bucket_value, spend, limit_amount, pct, state
from uc_ai_v_budget_buckets
order by pct desc nulls last;