@@ -22,6 +22,7 @@ The following middleware work with any LLM provider:
2222| [ To-do list] ( #to-do-list ) | Equip agents with task planning and tracking capabilities. |
2323| [ LLM tool selector] ( #llm-tool-selector ) | Use an LLM to select relevant tools before calling main model. |
2424| [ Tool retry] ( #tool-retry ) | Automatically retry failed tool calls with exponential backoff. |
25+ | [ Model retry] ( #model-retry ) | Automatically retry failed model calls with exponential backoff. |
2526| [ LLM tool emulator] ( #llm-tool-emulator ) | Emulate tool execution using an LLM for testing purposes. |
2627| [ Context editing] ( #context-editing ) | Manage conversation context by trimming or clearing tool uses. |
2728| [ Shell tool] ( #shell-tool ) | Expose a persistent shell session to agents for command execution. |
@@ -42,6 +43,7 @@ The following middleware work with any LLM provider:
4243| [ To-do list] ( #to-do-list ) | Equip agents with task planning and tracking capabilities. |
4344| [ LLM tool selector] ( #llm-tool-selector ) | Use an LLM to select relevant tools before calling main model. |
4445| [ Tool retry] ( #tool-retry ) | Automatically retry failed tool calls with exponential backoff. |
46+ | [ Model retry] ( #model-retry ) | Automatically retry failed model calls with exponential backoff. |
4547| [ LLM tool emulator] ( #llm-tool-emulator ) | Emulate tool execution using an LLM for testing purposes. |
4648| [ Context editing] ( #context-editing ) | Manage conversation context by trimming or clearing tool uses. |
4749
@@ -1261,11 +1263,13 @@ const agent = createAgent({
12611263 Either an array of error constructors to retry on, or a function that takes an error and returns ` true ` if it should be retried. Default is to retry on all errors.
12621264</ParamField >
12631265
1264- <ParamField body = " onFailure" type = " 'raise ' | 'return_message ' | ((error: Error) => string)" default = " return_message " >
1266+ <ParamField body = " onFailure" type = " 'error ' | 'continue ' | ((error: Error) => string)" default = " continue " >
12651267 Behavior when all retries are exhausted. Options:
1266- - ` 'return_message ' ` (default) - Return a ` ToolMessage ` with error details, allowing the LLM to handle the failure and potentially recover
1267- - ` 'raise ' ` - Re-raise the exception, stopping agent execution
1268+ - ` 'continue ' ` (default) - Return a ` ToolMessage ` with error details, allowing the LLM to handle the failure and potentially recover
1269+ - ` 'error ' ` - Re-raise the exception, stopping agent execution
12681270 - Custom function - Function that takes the exception and returns a string for the ` ToolMessage ` content, allowing custom error formatting
1271+
1272+ ** Deprecated values:** ` 'raise' ` (use ` 'error' ` instead) and ` 'return_message' ` (use ` 'continue' ` instead). These deprecated values still work but will show a warning.
12691273</ParamField >
12701274
12711275<ParamField body = " backoffFactor" type = " number" default = " 2.0" >
@@ -1313,8 +1317,8 @@ The middleware automatically retries failed tool calls with exponential backoff.
13131317- ` jitter ` - Add random variation (default: true)
13141318
13151319** Failure handling:**
1316- - ` onFailure: "return_message" ` - Return error message
1317- - ` onFailure: "raise " ` - Re-raise exception
1320+ - ` onFailure: "continue" ` (default) - Return error message
1321+ - ` onFailure: "error " ` - Re-raise exception
13181322- Custom function - Function returning error message
13191323:::
13201324
@@ -1416,7 +1420,281 @@ const constantBackoff = toolRetryMiddleware({
14161420// Raise exception on failure
14171421const strictRetry = toolRetryMiddleware ({
14181422 maxRetries: 2 ,
1419- onFailure: " raise" , // Re-raise exception instead of returning message
1423+ onFailure: " error" , // Re-raise exception instead of returning message
1424+ });
1425+ ```
1426+ :::
1427+
1428+ </Accordion >
1429+
1430+
1431+ ### Model retry
1432+
1433+ Automatically retry failed model calls with configurable exponential backoff. Model retry is useful for the following:
1434+
1435+ - Handling transient failures in model API calls.
1436+ - Improving reliability of network-dependent model requests.
1437+ - Building resilient agents that gracefully handle temporary model errors.
1438+
1439+ :::python
1440+ ** API reference:** @[ ` ModelRetryMiddleware ` ]
1441+
1442+ ``` python
1443+ from langchain.agents import create_agent
1444+ from langchain.agents.middleware import ModelRetryMiddleware
1445+
1446+ agent = create_agent(
1447+ model = " gpt-4o" ,
1448+ tools = [search_tool, database_tool],
1449+ middleware = [
1450+ ModelRetryMiddleware(
1451+ max_retries = 3 ,
1452+ backoff_factor = 2.0 ,
1453+ initial_delay = 1.0 ,
1454+ ),
1455+ ],
1456+ )
1457+ ```
1458+ :::
1459+
1460+ :::js
1461+ ** API reference:** @[ ` modelRetryMiddleware ` ]
1462+
1463+ ``` typescript
1464+ import { createAgent , modelRetryMiddleware } from " langchain" ;
1465+
1466+ const agent = createAgent ({
1467+ model: " gpt-4o" ,
1468+ tools: [searchTool , databaseTool ],
1469+ middleware: [
1470+ modelRetryMiddleware ({
1471+ maxRetries: 3 ,
1472+ backoffFactor: 2.0 ,
1473+ initialDelayMs: 1000 ,
1474+ }),
1475+ ],
1476+ });
1477+ ```
1478+ :::
1479+
1480+ <Accordion title = " Configuration options" >
1481+
1482+ :::python
1483+ <ParamField body = " max_retries" type = " number" default = " 2" >
1484+ Maximum number of retry attempts after the initial call (3 total attempts with default)
1485+ </ParamField >
1486+
1487+ <ParamField body = " retry_on" type = " tuple[type[Exception], ...] | callable" default = " (Exception,)" >
1488+ Either a tuple of exception types to retry on, or a callable that takes an exception and returns ` True ` if it should be retried.
1489+ </ParamField >
1490+
1491+ <ParamField body = " on_failure" type = " string | callable" default = " continue" >
1492+ Behavior when all retries are exhausted. Options:
1493+ - ` 'continue' ` (default) - Return an ` AIMessage ` with error details, allowing the agent to potentially handle the failure gracefully
1494+ - ` 'error' ` - Re-raise the exception (stops agent execution)
1495+ - Custom callable - Function that takes the exception and returns a string for the ` AIMessage ` content
1496+ </ParamField >
1497+
1498+ <ParamField body = " backoff_factor" type = " number" default = " 2.0" >
1499+ Multiplier for exponential backoff. Each retry waits ` initial_delay * (backoff_factor ** retry_number) ` seconds. Set to ` 0.0 ` for constant delay.
1500+ </ParamField >
1501+
1502+ <ParamField body = " initial_delay" type = " number" default = " 1.0" >
1503+ Initial delay in seconds before first retry
1504+ </ParamField >
1505+
1506+ <ParamField body = " max_delay" type = " number" default = " 60.0" >
1507+ Maximum delay in seconds between retries (caps exponential backoff growth)
1508+ </ParamField >
1509+
1510+ <ParamField body = " jitter" type = " boolean" default = " true" >
1511+ Whether to add random jitter (` ±25% ` ) to delay to avoid thundering herd
1512+ </ParamField >
1513+ :::
1514+
1515+ :::js
1516+ <ParamField body = " maxRetries" type = " number" default = " 2" >
1517+ Maximum number of retry attempts after the initial call (3 total attempts with default). Must be >= 0.
1518+ </ParamField >
1519+
1520+ <ParamField body = " retryOn" type = " ((error: Error) => boolean) | (new (...args: any[]) => Error)[]" default = " () => true" >
1521+ Either an array of error constructors to retry on, or a function that takes an error and returns ` true ` if it should be retried. Default is to retry on all errors.
1522+ </ParamField >
1523+
1524+ <ParamField body = " onFailure" type = " 'error' | 'continue' | ((error: Error) => string)" default = " continue" >
1525+ Behavior when all retries are exhausted. Options:
1526+ - ` 'continue' ` (default) - Return an ` AIMessage ` with error details, allowing the agent to potentially handle the failure gracefully
1527+ - ` 'error' ` - Re-raise the exception, stopping agent execution
1528+ - Custom function - Function that takes the exception and returns a string for the ` AIMessage ` content, allowing custom error formatting
1529+ </ParamField >
1530+
1531+ <ParamField body = " backoffFactor" type = " number" default = " 2.0" >
1532+ Multiplier for exponential backoff. Each retry waits ` initialDelayMs * (backoffFactor ** retryNumber) ` milliseconds. Set to ` 0.0 ` for constant delay. Must be >= 0.
1533+ </ParamField >
1534+
1535+ <ParamField body = " initialDelayMs" type = " number" default = " 1000" >
1536+ Initial delay in milliseconds before first retry. Must be >= 0.
1537+ </ParamField >
1538+
1539+ <ParamField body = " maxDelayMs" type = " number" default = " 60000" >
1540+ Maximum delay in milliseconds between retries (caps exponential backoff growth). Must be >= 0.
1541+ </ParamField >
1542+
1543+ <ParamField body = " jitter" type = " boolean" default = " true" >
1544+ Whether to add random jitter (` ±25% ` ) to delay to avoid thundering herd
1545+ </ParamField >
1546+ :::
1547+
1548+ </Accordion >
1549+
1550+ <Accordion title = " Full example" >
1551+
1552+ The middleware automatically retries failed model calls with exponential backoff.
1553+
1554+ :::python
1555+ ``` python
1556+ from langchain.agents import create_agent
1557+ from langchain.agents.middleware import ModelRetryMiddleware
1558+
1559+
1560+ # Basic usage with default settings (2 retries, exponential backoff)
1561+ agent = create_agent(
1562+ model = " gpt-4o" ,
1563+ tools = [search_tool],
1564+ middleware = [ModelRetryMiddleware()],
1565+ )
1566+
1567+ # Custom exception filtering
1568+ class TimeoutError (Exception ):
1569+ """ Custom exception for timeout errors."""
1570+ pass
1571+
1572+ class ConnectionError (Exception ):
1573+ """ Custom exception for connection errors."""
1574+ pass
1575+
1576+ # Retry specific exceptions only
1577+ retry = ModelRetryMiddleware(
1578+ max_retries = 4 ,
1579+ retry_on = (TimeoutError , ConnectionError ),
1580+ backoff_factor = 1.5 ,
1581+ )
1582+
1583+
1584+ def should_retry (error : Exception ) -> bool :
1585+ # Only retry on rate limit errors
1586+ if isinstance (error, TimeoutError ):
1587+ return True
1588+ # Or check for specific HTTP status codes
1589+ if hasattr (error, " status_code" ):
1590+ return error.status_code in (429 , 503 )
1591+ return False
1592+
1593+ retry_with_filter = ModelRetryMiddleware(
1594+ max_retries = 3 ,
1595+ retry_on = should_retry,
1596+ )
1597+
1598+ # Return error message instead of raising
1599+ retry_continue = ModelRetryMiddleware(
1600+ max_retries = 4 ,
1601+ on_failure = " continue" , # Return AIMessage with error instead of raising
1602+ )
1603+
1604+ # Custom error message formatting
1605+ def format_error (error : Exception ) -> str :
1606+ return f " Model call failed: { error} . Please try again later. "
1607+
1608+ retry_with_formatter = ModelRetryMiddleware(
1609+ max_retries = 4 ,
1610+ on_failure = format_error,
1611+ )
1612+
1613+ # Constant backoff (no exponential growth)
1614+ constant_backoff = ModelRetryMiddleware(
1615+ max_retries = 5 ,
1616+ backoff_factor = 0.0 , # No exponential growth
1617+ initial_delay = 2.0 , # Always wait 2 seconds
1618+ )
1619+
1620+ # Raise exception on failure
1621+ strict_retry = ModelRetryMiddleware(
1622+ max_retries = 2 ,
1623+ on_failure = " error" , # Re-raise exception instead of returning message
1624+ )
1625+ ```
1626+ :::
1627+
1628+ :::js
1629+ ``` typescript
1630+ import { createAgent , modelRetryMiddleware } from " langchain" ;
1631+
1632+ // Basic usage with default settings (2 retries, exponential backoff)
1633+ const agent = createAgent ({
1634+ model: " gpt-4o" ,
1635+ tools: [searchTool ],
1636+ middleware: [modelRetryMiddleware ()],
1637+ });
1638+
1639+ class TimeoutError extends Error {
1640+ // ...
1641+ }
1642+ class NetworkError extends Error {
1643+ // ...
1644+ }
1645+
1646+ // Retry specific exceptions only
1647+ const retry = modelRetryMiddleware ({
1648+ maxRetries: 4 ,
1649+ retryOn: [TimeoutError , NetworkError ],
1650+ backoffFactor: 1.5 ,
1651+ });
1652+
1653+ // Custom exception filtering
1654+ function shouldRetry(error : Error ): boolean {
1655+ // Only retry on rate limit errors
1656+ if (error .name === " RateLimitError" ) {
1657+ return true ;
1658+ }
1659+ // Or check for specific HTTP status codes
1660+ if (error .name === " HTTPError" && " statusCode" in error ) {
1661+ const statusCode = (error as any ).statusCode ;
1662+ return statusCode === 429 || statusCode === 503 ;
1663+ }
1664+ return false ;
1665+ }
1666+
1667+ const retryWithFilter = modelRetryMiddleware ({
1668+ maxRetries: 3 ,
1669+ retryOn: shouldRetry ,
1670+ });
1671+
1672+ // Return error message instead of raising
1673+ const retryContinue = modelRetryMiddleware ({
1674+ maxRetries: 4 ,
1675+ onFailure: " continue" , // Return AIMessage with error instead of throwing
1676+ });
1677+
1678+ // Custom error message formatting
1679+ const formatError = (error : Error ) =>
1680+ ` Model call failed: ${error .message }. Please try again later. ` ;
1681+
1682+ const retryWithFormatter = modelRetryMiddleware ({
1683+ maxRetries: 4 ,
1684+ onFailure: formatError ,
1685+ });
1686+
1687+ // Constant backoff (no exponential growth)
1688+ const constantBackoff = modelRetryMiddleware ({
1689+ maxRetries: 5 ,
1690+ backoffFactor: 0.0 , // No exponential growth
1691+ initialDelayMs: 2000 , // Always wait 2 seconds
1692+ });
1693+
1694+ // Raise exception on failure
1695+ const strictRetry = modelRetryMiddleware ({
1696+ maxRetries: 2 ,
1697+ onFailure: " error" , // Re-raise exception instead of returning message
14201698});
14211699```
14221700:::
0 commit comments