Skip to content

mnesis.retry

retry

Shared retry policy for transient LLM errors.

Used by MnesisSession.send() and by the compaction engine so that :class:~mnesis.models.config.RetryConfig governs every LLM call Mnesis makes.

RetriesExhaustedError

Bases: Exception

A retryable LLM error persisted through every configured Mnesis retry.

__cause__ is the last underlying error. Raised only when Mnesis owns retries (max_retries > 0); it signals an outage, so callers should stop sending further LLM calls rather than start another retry sequence.

is_retryable

is_retryable(exc: BaseException) -> bool

Return True if exc is a transient LLM error worth retrying.

Retryable errors are transient provider-side problems (rate limits, server errors, timeouts, connection issues). Non-retryable errors indicate caller mistakes (bad credentials, bad request, context window exceeded) that will not resolve on retry.

Any exception type not in either known list is treated as non-retryable (fail-fast) to avoid hiding unexpected errors.

backoff_delay

backoff_delay(cfg: RetryConfig, attempt: int) -> float

Exponential backoff (with optional jitter) before retry attempt + 1.

call_with_retry async

call_with_retry(
    call: Callable[[], Awaitable[T]],
    cfg: RetryConfig,
    *,
    abort: Event | None = None,
    logger: BoundLogger | None = None,
    on_retry: Callable[[int, float, Exception], None]
    | None = None,
) -> T

Await call(), retrying transient errors per cfg.

Non-retryable errors propagate unchanged. A retryable error that outlasts cfg.max_retries (> 0) raises :class:RetriesExhaustedError. If abort is set during backoff the wait ends immediately with asyncio.CancelledError; external task cancellation also propagates.

on_retry(attempt, delay, exc) is called (1-based attempt) just before each backoff sleep, e.g. to publish an LLM_RETRY event. An exception it raises is logged and swallowed: observability must not fail the call.