src/anthropic/_middleware.py defines the middleware system for the Anthropic SDK, exporting Middleware (base class), CallNext, AsyncCallNext, MiddlewareCallable, AsyncMiddlewareCallable, and MiddlewareInput as its public API surface.[1] MiddlewareInput accepts three forms: a Middleware subclass instance, a sync callable (MiddlewareCallable), or an async callable (AsyncMiddlewareCallable).[1] A middleware is a composable interceptor layer that runs before and after each HTTP attempt, enabling custom logic such as logging, header injection, or retry augmentation within the Anthropic SDK's request pipeline.
The middleware chain runs inside the SDK's retry loop — once per HTTP attempt — so each middleware sees individual attempts, not the full retry sequence.[1] CallNext returns an APIResponse for every HTTP response, including 4xx/5xx; middleware should inspect response.status_code to react to API errors, because the SDK raises its typed errors to the original caller only after the chain completes.[1] Connection failures — where no response object exists — raise exceptions directly from CallNext: either APITimeoutError or APIConnectionError.[1]
validate_sync_middleware raises TypeError if a Middleware subclass has not overridden handle, if handle is defined as an async function, or if a plain callable middleware is async — enforcing that the sync client receives only sync-capable middleware.[1] validate_async_middleware raises TypeError if a Middleware subclass has not overridden handle_async, if handle_async is defined as a sync function, or if a plain callable middleware is not async — enforcing that the async client receives only async-capable middleware.[1]
Sources