jeevesagent.governance¶
Resource governance: budgets, quotas, retry/backoff.
Submodules¶
Classes¶
Never blocks, never warns. |
|
Exponential-backoff-with-jitter retry schedule. |
|
Hard-limited, thread-safe budget tracker. |
Functions¶
|
Map an exception from any model SDK to the framework's taxonomy. |
|
Backoff (seconds) before retry number |
Package Contents¶
- class jeevesagent.governance.NoBudget[source]¶
Never blocks, never warns.
- async allows_step() jeevesagent.core.types.BudgetStatus[source]¶
- class jeevesagent.governance.RetryPolicy[source]¶
Exponential-backoff-with-jitter retry schedule.
The default is sensible for production: up to 3 attempts (one initial + two retries), starting at 1 s, doubling each attempt, capped at 30 s, with ±10% jitter so synchronised clients don’t reform a thundering herd.
Examples:
# default — sensible for most apps RetryPolicy() # disable retries (fail fast) RetryPolicy.disabled() # aggressive — survives long provider blips RetryPolicy.aggressive() # tuned to a specific SLO RetryPolicy(max_attempts=4, initial_delay_s=0.5, max_delay_s=15)
The schedule applies between attempts: the first call has no delay, the second is delayed by
initial_delay_s(± jitter), the third byinitial_delay_s * multiplier(± jitter), etc., each capped atmax_delay_s. Provider-suppliedRetry-Afterhints (carried onretry_after) override the computed delay when they ask for more time — we never sleep less than the provider asked for.- classmethod aggressive() RetryPolicy[source]¶
Up to 6 attempts, faster initial backoff, longer cap. Use when the underlying provider is known-flaky and the caller prefers slow success over fast failure.
- classmethod disabled() RetryPolicy[source]¶
Single attempt, no retries — fail fast on any error.
- initial_delay_s: float = 1.0¶
Backoff before the FIRST retry (i.e. between attempts 1 and 2). Subsequent retries use
initial_delay_s * multiplier**n.
- jitter: float = 0.1¶
Fractional ±jitter applied to each computed delay.
0.1= ±10%. Set to0for deterministic backoff (useful in tests).
- max_attempts: int = 3¶
Maximum total attempts including the first call.
1means no retries; the call either succeeds or raises immediately. The minimum-meaningful retry policy is thereforemax_attempts=2.
- class jeevesagent.governance.StandardBudget(cfg: BudgetConfig | None = None)[source]¶
Hard-limited, thread-safe budget tracker.
- async allows_step() jeevesagent.core.types.BudgetStatus[source]¶
- jeevesagent.governance.classify_model_error(exc: BaseException) jeevesagent.core.errors.ModelError | None[source]¶
Map an exception from any model SDK to the framework’s taxonomy.
Returns
Nonewhen the exception is not recognised as a model-call failure — let callers decide whether to wrap it in something else or propagate. Returns an instance of one ofTransientModelError/RateLimitError/AuthenticationError/InvalidRequestError/ContentFilterError/PermanentModelErrorotherwise.SDK imports are lazy — having e.g. the
anthropicpackage installed is not required for OpenAI classification to work, and vice versa.
- jeevesagent.governance.compute_backoff(policy: RetryPolicy, attempt: int, *, retry_after: float | None = None, rng: random.Random | None = None) float[source]¶
Backoff (seconds) before retry number
attempt(1-indexed).attempt=1is the delay before the first retry (i.e. between attempts 1 and 2 ofmax_attempts). Returns0whenpolicyis disabled.retry_after(provider hint, e.g. from a 429Retry-Afterheader) acts as a floor: we never wait less than the provider asked for, but we still cap atpolicy.max_delay_s. This means a provider-supplied 60-second hint paired with a 30-second cap is honoured at 60 seconds (exceeding the cap on purpose — the provider is more authoritative than our heuristic).