Loom

Type to search across the guides, specification and decision records.

↑↓ navigate ↵ open esc close Pagefind

Guides

Quotas, supervision and cancellation

Part of the Loom User Guide, section 17 (Loom 2.0 kernel hardening). Bounding and supervising a running execution: resource accounting and quotas (K3), fault supervision (K4), cancellation and deadlines (K8), and the advisory pre-warming hint.

Resource accounting & quotas (K3)

meteringMiddleware meters each effect (tokens/$/latency) onto the log and enforces a budget by admission control.

import { meteringMiddleware, llmUsageTokens } from "@loom/middleware";

const metering = meteringMiddleware({
  pricing: ({ result, ms }) => ({ tokens: llmUsageTokens(result), costUsd: llmUsageTokens(result) * 3e-6, ms }),
  budget: { maxCostUsd: 5 },   // once spent, the next effect is denied (QUOTA_EXCEEDED)
});
const effectRuntime = new EffectRuntime([metering]);
// Running totals live in state.variables._resources (tokens / costUsd / ms / count / exceeded).

Fault supervision (K4)

Wrap any dispatcher with SupervisingDispatcher for restart/backoff + a circuit breaker that fails fast when a target is consistently down.

import { SupervisingDispatcher } from "@loom/dispatcher";

const dispatcher = new SupervisingDispatcher(childDispatcher, {
  policy: { maxRestarts: 2, backoffMs: 200, circuit: { threshold: 5, cooldownMs: 30_000 } },
});

Cancellation & deadlines (K8)

The kernel can reclaim running work — cooperatively where effects honor the signal, and by durable settlement everywhere else (the guarantee is the logged fact, not physical termination of third-party I/O).

// Kill an execution BY ID, wherever it stands:
await runtime.cancel(executionId, "operator kill");
// - live in this runtime → aborts the in-flight effect + durable EXECUTION_CANCELLED
// - suspended / on a presumed-dead node → FENCE-THEN-CANCEL: acquires a newer fence
//   token first (K9.4), so a zombie worker can no longer write, then appends the fact.
// Cancelled is terminal: resume() refuses, a second cancel returns false.

// Declarative deadlines — enforced by the kernel, anchored to LOGGED timestamps
// (a crash/recovery never resets the clock):
step$({ id: "call-api", …, timeoutMs: 30_000 });       // per step, anchored to its first STEP_STARTED
flow$({ id: "audit", …, deadlineMs: 10 * 60_000 });    // per run, anchored to EXECUTION_STARTED
await runtime.start(flow, input, { deadlineMs: 5_000 }); // per-dispatch override

A step timeout fails the step (STEP_FAILED, retriable by your flow logic); an execution deadline cancels the run (EXECUTION_CANCELLED). Effects receive the abort via ctx.signal (LLM effects forward it to the provider’s HTTP call automatically); effects that ignore it are settled durably anyway. Aborted effects are still metered (wall-time at minimum), so cancel-before-completion cannot evade a K3 budget, and the retry middleware treats abort as terminally non-retryable. Deadlines fire while a process is actively running the execution. A suspended execution is not cancelled while it sits idle: a resume re-arms the deadline from its logged anchor, so a budget that ran out while it was parked cancels the run at once. T1 timers (suspend({ timeout }), ctx.sleep) are separate and do fire across idle suspension.

Across the compute seam (K8.5): cancellation follows the execution wherever it runs — dispatcher.cancel(executionId) forwards the kill through the placement seam, and a remote HTTP worker exposes POST /cancel (RemoteWorkerRuntime.cancel). Delivery is best-effort by contract (an unreachable worker returns false, never throws); the settlement is durable either way — the orchestrator’s own runtime.cancel() fences-then-appends on the shared store, so even an undeliverable zombie ends fenced out with EXECUTION_CANCELLED on the log. A cancelled dispatch settles as a normal terminal result, never a retryable transport error.

Pre-warming (latency, advisory)

Cold starts live at I/O boundaries — a K7 child-process fork (~50ms), an LLM provider’s first HTTPS handshake, a Cloud Run cold instance. Pre-warming spins those up before the call, strictly in the advisory plane: it is latency-only, never emits or touches the fold (P10), and a failed warm silently falls back to a cold call. It cannot change what happens — only how fast.

// K7 — pre-spawn the isolated child at boot so the first call skips the fork:
new IsolatedToolEffect({ id: "fetch-metrics", modulePath, warm: true }); // ~54ms → ~2ms first call
// or call effect.warm() / runtime's effectRuntime.warm(toolId) at boot.

// LLM — keep the provider connection/model cache hot (provider implements warm()):
const provider = { async complete(req) { … }, async warm() { await this.keepAlive(); } };
// createLlmEffect wires effect.warm() → provider.warm().

// Scheduled flows — the occurrence time is deterministic, so warm the flow's first
// step just before it fires (hides cold-start behind the wait you already know is coming):
defineConfig({
  timers: { store, schedules: [nightlyAudit], warmLeadMs: 10_000 }, // warm 10s ahead
});

Use it only where the hidden latency is large and real (K7 children, LLM/remote connections, cloud workers) — warming the in-process hot paths (the fold, local stores, middleware) buys nothing. Mispredicted warming spends resources (an idle child, a needless connection), so it is opt-in and belongs on high-probability boundaries: a scheduled fire, or a tool you know every request hits. Loom deliberately keeps speculation out of the durable core — pre-warming rides the advisory Warmer/Effect.warm() seam, never the log.


Back to User Guide section 17.

Source: docs/user-guide/quotas-supervision-and-cancellation.md in the loom repository.