python-resilience — Claude Code skill: setup and use
A Python skill for retries, timeouts, backoff, and transient failure handling. Use it when external services or network calls need bounded recovery.
/plugin marketplace add wshobson/agents
/plugin install python-development@claude-code-workflowsWhat python-resilience does
python-resilience gives an agent patterns for handling temporary failures in Python. It covers retries with exponential backoff and jitter, bounded attempt counts, total time limits, and timeouts for network operations. It also separates retryable exceptions and HTTP responses from permanent client or authentication errors.
The examples use tenacity decorators and httpx requests. They cover exception-based retries, status codes such as 429, 500, 502, 503, and 504, plus retry logging and combined conditions. More detailed patterns are stored in references/details.md.
Install it when a Python project calls external services or depends on unreliable network operations. For local code with no transient dependency failures, the skill adds little.
What it helps with
- add retries to external service calls
- bound network waits with timeouts
- separate transient errors from permanent ones
- handle retryable HTTP status codes
- prevent unbounded retry loops
Example prompts for the agent
- Add retries to `fetch_data` for transient network exceptions only.
- Configure exponential backoff, jitter, and a timeout for this `httpx` call.
- Review which exceptions and HTTP responses should trigger another request.
How to install python-resilience
1Plugin marketplace
/plugin marketplace add wshobson/agents/plugin install python-development@claude-code-workflowsThis installs the whole python-development plugin with all its skills
2Skills CLI (Vercel)
npx skills add wshobson/agents --skill python-resilience -a claude-code3Manually: put the files in place
~/.claude/skills/python-resilience/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/python-resilience/
1Skills CLI (Vercel)
npx skills add wshobson/agents --skill python-resilience -a codex2Manually: put the files in place
.agents/skills/python-resilience/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add wshobson/agents --skill python-resilience -a cursor2Manually: put the files in place
.cursor/skills/python-resilience/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install wshobson/agents python-resilience2Manually: put the files in place
.github/skills/python-resilience/SKILL.mdPlatform CLI
gemini skills install https://github.com/wshobson/agents --path plugins/python-development/skills/python-resilienceManually: put the files in place
.devin/skills/python-resilience/SKILL.mdThe legacy .windsurf/skills/ path still works
Claude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
From the same set213
The whole set →Similar
Questions about python-resilience
How do I install python-resilience in Claude Code?
Run npx skills add wshobson/agents --skill python-resilience -a claude-code. The skill file is placed at ~/.claude/skills/python-resilience/SKILL.md.
What does python-resilience do?
It guides Python changes involving retries, exponential backoff, jitter, timeouts, and bounded recovery from transient failures. It also covers which exceptions and HTTP responses should be retried.
Which libraries appear in the python-resilience examples?
The examples use tenacity for retry decorators and httpx for HTTP requests.
Source text
SKILL.md · MIT
---
name: python-resilience
description: Python resilience patterns including automatic retries, exponential backoff, timeouts, and fault-tolerant decorators. Use when adding retry logic, implementing timeouts, building fault-tolerant services, or handling transient failures.
---
# Python Resilience Patterns
Build fault-tolerant Python applications that gracefully handle transient failures, network issues, and service outages. Resilience patterns keep systems running when dependencies are unreliable.
## When to Use This Skill
- Adding retry logic to external service calls
- Implementing timeouts for network operations
- Building fault-tolerant microservices
- Handling rate limiting and backpressure
- Creating infrastructure decorators
- Designing circuit breakers
## Core Concepts
### 1. Transient vs Permanent Failures
Retry transient errors (network timeouts, temporary service issues). Don't retry permanent errors (invalid credentials, bad requests).
### 2. Exponential Backoff
Increase wait time between retries to avoid overwhelming recovering services.
### 3. Jitter
Add randomness to backoff to prevent thundering herd when many clients retry simultaneously.
### 4. Bounded Retries
Cap both attempt count and total duration to prevent infinite retry loops.
## Quick Start
```python
from tenacity import retry, stop_after_attempt, wait_exponential_jitter
@retry(
stop=stop_after_attempt(3),
wait=wait_exponential_jitter(initial=1, max=10),
)
def call_external_service(request: dict) -> dict:
return httpx.post("https://api.example.com", json=request).json()
```
## Fundamental Patterns
### Pattern 1: Basic Retry with Tenacity
Use the `tenacity` library for production-grade retry logic. For simpler cases, consider built-in retry functionality or a lightweight custom implementation.
```python
from tenacity import (
retry,
stop_after_attempt,
stop_after_delay,
wait_exponential_jitter,
retry_if_exception_type,
)
TRANSIENT_ERRORS = (ConnectionError, TimeoutError, OSError)
@retry(
retry=retry_if_exception_type(TRANSIENT_ERRORS),
stop=stop_after_attempt(5) | stop_after_delay(60),
wait=wait_exponential_jitter(initial=1, max=30),
)
def fetch_data(url: str) -> dict:
"""Fetch data with automatic retry on transient failures."""
response = httpx.get(url, timeout=30)
response.raise_for_status()
return response.json()
```
### Pattern 2: Retry Only Appropriate Errors
Whitelist specific transient exceptions. Never retry:
- `ValueError`, `TypeError` - These are bugs, not transient issues
- `AuthenticationError` - Invalid credentials won't become valid
- HTTP 4xx errors (except 429) - Client errors are permanent
```python
from tenacity import retry, retry_if_exception_type
import httpx
# Define what's retryable
RETRYABLE_EXCEPTIONS = (
ConnectionError,
TimeoutError,
httpx.ConnectTimeout,
httpx.ReadTimeout,
)
@retry(
retry=retry_if_exception_type(RETRYABLE_EXCEPTIONS),
stop=stop_after_attempt(3),
wait=wait_exponential_jitter(initial=1, max=10),
)
def resilient_api_call(endpoint: str) -> dict:
"""Make API call with retry on network issues."""
return httpx.get(endpoint, timeout=10).json()
```
### Pattern 3: HTTP Status Code Retries
Retry specific HTTP status codes that indicate transient issues.
```python
from tenacity import retry, retry_if_result, stop_after_attempt
import httpx
RETRY_STATUS_CODES = {429, 502, 503, 504}
def should_retry_response(response: httpx.Response) -> bool:
"""Check if response indicates a retryable error."""
return response.status_code in RETRY_STATUS_CODES
@retry(
retry=retry_if_result(should_retry_response),
stop=stop_after_attempt(3),
wait=wait_exponential_jitter(initial=1, max=10),
)
def http_request(method: str, url: str, **kwargs) -> httpx.Response:
"""Make HTTP request with retry on transient status codes."""
return httpx.request(method, url, timeout=30, **kwargs)
```
### Pattern 4: Combined Exception and Status Retry
Handle both network exceptions and HTTP status codes.
```python
from tenacity import (
retry,
retry_if_exception_type,
retry_if_result,
stop_after_attempt,
wait_exponential_jitter,
before_sleep_log,
)
import logging
import httpx
logger = logging.getLogger(__name__)
TRANSIENT_EXCEPTIONS = (
ConnectionError,
TimeoutError,
httpx.ConnectError,
httpx.ReadTimeout,
)
RETRY_STATUS_CODES = {429, 500, 502, 503, 504}
def is_retryable_response(response: httpx.Response) -> bool:
return response.status_code in RETRY_STATUS_CODES
@retry(
retry=(
retry_if_exception_type(TRANSIENT_EXCEPTIONS) |
retry_if_result(is_retryable_response)
),
stop=stop_after_attempt(5),
wait=wait_exponential_jitter(initial=1, max=30),
before_sleep=before_sleep_log(logger, logging.WARNING),
)
def robust_http_call(
method: str,
url: str,
**kwargs,
) -> httpx.Response:
"""HTTP call with comprehensive retry handling."""
return httpx.request(method, url, timeout=30, **kwargs)
```
## Detailed worked examples and patterns
Detailed sections (starting with `## Advanced Patterns`) live in `references/details.md`. Read that file when the navigation summary above is insufficient.
## Best Practices Summary
1. **Retry only transient errors** - Don't retry bugs or authentication failures
2. **Use exponential backoff** - Give services time to recover
3. **Add jitter** - Prevent thundering herd from synchronized retries
4. **Cap total duration** - `stop_after_attempt(5) | stop_after_delay(60)`
5. **Log every retry** - Silent retries hide systemic problems
6. **Use decorators** - Keep retry logic separate from business logic
7. **Inject dependencies** - Make infrastructure testable
8. **Set timeouts everywhere** - Every network call needs a timeout
9. **Fail gracefully** - Return cached/default values for non-critical paths
10. **Monitor retry rates** - High retry rates indicate underlying issues
© Seth Hobson · MIT · wshobson/agents