How LoopX Manages Quota Allocation and Compute Budgets for Long-Running Agent Goals

LoopX enforces compute budgets through a fractional quota system (0-1) that translates into time-based slots within a rolling window, tracking consumption via runtime events to determine whether an agent is eligible, throttled, or paused.

LoopX controls autonomous agent resource consumption through a deterministic quota system implemented in the huangruiteng/loopx repository. The system converts high-level compute budgets into granular slot allocations, ensuring long-running agent goals remain bounded and observable. This article examines how LoopX quota allocation works, from payload configuration to runtime state enforcement.

The Three Pillars of LoopX Quota Management

LoopX quota allocation rests on three interconnected concepts: fractional compute budgets, slot-based accounting, and rolling window constraints.

Fractional Compute Quotas

Every goal carries a compute quota—a fractional value between 0 and 1 that represents the percentage of available compute the agent may consume. The system uses DEFAULT_COMPUTE_QUOTA (set to 1.0) as the baseline, clamps the value via _clamp_compute, and stores it in the goal’s quota.compute field. This implementation lives in loopx/quota.py at lines 97‑100.

Slot-Based Accounting

Compute consumption is measured in slots, where each slot represents a unit of time (defaulting to 1 minute). The system tracks both spent and voided slots through events generated during execution. The functions build_quota_slot_spend_event and build_quota_slot_void_event create these events in loopx/control_plane/quota/slot_accounting.py (lines 4‑12), while load_quota_event_from_run extracts them from run payloads. The ledger aggregation occurs in goal_quota_with_spend_ledger within loopx/quota.py (lines 33‑69), which sums spent slots and subtracts voided slots to determine actual consumption.

Rolling Window Constraints

Quota enforcement operates within a configurable rolling window (default 24 hours). The goal_quota_config function in loopx/quota.py (lines 94‑100) converts raw goal JSON into a normalized payload containing window_hours, slot_minutes, allowed_slots, and spent_slots. The allowed slots calculation follows this formula:


allowed_slots = round((window_hours * 60 / slot_minutes) * compute)

If the goal explicitly defines allowed_slots, that value overrides the computed default.

Computing the Quota Payload

When LoopX receives a goal, it first builds a normalized quota payload through goal_quota_config (lines 90‑99 in loopx/quota.py). This function:

  • Reads compute_quota (or the legacy compute field) and clamps it to [0, 1]
  • Determines the window length and slot granularity
  • Calculates the default allowed slots using the formula above

The resulting payload serves as the foundation for all subsequent quota decisions.

Updating Spent Slots from Runtime Events

During execution, each run may emit quota events that adjust the budget ledger. The function load_quota_event_from_run (lines 41‑45 in loopx/quota.py) extracts these events from run payloads.

The goal_quota_with_spend_ledger routine iterates over all runs belonging to the goal, discards those outside the current window, and aggregates:

  • spent_by_run[run_key] += slots for spend events
  • voided_by_run[voided_run_generated_at] += slots for void events

After aggregation, the routine subtracts voided slots from spent slots to compute the final payload["spent_slots"] value.

Deriving the Quota State

The quota_status function (lines 71‑121 in loopx/quota.py) evaluates the quota payload alongside runtime context—such as user gates, health severity, or focus-wait markers—to emit a discrete state:

  • eligible: Compute quota not exhausted; agent may run an automatic turn
  • throttled: spent_slots ≥ allowed_slots; agent paused until window slides
  • paused: compute == 0; all automatic turns disabled
  • operator_gate: Waiting on a user/controller gate; only non-gated actions run
  • focus_wait: Focus-wait marker present in lifecycle; delivery compute withheld
  • waiting: No Codex-ready work selected; no automatic action

The function also injects auxiliary fields including blocked_action_scope, safe_bypass_allowed, and a human-readable reason string.

Integrating Into the Quota Plan

The top-level planner build_quota_plan (lines 88‑154 in loopx/quota.py) collects all goals from run history, retrieves each goal’s quota via _quota_plan_goal_quota, and organizes results into state-group maps (eligible, throttled, etc.). The plan identifies the next automatic turn (the first goal in the eligible group) and summarizes health blockers.

plan = build_quota_plan(status_payload, mode="status")
next_turn = plan["next_automatic_turn"]

The runtime consumes this plan to decide whether the current agent turn should execute or skip.

Special Cases and Bypass Mechanisms

LoopX quota allocation includes several override mechanisms for complex operational scenarios.

Handoff Outcome Floor

When a handoff is pending, quota_with_handoff_outcome_floor (lines 11‑30) can force a focus-wait state if the handoff’s outcome-gap streak exceeds the profile’s threshold defined by execution_profile_outcome_floor.

