Skip to main content
Version: 1.0.0

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​

Terminal
mkdir -p budget-demo
cd budget-demo
budget-demo.tb
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​

Terminal
touba compile budget-demo.tb --out budget-demo.air.json

3. Run with a Sufficient Budget​

Terminal
touba run budget-demo.air.json \
--entry strategy:examples.budget_demo/RunBudgetDemo \
--output all \
--trace-out budget-demo.trace.json

Expected output:

Output
budget demo

The trace should contain budget-consumption events.

4. Run with a Budget That Is Too Strict​

Terminal
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:

Summary
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​

Terminal
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.

touba.manifest.json
{
"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:

Terminal
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.