tao-loop
Iterates a generator step + judge step until the judge says done or the kill-switch fires. Returns a fully-populated LoopResult; never raises KillSwitchAbort to the caller.
When to trigger
- A user issues an autonomy-class brief that warrants more than one iteration.
- A higher-level orchestrator wants a budget-bounded, judge-gated worker loop rather than the wave-orchestrated path.
Public API
from app.server.tao_loop import run_until_done, LoopResult
result = await run_until_done(
goal="implement X",
workspace="/path/to/repo",
max_iters=10, # else honour TAO_MAX_ITERS
max_cost_usd=1.50, # else honour TAO_MAX_COST_USD
judge_every_n_iters=2, # cost-control knob
timeout_per_iter_s=600,
evt: ..., # streamed iter_complete payloads
)
# result.done; result.reason; result.iters; result.cost_usd;
# result.judge_history; result.final_state
Autoresearch envelope
The judge's score ∈ [0, 1] is the single termination scalar. The kill-switch
provides the orthogonal cost / iteration / hard-stop bounds.
Kill-switch dependency
RA-1966's LoopCounter is constructed once per loop. tick() advances iters
and adds cost atomically, raising KillSwitchAbort on any breach — captured
into LoopResult.reason.
CLI
python scripts/run_tao_loop.py --goal "..." --workspace /path --max-iters N --max-cost X --judge-every N
Lookahead mode (OM-1 / RA-1970)
Set TAO_OM1_ENABLED=1 for a 15-step default horizon, or TAO_PLANNER_HORIZON=1..20
explicitly. The loop decomposes the goal up front via the Opus orchestrator planner,
executes one step per iteration, and re-plans on stall or horizon exhaustion
(capped by TAO_PLANNER_MAX_REPLANS, default 2).
result = await run_until_done(
goal="implement X",
workspace="/path/to/repo",
planner_horizon=15, # or omit and rely on OM-1 / env
max_replans=2,
...
)
Status: GET /api/autonomy/status → planner block (mode, effective_horizon).