Focus-Wait Override

If a lifecycle flag contains a focus-wait marker, _quota_with_focus_wait_override (lines 72‑88) forces the focus_wait state even when the compute quota remains available.

Self-Repair Spend Actions

Certain repair actions (such as state_projection_gap_repair) may spend compute despite quota throttling by setting safe_bypass_allowed and safe_bypass_kind in the payload, allowing critical maintenance to proceed.

Implementation Examples

Getting a Single Goal’s Quota Status

from loopx.quota import quota_status, goal_quota_config

goal = {
    "id": "example-123",
    "quota": {"compute": 0.5, "window_hours": 12, "slot_minutes": 2},
}

payload = goal_quota_config(goal)
status = quota_status(
    goal,
    waiting_on="codex",
    lifecycle_phase=None,
    lifecycle_flags=None,
    status=None,
)
print(status["state"], status["reason"])

Relevant source: quota_status – loopx/quota.py lines 71‑121.

Building a Full Quota Plan

from loopx.quota import build_quota_plan

plan = build_quota_plan(status_payload, mode="status")
next_turn = plan["next_automatic_turn"]
if next_turn:
    print("Next auto-turn goal:", next_turn["goal_id"])
else:
    print("No eligible goals – all are throttled or waiting.")

Relevant source: build_quota_plan – loopx/quota.py lines 88‑154.

Manually Adding a Quota Spend Event

from loopx.control_plane.quota.slot_accounting import build_quota_slot_spend_event

event = build_quota_slot_spend_event(
    slots=1,
    source="runtime_events",
)

Relevant source: build_quota_slot_spend_event – loopx/control_plane/quota/slot_accounting.py line 7.

Key Source Files

File Role
loopx/quota.py Central quota utilities: payload creation, ledger aggregation, state derivation, and plan construction
loopx/control_plane/quota/slot_accounting.py Event schema for spending/voiding slots and helpers for reading them from runs
loopx/control_plane/quota/goal_boundary.py Calculates effective capabilities and budget constraints per goal
loopx/control_plane/quota/heartbeat_recommendation.py Generates heartbeat-level recommendations influencing quota decisions
loopx/control_plane/quota/monitor_poll.py Handles monitor-poll classifications affecting quota state transitions
loopx/control_plane/quota/stall_repair.py Provides self-repair hints that may bypass quota throttling
loopx/control_plane/quota/turn_envelope.py Wraps turn execution payloads with quota metadata
loopx/control_plane/quota/usage_summary.py Renders human-readable markdown summaries of quota usage

Summary

  • LoopX quota allocation uses a fractional compute quota (0‑1) clamped by _clamp_compute and stored in quota.compute.
  • Slot accounting tracks consumption in time-based units (default 1 minute) via build_quota_slot_spend_event and goal_quota_with_spend_ledger.
  • Rolling windows (default 24 hours) bound consumption via window_hours and slot_minutes calculated in goal_quota_config.
  • The quota state machine (quota_status) transitions between eligible, throttled, paused, operator_gate, focus_wait, and waiting.
  • Bypass mechanisms allow self-repair actions to consume compute despite throttling when safe_bypass_allowed is set.
  • All quota logic resides in loopx/quota.py with supporting event schemas in loopx/control_plane/quota/.

Frequently Asked Questions

How does LoopX calculate the maximum allowed compute for a goal?

LoopX calculates allowed slots using goal_quota_config in loopx/quota.py (lines 94‑100). The formula multiplies the fractional compute quota by the number of slots in the configured window: round((window_hours * 60 / slot_minutes) * compute). This value can be overridden by explicitly setting allowed_slots in the goal JSON.

What happens when an agent exceeds its quota allocation?

When spent_slots meets or exceeds allowed_slots, the quota_status function returns throttled (lines 71‑121 in loopx/quota.py). In this state, the agent pauses automatic turns until the rolling window slides forward and older slots expire from the ledger, effectively freeing up budget for new execution.

Can an agent consume compute while technically throttled?

Yes, under specific conditions. The safe_bypass_allowed flag in the quota payload permits certain self-repair actions—such as state_projection_gap_repair—to consume slots even when the goal is throttled. This ensures critical maintenance operations can proceed to prevent system degradation.

How does LoopX track compute consumption across multiple runs?

The system aggregates consumption through goal_quota_with_spend_ledger (lines 33‑69 in loopx/quota.py), which iterates over all runs belonging to the goal. It extracts quota events using load_quota_event_from_run, filters out events outside the current window, and nets spent slots against voided slots to determine the true consumption total.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →