How to Debug Quota Eligibility Failures in LoopX: A Step-by-Step Diagnostic Guide
LoopX determines whether an agent turn proceeds through the quota-should-run subsystem, and debugging failures requires tracing the envelope construction, signature verification, and disposition logic across three core stages.
When an agent turn fails to execute in the huangruiteng/loopx repository, the root cause often lies in the quota eligibility check. This subsystem evaluates whether sufficient resources exist and whether gates permit execution. Understanding how to debug quota eligibility failures in LoopX involves tracing the flow from the CLI command through envelope construction to the final disposition decision.
How Quota Eligibility Works in LoopX
The quota decision flow consists of three interconnected stages defined in loopx/control_plane/quota/. A failure typically originates when any stage returns should_run = False or fails to validate the envelope signature.
Stage 1: Building the Turn Envelope
Located in loopx/control_plane/quota/turn_envelope.py, the build_turn_envelope() function assembles a turn envelope that travels with the turn receipt. This envelope encapsulates the quota decision, the effective_action (such as run, quiet-noop, or terminal-no-follow-up), and the turn metadata. The envelope serves as the canonical record of why a turn was permitted or blocked.
Stage 2: Interpreting the Quota Packet
The interpret_quota_should_run_packet() function in loopx/control_plane/quota/effect_program.py decodes the JSON output from the CLI command loopx quota should-run. It creates a QuotaDecision object containing the boolean should_run, the effective_action string, and the signature block. This stage transforms the raw provider response into a typed structure that downstream logic consumes.
Stage 3: Deciding Loop Disposition
Also in loopx/control_plane/quota/turn_envelope.py, the decide_loop_disposition() function combines the turn receipt with the quota envelope to determine if the loop will spend quota, wait, re-plan, or terminate. This final stage checks for signature mismatches, stale source_hash values, and propagation errors in turn_key or selected_todo_id.
Step-by-Step Debugging Checklist
1. Run the Quota Command with Full Details
Execute the CLI command to see the raw provider decision:
loopx quota should-run \
--goal-id <your-goal-id> \
--include-detail scheduler \
--format json
Examine the JSON payload for the should_run field. If this value is false, the failure originates from the quota provider itself—indicating limits, missing resources, or explicit gating. The effective_action field reveals whether the system intends to run_now, stop_until_explicit_resume, or execute a quiet-noop.
2. Inspect the Signature Block
The signature object proves that the quota decision matches the current goal state. Check the source_hash against the goal's latest state stored in the goal ledger (loopx/state/). A stale or mismatched hash causes the envelope to be rejected later in the pipeline even if should_run is true.
3. Trace the Turn Envelope Construction
Verify that build_turn_envelope() receives the correct arguments:
from loopx.control_plane.quota.turn_envelope import build_turn_envelope
envelope = build_turn_envelope(
quota_decision=quota_decision, # Must match CLI output
turn_key=receipt.turn_key, # Must match the turn receipt
selected_todo_id=None, # Propagate correctly if present
)
Mismatched keys cause the envelope to be ignored during disposition. Ensure the quota_decision argument matches the CLI JSON exactly, including the signature block.
4. Check the Disposition Logic
The disposition function determines whether quota is actually consumed:
from loopx.control_plane.quota.turn_envelope import decide_loop_disposition
disposition = decide_loop_disposition(
turn_receipt=receipt,
quota_decision=envelope,
)
The disposition["spends_quota"] field should be True when should_run is True. If it is False, inspect the envelope for flags such as quiet_noop_allowed, replan_required, or a failed signature verification.
5. Enable Debug Logging
Set the environment variable to capture detailed trace logs:
export LOOPX_LOG_LEVEL=debug
The logs emit messages from critical functions including quota_action_signature_document (signature creation), interpret_quota_should_run_packet (payload parsing), and decide_loop_disposition (final decision).
6. Validate the Quota Provider
Provider implementations reside in loopx/control_plane/quota/provider/. The ecosystem includes:
- Static gates defined in test fixtures (see
tests/test_summary_all.py) - Dynamic quota services consulted via HTTP in
quota_service.py
If using a custom provider, ensure it returns a JSON object with the strict schema: should_run, effective_action, and signature. Missing fields cause parsing failures in effect_program.py.
7. Run the Relevant Unit Tests
Isolate failures using the dedicated test suites:
pytest tests/test_turn_envelope.py -v
pytest tests/test_turn_loop_disposition.py::test_quota_failure -v
These tests validate envelope construction, signature handling, and disposition logic for both success and failure scenarios.
Practical Code Examples
Inspecting a Quota Packet Manually
Simulate CLI output to debug parsing logic without running the full agent:
import json
from loopx.control_plane.quota.effect_program import interpret_quota_should_run_packet
raw = """
{
"should_run": false,
"effective_action": "stop_until_explicit_resume",
"signature": {
"source_hash": "sha256:abc123",
"gate_id": "explicit-quota-gate"
}
}
"""
packet = json.loads(raw)
decision = interpret_quota_should_run_packet(packet)
assert decision.should_run is False
assert decision.effective_action == "stop_until_explicit_resume"
Source: loopx/control_plane/quota/effect_program.py
Building a Turn Envelope and Deciding Disposition
Programmatically replicate the envelope flow to verify integration:
from loopx.control_plane.quota.turn_envelope import (
build_turn_envelope,
decide_loop_disposition,
)
from loopx.control_plane.quota.effect_program import interpret_quota_should_run_packet
# Assume receipt from a previous turn
receipt = ... # TurnReceipt object
quota_payload = {
"should_run": True,
"effective_action": "run_now",
"signature": {"source_hash": "sha256:def456", "gate_id": "default"}
}
quota_decision = interpret_quota_should_run_packet(quota_payload)
envelope = build_turn_envelope(
quota_decision=quota_decision,
turn_key=receipt.turn_key,
selected_todo_id=None,
)
disposition = decide_loop_disposition(
turn_receipt=receipt,
quota_decision=envelope
)
print(disposition["spends_quota"]) # Expected: True when eligible
Source: loopx/control_plane/quota/turn_envelope.py
CLI Diagnostic Output
Generate full diagnostic data including scheduler internals:
loopx quota should-run \
--goal-id my-goal \
--include-detail scheduler \
--format json
The output includes a "scheduler" block indicating whether execution occurs immediately or is deferred, which distinguishes between hard gate failures and scheduling waits.
Source: loopx/control_plane/quota/cli.py
Key Source Files
loopx/control_plane/quota/turn_envelope.py— Builds the turn envelope and decides loop disposition viabuild_turn_envelope()anddecide_loop_disposition()loopx/control_plane/quota/effect_program.py— Parses JSON packets fromquota should-runviainterpret_quota_should_run_packet()loopx/control_plane/quota/task_orchestration.py— Orchestrates quota checks for a goal and integrates with the schedulerloopx/control_plane/quota/provider/— Contains static gates and dynamic HTTP quota service implementationstests/test_turn_envelope.py— Unit tests for envelope creation and signature validationtests/test_turn_loop_disposition.py— Tests covering decision-making across all quota outcomes
Summary
- Trace the CLI output to verify the raw
should_runandeffective_actionvalues usingloopx quota should-run --include-detail scheduler --format json - Verify signatures by ensuring
source_hashmatches the current goal ledger state to prevent stale envelope rejections - Inspect envelope construction in
build_turn_envelope()to confirm correct propagation ofquota_decision,turn_key, andselected_todo_id - Check disposition logic to ensure
decide_loop_disposition()returnsspends_quota=Truewhen execution is expected, and watch forquiet_noop_allowedorreplan_requiredflags - Enable debug logging with
LOOPX_LOG_LEVEL=debugto capture detailed traces fromquota_action_signature_document,interpret_quota_should_run_packet, anddecide_loop_disposition - Run unit tests in
tests/test_turn_envelope.pyandtests/test_turn_loop_disposition.pyto isolate component-level failures
Frequently Asked Questions
What causes a quota eligibility failure in LoopX?
A failure occurs when the quota provider returns should_run: false due to resource limits, explicit gates, or missing prerequisites. Failures also happen when the envelope's signature contains a stale source_hash that does not match the goal ledger, causing decide_loop_disposition() to reject the envelope even if the provider initially approved execution.
How do I check if the quota signature is valid?
Compare the source_hash field in the quota decision's signature block against the latest hash stored in the goal ledger (loopx/state/). The quota_action_signature_document function generates this hash during envelope construction; if the ledger has advanced since the quota check, the hash mismatch triggers a rejection.
Where are quota provider implementations located?
Providers reside in loopx/control_plane/quota/provider/. The repository includes static gates for testing (defined in tests/test_summary_all.py) and dynamic services that query external HTTP endpoints (quota_service.py). Custom providers must return JSON with should_run, effective_action, and signature fields to be compatible with effect_program.py.
Can I test quota logic without running the full agent?
Yes. Use the unit tests in tests/test_turn_envelope.py to validate envelope construction and signature handling, and tests/test_turn_loop_disposition.py to verify disposition decisions against mock quota decisions. You can also manually call interpret_quota_should_run_packet() with JSON payloads to simulate provider responses without invoking the CLI.
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 →