Cloud spend caps example¶
Simon Willison argues that pay-per-use services should ship with hard budget caps on by default: when spending reaches the limit the service stops, and removing the cap takes an explicit opt-in. Coding agents make it easy to deploy things without thinking about cost, so a runaway service can run up a large bill overnight.
The provider enforces the cap at runtime. This example checks the agent's side before anything runs: every deploy carries a cap, the caps fit the user's budget, and the opt-out is not used without the user agreeing to it.
Trusted module¶
deploy requires a positive cap, so an uncapped deploy cannot be written.
remove_spend_cap is the opt-out. Both declare
successor-state axioms over a Capped fluent.
estimate_monthly_cost is non-negative but unbounded above.
examples/cloud/tools/cloud/trusted/effects.py
import clauz3
from clauz3.fluent import effect, fluent
# Successor-state fluent: a service is capped unless this program removes its
# cap. ``deploy`` always installs a cap; ``remove_spend_cap`` is the explicit
# opt-out ("I will be responsible for subsequent charges"). Contracts in
# ``contracts.py`` query the final valuation, so an agent may lift a cap
# mid-program only if a later deploy restores one.
Capped = fluent("capped", key=str, value=bool, initial=True)
@clauz3.ensures(lambda result: result >= 0, message="estimate must be non-negative")
@clauz3.trusted
def estimate_monthly_cost(service: str) -> int:
"""MOCK trusted cost estimate for ``service`` in whole USD per month.
Contract: the returned estimate is non-negative. Nothing bounds it from
above, so a cap computed from it must be clamped by the agent.
"""
return 0
@clauz3.requires(
lambda service, spend_cap_usd: spend_cap_usd > 0,
message="spend_cap_usd must be positive",
)
@clauz3.trusted
@effect(lambda service, spend_cap_usd: Capped.set(service, True))
def deploy(service: str, spend_cap_usd: int) -> None:
"""MOCK trusted deploy with a hard monthly spend cap.
The provider halts ``service`` once its monthly spend reaches
``spend_cap_usd``. Contract: the cap is positive; how high it may go is
an agent-stated guarantee. Records ``Capped[service] = True``.
"""
pass
@clauz3.requires(lambda service: len(service) > 0, message="service must be non-empty")
@clauz3.trusted
@effect(lambda service: Capped.set(service, False))
def remove_spend_cap(service: str) -> None:
"""MOCK trusted removal of a service's hard spend cap.
After this call the provider bills without limit and will not shut the
service down. Records ``Capped[service] = False``.
"""
pass
examples/cloud/tools/cloud/trusted/contracts.py
"""Cloud-spend predicates built from generic trusted effect facts.
Inspired by Simon Willison's case for hard budget caps on by default
(https://simonwillison.net/2026/Oct/3/default-hard-budget-caps/). The provider
enforces a cap at runtime; these contracts let a user check, before anything
runs, that an agent's deploys carry caps and that the caps are sane.
"""
from tools.cloud.trusted.effects import deploy, remove_spend_cap
from clauz3.spec import ContractSpec, contract, effect
from .effects import Capped
Deploy = effect(deploy)
RemoveCap = effect(remove_spend_cap)
@contract
def cap_at_most(max_usd: int) -> ContractSpec:
"""Guarantee every deploy's monthly spend cap is at most ``max_usd``."""
return Deploy.all(lambda d: d.spend_cap_usd <= max_usd)
@contract
def total_caps_at_most(max_usd: int) -> ContractSpec:
"""Guarantee the deploy caps sum to at most ``max_usd``.
The sum counts every deploy, so redeploying a service counts its cap
again; that over-approximates and fails closed. This bounds the
worst-case monthly bill only while every service stays capped: pair it
with ``never_remove_caps()`` or ``all_services_capped_at_end()``, since a
later ``remove_spend_cap`` is not visible to the sum.
"""
return Deploy.sum(lambda d: d.spend_cap_usd) <= max_usd
@contract
def only_services(allowed: list[str]) -> ContractSpec:
"""Guarantee every deploy targets a service in ``allowed``."""
return Deploy.all(lambda d: d.service in allowed)
@contract
def never_remove_caps() -> ContractSpec:
"""Guarantee no spend cap is ever removed, even temporarily."""
return RemoveCap.empty()
@contract
def all_services_capped_at_end() -> ContractSpec:
"""Guarantee no service is left uncapped once the program finishes.
A cap may be removed partway through as long as a later ``deploy``
restores one before the end.
"""
return Capped.final.all(lambda s: s.value == True) # noqa: E712
Clamping a computed cap¶
A cap derived from the estimate must be clamped. Without the clamp the prover finds a counterexample: any estimate of 50 or more pushes the cap past the bound.
examples/cloud/cases/estimate_clamped_pass.py
# ruff: noqa: F821
from tools.cloud.trusted import contracts as cloud
from tools.cloud.trusted.effects import deploy, estimate_monthly_cost
import clauz3
@clauz3.guarantee(cloud.cap_at_most(100))
def main() -> None:
headroom = 2 * estimate_monthly_cost("api")
if headroom > 100:
deploy("api", 100)
elif headroom > 0:
deploy("api", headroom)
else:
deploy("api", 1)
examples/cloud/cases/estimate_unclamped_fail.py
# ruff: noqa: F821
from tools.cloud.trusted import contracts as cloud
from tools.cloud.trusted.effects import deploy, estimate_monthly_cost
import clauz3
@clauz3.guarantee(cloud.cap_at_most(100))
def main() -> None:
headroom = 2 * estimate_monthly_cost("api")
deploy("api", headroom + 1) # unclamped: a large estimate exceeds the cap
Per-service and total budgets¶
cap_at_most bounds each service. The user's budget is usually for the whole
bill, which is what total_caps_at_most bounds. Four services capped at 50
each pass the first and fail the second:
examples/cloud/cases/total_caps_fail.py
# ruff: noqa: F821
from tools.cloud.trusted import contracts as cloud
from tools.cloud.trusted.effects import deploy
import clauz3
@clauz3.guarantee(cloud.cap_at_most(50))
@clauz3.guarantee(cloud.total_caps_at_most(150))
def main() -> None:
# Each service's cap is within the per-service bound; together they are not.
deploy("api", 50)
deploy("worker", 50)
deploy("scheduler", 50)
deploy("cron", 50)
The sum counts every deploy, so redeploying a service counts its cap twice. That over-approximates the bill, which is the safe direction.
Cap bounds need an end-state guarantee¶
Bounding the caps does not stop the agent removing one afterwards. This
program proves against both cap bounds, yet api ends up billing without
limit:
examples/cloud/cases/cap_bounds_then_removed_pass.py
# ruff: noqa: F821
from tools.cloud.trusted import contracts as cloud
from tools.cloud.trusted.effects import deploy, remove_spend_cap
import clauz3
# Proves: cap bounds only constrain deploy caps. They do not see the later
# removal, so the service ends up billing without limit. See the paired
# _fail case for the guarantee that closes this gap.
@clauz3.guarantee(cloud.cap_at_most(100))
@clauz3.guarantee(cloud.total_caps_at_most(150))
def main() -> None:
deploy("api", 50)
remove_spend_cap("api")
Adding all_services_capped_at_end() (or never_remove_caps()) rejects it.
State one of them whenever the user's budget must actually hold:
examples/cloud/cases/cap_bounds_then_removed_fail.py
# ruff: noqa: F821
from tools.cloud.trusted import contracts as cloud
from tools.cloud.trusted.effects import deploy, remove_spend_cap
import clauz3
@clauz3.guarantee(cloud.cap_at_most(100))
@clauz3.guarantee(cloud.total_caps_at_most(150))
@clauz3.guarantee(cloud.all_services_capped_at_end())
def main() -> None:
deploy("api", 50)
remove_spend_cap("api") # the end-state guarantee rejects this
Removing a cap¶
never_remove_caps() forbids the opt-out anywhere in the trace.
all_services_capped_at_end() is a state contract: a cap may be lifted for a
one-off job as long as a later deploy restores one.
examples/cloud/cases/capped_at_end_pass.py
# ruff: noqa: F821
from tools.cloud.trusted import contracts as cloud
from tools.cloud.trusted.effects import deploy, remove_spend_cap
import clauz3
@clauz3.guarantee(cloud.all_services_capped_at_end())
def main() -> None:
# Lift the cap for a one-off backfill, then redeploy with a cap.
deploy("api", 50)
remove_spend_cap("api")
deploy("api", 50)
examples/cloud/cases/capped_at_end_fail.py
# ruff: noqa: F821
from tools.cloud.trusted import contracts as cloud
from tools.cloud.trusted.effects import deploy, remove_spend_cap
import clauz3
@clauz3.guarantee(cloud.all_services_capped_at_end())
def main() -> None:
deploy("api", 50)
deploy("worker", 20)
remove_spend_cap("worker") # worker is left billing without limit
Limits¶
The contracts cover the deploys in one program. A provider's cap applies to spending over a billing period across many runs, which needs state carried between runs. That is not modeled here.
All cases¶
Browse the full set on the all-cases page.
How they run¶
examples/cloud/Justfile
trusted := "tools/cloud/trusted"
prove := "uv run clauz3 prove --trusted-root " + trusted
# Proves each case in one process: *_pass.py must prove, *_fail.py must not.
prove-cases := "uv run python -m clauz3._prove_cases --trusted-root " + trusted
test: lint cases
lint:
uv run clauz3 lint {{trusted}}/effects.py
cases:
{{prove-cases}} cases/*_pass.py cases/*_fail.py