Programs/Limits

Limits

Every guest instruction — CPython's interpreter loop included — is wasm compiled by wasmtime, so all of it can be counted and bounded. A runaway program is a clean, typed failure, never a hung process, and the outcome and its metrics land in the trace.

The kernel is fresh for every invocation, so long-lived work belongs in records: save a cursor, finish a bounded batch, continue in a later scheduled run.

The bounds

Limit Mechanism Character
instruction budget fuel — a per-block counter decremented at compile time; zero traps at exactly that instruction deterministic and replayable: same code + inputs = same cutoff
wall timeout epoch deadline — a load+compare at function entries and loop back-edges; a ticker bumps the epoch wall-clock driven, lands inside any guest loop
hard break the run's interrupt flag, checked on every epoch tick always lands; the tool for cancellation

Fuel budgets; the epoch cancels. Epoch checks run only in guest code — inside a host function (an effect) interruption is cooperative, and the effects honor it: HTTP calls carry timeouts, and a blocked shell command is killed when the run is interrupted, so no un-cancellable path remains. No separate memory cap is configured; an allocation that cannot grow the guest's linear memory surfaces as an ordinary MemoryError.

Defaults

Setting Value
fuel per run 50 billion instructions — tens of seconds of pure compute; a hard runaway ceiling, not a working budget for ordinary jobs
wall timeout 120 s for anyrt run (--timeout-s); 3600 s for runs under anyrt serve
epoch tick 10 ms
blob spill threshold 64 KB per recorded value

What exhaustion looks like

Fuel exhaustion surfaces as a typed FuelExhausted error whose message says what works: split the work into smaller chunks and check fuel.state in long loops. The trap is deterministic, so a verbatim retry can never succeed; in a conversation the runtime posts the typed error into the chat so the next turn acts on it. A wall timeout ends the run as an error too. Only a hard break ends it interrupted. The verdict lands in the run's terminal cell record:

{"kind": "cell", "seq": 23, "cell": "main", "ok": false, "interrupted": false,
 "error": {"type": "FuelExhausted", "message": "run exceeded its compute budget …"},
 "metrics": {"fuel_used": 50000000000, "duration_ms": 31877}}

For a trigger run, the run summary's status is FAILED (or interrupted after a hard break), the trigger's lastStatus is error, and the trigger's circuit breaker counts it — see Runs and monitoring.

Checkpointing long jobs

Long data jobs avoid the cliff cooperatively. The fuel.state syscall returns {remaining, budget}, refreshed by the epoch ticker (so up to one tick stale — a checkpoint signal, not an exact meter), and recorded like any effect so replay stays stable:

JOB = "my-sync"

def main(args):
    c = use("agent:any@v1")
    space, brain = c.bao_space(), c.get_brain()["objectId"]
    rows = c.query(space, brain, "agent_job_state", filter={"id": JOB}, limit=1)
    cursor = rows[0].get("cursor", 0) if rows else 0
    for page in pages_from(cursor):              # your own paging helper
        process(page)
        cursor = page["next"]
        f = effect("fuel.state", {})
        if f["remaining"] < f["budget"] * 0.15:  # checkpoint, then exit cleanly
            c.upsert_record(space, brain, "agent_job_state", JOB, {"cursor": cursor})
            return {"ok": True, "resumed_at": cursor, "partial": True}
    c.upsert_record(space, brain, "agent_job_state", JOB, {"cursor": cursor})
    return {"ok": True, "partial": False}

Pair this with a cron trigger and the job drains itself across runs, each one budgeted.

Metrics are always recorded

Each run's terminal cell record carries fuel_used and duration_ms; each effect record carries meta.durMs, and each llm.chat span its token usage. anyrt trace show --stats renders per-turn tokens, cache and cost; anyrt trace stats gives p50/p95 distributions and a fuel-ceiling suggestion over every stored run. Capacity decisions are made from these numbers.

Other constraints

  • Single-threaded, synchronous Python. No async, no threads. Concurrency is the host's job — batch fan-out on Effects.
  • Guest memory lasts for one run. Each run gets a fresh kernel; assignments persist across the model's cells within that run. Records, program source, and checkpoints written to the database survive it.
  • The value store is uncapped — guest memory is its backstop.
  • oauth.connect blocks up to 120 s by default on a run thread; never call it from a cron program.

Note. In-process enforcement is complete for honest code: nothing ambient is reachable, so accidental effects and accidental nondeterminism are structurally impossible. The wasm cage is the substrate; the same syscall surface is what any future host implements.