NousResearch/hermes-agent
HTTP 429 rate limit and Retry-After header handling
Cluster 2642 · agent. Data as of
Nothing open on GitHub. Fix merged in #3809 on 29 Mar 2026. Check it covers your case.
The short answer
0open issues
0open PRs
4items grouped
- Known?
- Yes. 4 related items grouped here, 1 issue already closed.
- Fix event
- A fix was merged to main in PR #3809. Check it covers your case. No release data is tracked.
- Tracker
- The maintainers' tracker marks this
unresolved. That is separate from the fix event. - Still open
- Nothing open on GitHub.
These items address a bug where HTTP 429 Too Many Requests responses were not properly handled, covering both honouring the Retry-After header and surfacing user-friendly rate limit messages.
Open issues0
Open PRs0
Fixes on record
-
#3809 fix(agent): user-friendly 429 rate limit messages with Retry-After support
files:
run_agent.pyShow the diff
-
run_agent.py@@ -7229,7 +7229,10 @@ def _stop_spinner(): retry_count = 0 continue _final_summary = self._summarize_api_error(api_error) - self._vprint(f"{self.log_prefix}❌ Max retries ({max_retries}) exceeded. Giving up.", force=True) + if is_rate_limited: + self._vprint(f"{self.log_prefix}❌ Rate limit persisted after {max_retries} retries. Please try again later.", force=True) + else: + self._vprint(f"{self.log_prefix}❌ Max retries ({max_retries}) exceeded. Giving up.", force=True) self._vprint(f"{self.log_prefix} 💀 Final error: {_final_summary}", force=True) # Detect SSE stream-drop pattern (e.g. "Network @@ -7289,8 +7292,22 @@ def _stop_spinner(): "error": _final_summary, } - wait_time = min(2 ** retry_count, 60) # Exponential backoff: 2s, 4s, 8s, 16s, 32s, 60s, 60s - self._emit_status(f"⏳ Retrying in {wait_time}s (attempt {retry_count}/{max_retries})...") + # For rate limits, respect the Retry-After header if present + _retry_after = None + if is_rate_limited: + _resp_headers = getattr(getattr(api_error, "response", None), "headers", None) + if _resp_headers and hasattr(_resp_headers, "get"): + _ra_raw = _resp_headers.get("retry-after") or _resp_headers.get("Retry-After") + if _ra_raw: + try: + _retry_after = min(int(_ra_raw), 120) # Cap at 2 minutes + except (TypeError, ValueError): + pass + wait_time = _retry_after if _retry_after else min(2 ** retry_count, 60) + if is_rate_limited: + self._emit_status(f"⏱️ Rate limit reached. Waiting {wait_time}s before retry (attempt {retry_count + 1}/{max_retries})...") + else: + self._emit_status(f"⏳ Retrying in {wait_time}s (attempt {retry_count}/{max_retries})...") logger.warning( "Retrying API call in %ss (attempt %s/%s) %s error=%s", wait_time,
-
2 PRs closed without merging
From the close comments: closed without comment 1 · done elsewhere 1
Closed issues · 1
- Closed#2642[Bug]: HTTP 429 Too Many Requests is not treated
How this cluster was grouped
-
Link evidence (
structural links throughout): every member is connected by structural evidence: shared changed files, or a closing/superseded reference. -
Pairwise link density
0.50: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36.1.00means every pair is linked.
Pick up a Lab task
Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.
Open the LabAt a glance
- Subsystem
- agent
- Merged PRs
- #3809
- Closed issues
- 1
- Attempts
- 2 PRs closed without merging
- Fix link checked
- 29 Mar 2026. This confirmation is old and may be out of date (a revert or reopen would not have invalidated it here); re-verify.