diff --git a/pkg/agent/loop.go b/pkg/agent/loop.go index ca763b97c..87fe5f0cf 100644 --- a/pkg/agent/loop.go +++ b/pkg/agent/loop.go @@ -617,8 +617,8 @@ func (al *AgentLoop) runLLMIteration(ctx context.Context, agent *AgentInstance, }) } - // Retry loop for context/token errors - maxRetries := 2 + // Retry loop for recoverable errors (context window + rate limits). + maxRetries := 3 for retry := 0; retry <= maxRetries; retry++ { response, err = callLLM() if err == nil { @@ -626,6 +626,34 @@ func (al *AgentLoop) runLLMIteration(ctx context.Context, agent *AgentInstance, } errMsg := strings.ToLower(err.Error()) + + // Rate-limit / transient errors: wait with exponential backoff. + isRateLimitError := strings.Contains(errMsg, "429") || + strings.Contains(errMsg, "rate limit") || + strings.Contains(errMsg, "rate_limit") || + strings.Contains(errMsg, "resource_exhausted") || + strings.Contains(errMsg, "resource exhausted") || + strings.Contains(errMsg, "too many requests") || + strings.Contains(errMsg, "overloaded") || + strings.Contains(errMsg, "quota") + + if isRateLimitError && retry < maxRetries { + backoff := time.Duration(1<