Outcome Contracts

Bind every task to a goal, a budget, and required evidence — so the agent stops or escalates before it overspends.

An Outcome Contract is an agreement BudgetAI makes before a task runs. It defines what success means, how much the task may cost, and what proof it must produce. This is what turns "an agent that chats" into "an agent that is accountable."

Why contracts

Most agents will happily burn tokens chasing a goal with no ceiling and no definition of done. A contract replaces that open-ended behavior with explicit limits:

  • A goal that can be checked.
  • A budget on cost, time, and tool rounds.
  • Evidence the agent must return.
  • A breach policy — what to do when a limit is about to be crossed.

Anatomy of a contract

[contract]
goal      = "tests pass in ./api"
done_when = "pytest -q exits 0"
 
[budget]
max_usd     = 0.25
max_rounds  = 8
max_minutes = 4
 
[evidence]
require = ["test_log", "diff"]
 
[on_breach]
action = "escalate"  # stop | escalate | ask

Fields

FieldPurpose
goalHuman-readable objective
done_whenA checkable success condition
max_usdHard spend ceiling for the task
max_roundsMaximum tool-call rounds
max_minutesWall-clock limit
evidenceArtifacts that must be produced
on_breachstop, escalate, or ask when a limit is hit

Running under a contract

Attach a contract from the CLI:

budgetai agent -m "Make the api tests pass" \
  --max-usd 0.25 --done-when "pytest -q" --on-breach escalate

Or reference a file:

budgetai agent -m "Ship the fix" --contract ./contract.toml

Breach behavior

When BudgetAI projects that the next step would break a limit, it follows on_breach:

  • stop — halt and return partial work plus the receipt.
  • escalate — move to a higher tier or ask for approval to continue.
  • ask — pause and request a human decision.

A contract is a ceiling, not a target. BudgetAI still tries to finish as cheaply as possible — the budget only defines where it must stop trying silently.