Llm retry with typed error formatting
Skill kjuhwa/skills-hub/skills/agent-sdk/llm-retry-with-typed-error-formatting
Wrap LLM calls in a 3-attempt exponential-backoff retry that re-raises auth errors immediately (don't retry 401/403), and on final failure formats a user-actionable message based on error type and HTTP status (529 overload, APIConnectionError, etc).From its SKILL.md
npx -y skills add kjuhwa/skills-hub --skill llm-retry-with-typed-error-formattingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
3.5 KB, 639 tokens by cl100k_base, as published. Nobody here has run it
LLM Retry with Typed Error Formatting
When to use
You're calling provider SDKs (Anthropic, OpenAI) and want a uniform "retry transient failures, surface useful error" path. AuthenticationError and any guardrail block must propagate immediately — they won't get better with retries.
How it works
- Hard-coded
max_attempts=3andbackoff_seconds = 1.0; backoff_seconds *= 2between tries. AuthenticationErrorre-raised asRuntimeError("...check your API key in env or .env...")— no retries.GuardrailBlockedErrorpropagates unchanged (caller-relevant).- All other exceptions retried; on final failure, a custom formatter inspects the type name and
status_codeto produce a user-actionable message ("Anthropic API is overloaded (HTTP 529) after multiple retries. Try again in a few seconds.").
Example
def invoke(self, prompt_or_messages):
self._ensure_client()
system, messages = _normalize_messages(prompt_or_messages)
# ... apply guardrails ...
backoff_seconds = 1.0
max_attempts = 3
last_err = None
for attempt in range(max_attempts):
try:
response = self._client.messages.create(...)
break
except AuthenticationError as err:
raise RuntimeError(
"Anthropic authentication failed. Check ANTHROPIC_API_KEY in your environment or .env."
) from err
except GuardrailBlockedError:
raise
except Exception as err:
last_err = err
if attempt == max_attempts - 1:
raise RuntimeError(_format_anthropic_retry_error(err)) from err
time.sleep(backoff_seconds)
backoff_seconds *= 2
else:
raise RuntimeError("LLM invocation failed without a concrete error") from last_err
return LLMResponse(content=_extract_text(response))
def _format_anthropic_retry_error(err: Exception) -> str:
name = type(err).__name__
status = getattr(err, "status_code", None)
if name == "APIConnectionError":
return "Anthropic API connection failed after multiple retries. Check network access and try again."
if status == 529:
return "Anthropic API is overloaded (HTTP 529) after multiple retries. Try again in a few seconds."
return f"Anthropic API request failed after multiple retries: {name}."
Gotchas
- The
elseon the for-loop is reachable only if the loop never breaks — useful as a "no concrete error captured" defensive path. - Don't retry on auth errors; the user has to fix the env. Retrying makes the misconfig look like a flaky network.
- Guardrail errors must propagate at the same priority as auth — they're an explicit user-policy block, not a transient failure.
- Re-resolve API key on each call (
_ensure_client) so a key rotated mid-process is picked up without restarting.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.