F1 · States that the bare model-retry middleware re-raises when retries run out; the shipped default returns an AIMessage and the agent carries on
langchain 1.1.0 shipped 2025-11-24, inside every tested subject's stated window.
"What invoke does: it raises, not returns. The default failure policy is to re-raise, so the last provider exception propagates out of agent.invoke(...) unchanged ... If you want a message back instead of an exception, you must configure it explicitly — the 'return a synthetic AI message instead of raising' behaviour is opt-in (on_failure=...), not the default."
agent = create_agent(
model="anthropic:claude-sonnet-4-5",
tools=tools,
middleware=[ModelRetryMiddleware()],
)
# claimed: 3 calls, then the provider exception propagates out of invoke()agent = create_agent(
model,
tools,
middleware=[ModelRetryMiddleware(on_failure="error")],
)
# or, keeping the default, handle the synthetic reply:
# the last AIMessage will read "Model call failed after 3 attempts with ..."The default is on_failure="continue", which swallows the provider exception and returns a ModelResponse carrying a synthetic AIMessage reading "Model call failed after 3 attempts with {ExcType}: {message}". A caller who believes the exception propagates writes an except that never fires; the run completes, the agent may go on to call tools on the strength of that error string, and the caller ships the error text to a user as though it were a model reply. Re-raising is one keyword away and is not the default.
Half-right, and the half that is right is the half that does not matter: the subject named the retry count correctly (2 retries, 3 calls) and got the exhaustion behaviour backwards. Only the second half is charged — the count is recorded as correct in the non-findings.
- LangChain changelog — langchain v1.1.0 published 2025-11-24
Model retry middleware: New middleware for automatically retrying failed model calls with configurable exponential backoff.
- langchain 1.3.18 published wheel — langchain/agents/middleware/model_retry.py published 2026-08-27
max_retries: int = 2, retry_on: RetryOn = default_retry_on, on_failure: OnFailure = "continue", ... if self.on_failure == "error": raise exc ... return ModelResponse(result=[ai_msg])