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 legacycomputefield) 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] += slotsfor spend eventsvoided_by_run[voided_run_generated_at] += slotsfor 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_computeand stored inquota.compute. - Slot accounting tracks consumption in time-based units (default 1 minute) via
build_quota_slot_spend_eventandgoal_quota_with_spend_ledger. - Rolling windows (default 24 hours) bound consumption via
window_hoursandslot_minutescalculated ingoal_quota_config. - The quota state machine (
quota_status) transitions betweeneligible,throttled,paused,operator_gate,focus_wait, andwaiting. - Bypass mechanisms allow self-repair actions to consume compute despite throttling when
safe_bypass_allowedis set. - All quota logic resides in
loopx/quota.pywith supporting event schemas inloopx/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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →