hermes - 💡(How to fix) Fix feat: generalize nous_rate_guard to a universal provider rate limit guard [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
NousResearch/hermes-agent#14840Fetched 2026-04-24 06:14:32
View on GitHub
Comments
0
Participants
1
Timeline
3
Reactions
0
Author
Participants
Timeline (top)
labeled ×3

agent/nous_rate_guard.py currently provides a cross-session rate limit guard exclusively for the Nous Portal provider. This FR proposes generalizing it into a universal provider rate limit guard that benefits all providers (OpenAI-compatible, Z.ai/DashScope, etc.) with the same preventive pattern.

Root Cause

agent/nous_rate_guard.py currently provides a cross-session rate limit guard exclusively for the Nous Portal provider. This FR proposes generalizing it into a universal provider rate limit guard that benefits all providers (OpenAI-compatible, Z.ai/DashScope, etc.) with the same preventive pattern.

Code Example

# Before (3 locations):
if self.provider == "nous":
    from agent.nous_rate_guard import nous_rate_limit_remaining
    ...

# After:
from agent.provider_rate_guard import provider_rate_limit_remaining
_remaining = provider_rate_limit_remaining(self.provider)
if _remaining is not None and _remaining > 0:
    ...
RAW_BUFFERClick to expand / collapse

Summary

agent/nous_rate_guard.py currently provides a cross-session rate limit guard exclusively for the Nous Portal provider. This FR proposes generalizing it into a universal provider rate limit guard that benefits all providers (OpenAI-compatible, Z.ai/DashScope, etc.) with the same preventive pattern.

Current State

nous_rate_guard.py works well for Nous:

  • Pre-request check: Before each API call, checks shared state file. If rate-limited, skips the call entirely (prevents RPH amplification from retries).
  • Post-429 recording: Records rate limit state with reset time parsed from response headers.
  • Post-success clearing: Clears rate limit state after a successful request.
  • Atomic file writes: Uses tempfile + os.replace for safe writes.
  • Shared state: File at ~/.hermes/rate_limits/nous.json, readable by all sessions (CLI, gateway, cron).

However, this logic only triggers when self.provider == "nous" (hardcoded at 3 call sites in run_agent.py).

Proposed Changes

1. Rename and generalize the module

agent/nous_rate_guard.pyagent/provider_rate_guard.py

Replace Nous-specific functions with provider-agnostic ones:

Current (Nous-only)Proposed (Universal)
record_nous_rate_limit()record_provider_rate_limit(provider)
nous_rate_limit_remaining()provider_rate_limit_remaining(provider)
clear_nous_rate_limit()clear_provider_rate_limit(provider)
format_remaining()(keep as internal utility)

The provider parameter maps to the same {provider}.json file convention. No model-level granularity needed — rate limits are API-key/account level, so one provider being rate-limited means all its models are unavailable.

2. Replace hardcoded provider == "nous" checks

In run_agent.py, replace 3 hardcoded Nous guards with generic provider calls:

# Before (3 locations):
if self.provider == "nous":
    from agent.nous_rate_guard import nous_rate_limit_remaining
    ...

# After:
from agent.provider_rate_guard import provider_rate_limit_remaining
_remaining = provider_rate_limit_remaining(self.provider)
if _remaining is not None and _remaining > 0:
    ...

Same for record_provider_rate_limit and clear_provider_rate_limit.

3. Keep Nous as default behavior, add config opt-in for other providers

By default, the guard activates for all providers (opt-out via config if needed). Alternatively, guard only providers that have been observed rate-limited (lazy activation — no guard file = not rate-limited).

4. Chinese date format parsing

For Z.ai/DashScope and similar Chinese API providers, rate limit reset times may come in Chinese format (e.g. 您的限额将在 2026-04-19 06:17:24 重置). The _extract_api_error_context() method in run_agent.py should parse these into a numeric reset_at timestamp so the guard can use them. This is currently missing.

Benefits

  • All providers benefit: Z.ai, DashScope, OpenAI-compatible, etc. — no more repeated 429 → fallback cycles for each turn.
  • Preventive pattern: Same efficiency gain as Nous — skip the API call entirely when rate-limited, avoiding retry amplification.
  • No extra dependencies: Reuses existing file-based shared state mechanism.
  • Backward compatible: Nous behavior unchanged, other providers gain new capability.

References

  • Previous Nous-specific implementation: agent/nous_rate_guard.py (182 lines)

extent analysis

TL;DR

To generalize the rate limit guard for all providers, rename and modify the agent/nous_rate_guard.py module to agent/provider_rate_guard.py and replace hardcoded provider checks in run_agent.py.

Guidance

  • Rename the agent/nous_rate_guard.py module to agent/provider_rate_guard.py and update its functions to be provider-agnostic.
  • Replace the three hardcoded self.provider == "nous" checks in run_agent.py with generic provider calls using the provider_rate_limit_remaining function.
  • Update the _extract_api_error_context() method in run_agent.py to parse Chinese date formats for rate limit reset times.
  • Consider adding a configuration option to opt-in or opt-out of the rate limit guard for specific providers.

Example

# Before:
if self.provider == "nous":
    from agent.nous_rate_guard import nous_rate_limit_remaining
    ...

# After:
from agent.provider_rate_guard import provider_rate_limit_remaining
_remaining = provider_rate_limit_remaining(self.provider)
if _remaining is not None and _remaining > 0:
    ...

Notes

The proposed changes aim to generalize the rate limit guard for all providers, but the implementation details for parsing Chinese date formats and handling different provider-specific behaviors are not fully specified.

Recommendation

Apply the proposed changes to generalize the rate limit guard, as they provide a clear benefit for all providers and do not introduce new dependencies.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - 💡(How to fix) Fix feat: generalize nous_rate_guard to a universal provider rate limit guard [1 participants]