Repository navigation
feat(llc/scheduler): registry adapters (claude_code) get no ProviderRateLimited backoff recovery #9773
Description
Activity
- addedenhancementNew feature or requestNew feature or request
on Jun 8, 2026 Related cleanup surfaced in review of #9835:
claude_code_subscription_adapter.pyandcopilot_subscription_adapter.pyeach carry a# TODO: Implement auto-pause + board notification (depends on GH#8225)on the quota-exhaustion path — violates the repo "no TODO comments" rule. The auto-pause/board-notify behavior belongs to this issue's domain (quota/rate-limit handling for registry adapters); fold it in when implementing theRATE_LIMITEDchannel here.Consolidation to fold in here (verified duplication):
_check_quota_exhaustion()is byte-identical (bar log strings) betweenclaude_code_subscription_adapter.py:210andcopilot_subscription_adapter.py:186, and each carries its own_QUOTA_EXHAUSTED_PATTERNSlist + an identical quota-check block instatus(). When implementing theRATE_LIMITEDchannel here, hoist_check_quota_exhaustion(and a per-adapterQUOTA_PATTERNSclass attr) into a shared mixin /subprocess_supporthelper so the detection logic lives once. (codex_subscription_adapteris a NotImplementedError stub — no quota logic.)- added a commit that references this issue
on Jun 11, 2026 github-actions commented
on Jun 11, 2026 on Jun 11, 2026 – with GitHub ActionsContributorMore actionsClosed — merged to Dev_new_gui via PR #9993 (squash commit
a2be8d76e).Criteria met:
- Shared rate-limit detection in
subprocess_support(_RL_KEYWORDS,is_rate_limit_output,read_output_tail,final_result_event) — extracted fromautobot_agent_adapter, which now delegates (also resolves this issue's_check_quota_exhaustion-dup note: subscription adapter's quota check now wins over inherited RATE_LIMITED, tested) ClaudeCodeAdapter._status()reclassifies exited runs to RATE_LIMITED only when the stream-json terminal result event is missing (mid-stream kill) or carries an error — a successful run mentioning 'rate limit'/'429'/'quota' can never be re-queued (review-caught critical, covered by 3 dedicated false-positive tests)_dispatch_registry_adaptertranslates terminal RATE_LIMITED →raise ProviderRateLimited— identical GH#8204 path (checkout preservation, exponential backoff, retry cap,rate_limitedrun record, no AdapterRunFailed); reviewer-verified parity. RATE_LIMITED never persisted for registry adapters → zero frontend ripple- 150 tests pass (21 in the new rate-limit suite + full adapter package)
Discoveries: #9992 (claude CLI stderr PIPE'd, never drained — limits detector recall + potential pipe-buffer block).
- Shared rate-limit detection in
Problem
The heartbeat scheduler's
ProviderRateLimitedexponential-backoff recovery (GH#8204) only fires when an adapter raisesProviderRateLimited— which happens for in-processautobot_agentagents viaAutoBotAgentAdapter.run_blocking.Registry adapters (e.g.
claude_code) report status through theAdapterRunStatusdataclass (invoke/status/cancel), which has no rate-limited representation. When aclaude_codesubprocess hits a provider rate limit, it exits and surfaces as a non-success terminal status — now recorded as a failed run (PR #9772,AdapterRunFailed) rather than triggering backoff + work-item-checkout preservation.So registry-adapter agents get no automatic rate-limit recovery; a rate-limited run is treated as a plain failure.
Proposed fix
RATE_LIMITEDchannel toAdapterRunStatus(or a dedicated detector) soClaudeCodeAdapter.status/ subprocess output parsing can report rate limiting._dispatch_registry_adapter/_await_adapter_completion, translate aRATE_LIMITEDterminal status into a raisedProviderRateLimitedso the existing backoff path in_run_adapterapplies uniformly.References
Discovered in code review of PR #9772 (#9622 / #9623). See
_dispatch_registry_adapterinautobot-backend/llc/scheduler/heartbeat_scheduler.py.Labels: enhancement · backend · agents · priority: medium