retryWith

suspend fun <A> retryWith(policy: RetryPolicy, operationLabel: () -> String, logger: KLogger, analyzeFailure: (exception: Exception) -> AnalyzedFailure, collectAttemptMetrics: () -> AttemptMetrics, onAttemptStarting: (attemptIndex: Int) -> Unit = {}, onAbort: (abort: ExecutionAbortException, previousAttempts: List<FailedAttempt>, abortedAttemptMetrics: AttemptMetrics) -> Unit = { _, _, _ -> }, block: suspend (attemptIndex: Int) -> A): RetriesOutcome<A>

Runs block up to policy.maxAttempts + 1 times (one initial attempt plus up to maxAttempts retries), capturing per-attempt metrics via collectAttemptMetrics and applying retry / delay decisions per policy.

Abort semantics. ExecutionAbortException thrown by block short-circuits the retry loop and propagates to the caller — aborts always trump retries (a spend-limit breach or operator cancel must not be silently re-attempted). Before rethrowing, onAbort is invoked with the collected previousAttempts plus the metrics of the just-interrupted attempt, so the caller can record a complete leaf entry (with prior failed attempts preserved) before the abort propagates.

Observability. All retry-observability log events ("planned retry", "retries exhausted", etc.) are emitted from inside this helper via logger so all three retry call sites (training agent run, training prompt execution, eval per-item) produce identical log output.

Parameters

policy

active retry policy (resolved from session settings or a per-call override).

operationLabel

human-readable identifier of the operation under retry — included in log messages (e.g., "agent run for item 7 / 50"). Lazy: only invoked when a log event fires.

logger

logger to emit retry-observability events on.

analyzeFailure

converts a caught Throwable into the project's AnalyzedFailure. Each call site passes the analyzer matching its context (analyzeAgentRunFailure for runAgent, analyzeTrainingFailure for prompt execution, etc.).

collectAttemptMetrics

returns the metrics of the just-finished attempt (success or failure). Called once after each attempt completes — including on the abort path, where the metrics of the interrupted attempt are read once and passed to onAbort.

onAttemptStarting

optional hook called before each attempt starts. Receives the 0-based attemptIndex (0 = original attempt; ≥ 1 = retry). Used for per-attempt instrumentation (e.g., resetting consumption trackers, decorating the Langfuse trace name).

onAbort

optional hook called inside the abort-catch arm, before the abort is rethrown. Receives the abort exception, the previousAttempts collected before the abort fired, and the metrics of the attempt-that-was-interrupted. The default is a no-op (suitable for call sites where the enclosing flow records the abort at a higher level — e.g. eval-side evaluateItem). The retry helper itself rethrows the abort after this hook returns; callers should not rethrow from inside the hook.

block

the operation to retry. Receives the 0-based attemptIndex.