Tutorial - Bound a Run with Autonomy Budgets
Goal: run a Touba program with explicit run limits and observe a refusal before execution exceeds the declared perimeter.
Autonomy budgets (BQ-1) cover run duration, steps, tool calls, agent invocations, and trigger quotas. They do not measure tokens, vendor costs, or distributed quotas.
1. Create a Simple Program
mkdir -p budget-demo
cd budget-demo
module examples.budget_demo
limits run
max_run_ms as 30000
max_steps as 20
max_tool_calls as 5
max_agent_invocations as 3
max_provider_calls as 4
skill BuildMessage
description "Display a message and return the completed value."
gives Text
do
show
with message as "budget demo"
give "done"
strategy RunBudgetDemo
gives Text
uses BuildMessage
do
BuildMessage
into result
give result
2. Compile
touba compile budget-demo.tb --out budget-demo.air.json
3. Run with a Sufficient Budget
touba run budget-demo.air.json \
--entry strategy:examples.budget_demo/RunBudgetDemo \
--output all \
--trace-out budget-demo.trace.json
Expected output:
budget demo
The trace should contain budget-consumption events.
4. Run with a Budget That Is Too Strict
if touba run budget-demo.air.json \
--entry strategy:examples.budget_demo/RunBudgetDemo \
--max-steps 1 \
--output json > refused.json; then
exit 1
else
test "$?" -eq 1
fi
node --input-type=module -e 'import assert from "node:assert/strict"; import {readFileSync} from "node:fs"; const r=JSON.parse(readFileSync("refused.json","utf8")); assert.equal(r.reason,"StepBudgetExceeded"); assert.deepEqual(r.messages,[]); assert.equal(r.result,null); console.log("STEP_BUDGET_REFUSED_OK");'
Expected result:
budget error [...]
The refusal must arrive as an observable runtime event. The goal is not to hide the failure, but to show that autonomy is bounded by contract.
5. Inspect a Budget Trace
touba inspect budget-demo.trace.json
You should see runtime limits and consumption. Touba does not infer financial cost from this information.
Variant with Manifest
A host can also declare limits in the manifest.
{
"manifest_version": "touba-manifest-v1",
"run_limits": {
"max_steps": 20,
"max_tool_calls": 5,
"max_agent_invocations": 3,
"max_provider_calls": 4
}
}
The runtime refuses when the manifest attempts to widen a stricter budget already declared in AIR.
Validated Contract
Autonomy budgets provide an observable execution boundary. The runtime can refuse a loop, call, or configuration that exceeds the declared perimeter.
The following command actually exercises the manifest above:
touba run budget-demo.air.json --entry strategy:examples.budget_demo/RunBudgetDemo \
--manifest touba.manifest.json --output json > manifest-result.json
node --input-type=module -e 'import assert from "node:assert/strict"; import {readFileSync} from "node:fs"; const r=JSON.parse(readFileSync("manifest-result.json","utf8")); assert.equal(r.status,"success"); assert.equal(r.result,"done"); assert.ok(r.trace.events.some(e=>e.kind==="budget_limit_checked" && e.payload.budget_kind==="max_steps")); console.log("MANIFEST_BUDGET_OK");'
This program declares its limits with limits run. The CLI and manifest can tighten them. Limits grant no additional tools or scopes. max_provider_calls counts orientation, selection, runtime-controlled retries and finalization, not tokens or financial cost.