@@ -13,9 +13,7 @@ seamlessly with httpx clients. You can configure retry behavior for any provider
13
13
To use the retry transports, you need to install the ` tenacity ` dependency:
14
14
15
15
``` bash
16
- pip install tenacity
17
- # or if using uv
18
- uv add tenacity
16
+ pip/uv-add ' pydantic-ai-slim[tenacity]'
19
17
```
20
18
21
19
## Usage Example
@@ -32,7 +30,7 @@ from tenacity import (
32
30
)
33
31
from pydantic_ai import Agent
34
32
from pydantic_ai.models.openai import OpenAIModel
35
- from pydantic_ai.tenacity import AsyncTenacityTransport, wait_retry_after
33
+ from pydantic_ai.retries import AsyncTenacityTransport, wait_retry_after
36
34
from pydantic_ai.providers.openai import OpenAIProvider
37
35
38
36
def create_retrying_client ():
@@ -74,7 +72,7 @@ agent = Agent(model)
74
72
The ` wait_retry_after ` function is a smart wait strategy that automatically respects HTTP ` Retry-After ` headers:
75
73
76
74
``` python {title="wait_strategy_example.py"}
77
- from pydantic_ai.tenacity import wait_retry_after
75
+ from pydantic_ai.retries import wait_retry_after
78
76
from tenacity import wait_exponential
79
77
80
78
# Basic usage - respects Retry-After headers, falls back to exponential backoff
@@ -102,7 +100,7 @@ For asynchronous HTTP clients (recommended for most use cases):
102
100
``` python {title="async_transport_example.py"}
103
101
from httpx import AsyncClient
104
102
from tenacity import AsyncRetrying, stop_after_attempt
105
- from pydantic_ai.tenacity import AsyncTenacityTransport
103
+ from pydantic_ai.retries import AsyncTenacityTransport
106
104
107
105
# Create the basic components
108
106
async_retrying = AsyncRetrying(stop = stop_after_attempt(3 ), reraise = True )
@@ -128,7 +126,7 @@ For synchronous HTTP clients:
128
126
``` python {title="sync_transport_example.py"}
129
127
from httpx import Client
130
128
from tenacity import Retrying, stop_after_attempt
131
- from pydantic_ai.tenacity import TenacityTransport
129
+ from pydantic_ai.retries import TenacityTransport
132
130
133
131
# Create the basic components
134
132
retrying = Retrying(stop = stop_after_attempt(3 ), reraise = True )
@@ -154,7 +152,7 @@ client = Client(transport=transport)
154
152
``` python {title="rate_limit_handling.py"}
155
153
from httpx import AsyncClient, HTTPStatusError
156
154
from tenacity import AsyncRetrying, stop_after_attempt, retry_if_exception_type, wait_exponential
157
- from pydantic_ai.tenacity import AsyncTenacityTransport, wait_retry_after
155
+ from pydantic_ai.retries import AsyncTenacityTransport, wait_retry_after
158
156
159
157
def create_rate_limit_client ():
160
158
""" Create a client that respects Retry-After headers from rate limiting responses."""
@@ -184,7 +182,7 @@ The `wait_retry_after` function automatically detects `Retry-After` headers in 4
184
182
``` python {title="network_error_handling.py"}
185
183
import httpx
186
184
from tenacity import AsyncRetrying, retry_if_exception_type, wait_exponential, stop_after_attempt
187
- from pydantic_ai.tenacity import AsyncTenacityTransport
185
+ from pydantic_ai.retries import AsyncTenacityTransport
188
186
189
187
def create_network_resilient_client ():
190
188
""" Create a client that handles network errors with retries."""
@@ -212,7 +210,7 @@ client = create_network_resilient_client()
212
210
``` python {title="custom_retry_logic.py"}
213
211
import httpx
214
212
from tenacity import AsyncRetrying, wait_exponential, stop_after_attempt
215
- from pydantic_ai.tenacity import AsyncTenacityTransport, wait_retry_after
213
+ from pydantic_ai.retries import AsyncTenacityTransport, wait_retry_after
216
214
217
215
def create_custom_retry_client ():
218
216
""" Create a client with custom retry logic."""
@@ -249,30 +247,12 @@ The retry transports work with any provider that accepts a custom HTTP client:
249
247
250
248
### OpenAI
251
249
252
- ``` python {title="openai_with_retries.py"}
253
- from httpx import AsyncClient, HTTPStatusError
254
- from tenacity import AsyncRetrying, stop_after_attempt, retry_if_exception_type
250
+ ``` python {title="openai_with_retries.py" requires="smart_retry_example.py"}
255
251
from pydantic_ai import Agent
256
252
from pydantic_ai.models.openai import OpenAIModel
257
253
from pydantic_ai.providers.openai import OpenAIProvider
258
- from pydantic_ai.tenacity import AsyncTenacityTransport, wait_retry_after
259
254
260
- def create_retrying_client ():
261
- """ Create a client with retry functionality."""
262
- def should_retry_status (response ):
263
- if response.status_code in (429 , 502 , 503 , 504 ):
264
- response.raise_for_status()
265
-
266
- transport = AsyncTenacityTransport(
267
- controller = AsyncRetrying(
268
- retry = retry_if_exception_type(HTTPStatusError),
269
- wait = wait_retry_after(max_wait = 300 ),
270
- stop = stop_after_attempt(5 ),
271
- reraise = True
272
- ),
273
- validate_response = should_retry_status
274
- )
275
- return AsyncClient(transport = transport)
255
+ from smart_retry_example import create_retrying_client
276
256
277
257
client = create_retrying_client()
278
258
model = OpenAIModel(' gpt-4o' , provider = OpenAIProvider(http_client = client))
@@ -281,30 +261,12 @@ agent = Agent(model)
281
261
282
262
### Anthropic
283
263
284
- ``` python {title="anthropic_with_retries.py"}
285
- from httpx import AsyncClient, HTTPStatusError
286
- from tenacity import AsyncRetrying, stop_after_attempt, retry_if_exception_type
264
+ ``` python {title="anthropic_with_retries.py" requires="smart_retry_example.py"}
287
265
from pydantic_ai import Agent
288
266
from pydantic_ai.models.anthropic import AnthropicModel
289
267
from pydantic_ai.providers.anthropic import AnthropicProvider
290
- from pydantic_ai.tenacity import AsyncTenacityTransport, wait_retry_after
291
268
292
- def create_retrying_client ():
293
- """ Create a client with retry functionality."""
294
- def should_retry_status (response ):
295
- if response.status_code in (429 , 502 , 503 , 504 ):
296
- response.raise_for_status()
297
-
298
- transport = AsyncTenacityTransport(
299
- controller = AsyncRetrying(
300
- retry = retry_if_exception_type(HTTPStatusError),
301
- wait = wait_retry_after(max_wait = 300 ),
302
- stop = stop_after_attempt(5 ),
303
- reraise = True
304
- ),
305
- validate_response = should_retry_status
306
- )
307
- return AsyncClient(transport = transport)
269
+ from smart_retry_example import create_retrying_client
308
270
309
271
client = create_retrying_client()
310
272
model = AnthropicModel(' claude-3-5-sonnet-20241022' , provider = AnthropicProvider(http_client = client))
@@ -313,30 +275,12 @@ agent = Agent(model)
313
275
314
276
### Any OpenAI-Compatible Provider
315
277
316
- ``` python {title="openai_compatible_with_retries.py"}
317
- from httpx import AsyncClient, HTTPStatusError
318
- from tenacity import AsyncRetrying, stop_after_attempt, retry_if_exception_type
278
+ ``` python {title="openai_compatible_with_retries.py" requires="smart_retry_example.py"}
319
279
from pydantic_ai import Agent
320
280
from pydantic_ai.models.openai import OpenAIModel
321
281
from pydantic_ai.providers.openai import OpenAIProvider
322
- from pydantic_ai.tenacity import AsyncTenacityTransport, wait_retry_after
323
282
324
- def create_retrying_client ():
325
- """ Create a client with retry functionality."""
326
- def should_retry_status (response ):
327
- if response.status_code in (429 , 502 , 503 , 504 ):
328
- response.raise_for_status()
329
-
330
- transport = AsyncTenacityTransport(
331
- controller = AsyncRetrying(
332
- retry = retry_if_exception_type(HTTPStatusError),
333
- wait = wait_retry_after(max_wait = 300 ),
334
- stop = stop_after_attempt(5 ),
335
- reraise = True
336
- ),
337
- validate_response = should_retry_status
338
- )
339
- return AsyncClient(transport = transport)
283
+ from smart_retry_example import create_retrying_client
340
284
341
285
client = create_retrying_client()
342
286
model = OpenAIModel(
@@ -368,30 +312,12 @@ agent = Agent(model)
368
312
369
313
The retry transports will re-raise the last exception if all retry attempts fail. Make sure to handle these appropriately in your application:
370
314
371
- ``` python {title="error_handling_example.py"}
372
- from httpx import AsyncClient, HTTPStatusError
373
- from tenacity import AsyncRetrying, stop_after_attempt, retry_if_exception_type
315
+ ``` python {title="error_handling_example.py" requires="smart_retry_example.py"}
374
316
from pydantic_ai import Agent
375
317
from pydantic_ai.models.openai import OpenAIModel
376
318
from pydantic_ai.providers.openai import OpenAIProvider
377
- from pydantic_ai.tenacity import AsyncTenacityTransport, wait_retry_after
378
319
379
- def create_retrying_client ():
380
- """ Create a client with retry functionality."""
381
- def should_retry_status (response ):
382
- if response.status_code in (429 , 502 , 503 , 504 ):
383
- response.raise_for_status()
384
-
385
- transport = AsyncTenacityTransport(
386
- controller = AsyncRetrying(
387
- retry = retry_if_exception_type(HTTPStatusError),
388
- wait = wait_retry_after(max_wait = 300 ),
389
- stop = stop_after_attempt(3 ), # Low for demonstration
390
- reraise = True
391
- ),
392
- validate_response = should_retry_status
393
- )
394
- return AsyncClient(transport = transport)
320
+ from smart_retry_example import create_retrying_client
395
321
396
322
client = create_retrying_client()
397
323
model = OpenAIModel(' gpt-4o' , provider = OpenAIProvider(http_client = client))
0 commit comments