---
title: Middleware do SDK
url: https://platform.claude.com/docs/pt-BR/cli-sdks-libraries/middleware
description: Intercepte e modifique as requisições e respostas do SDK.
---

O Claude SDK fornece um hook de "middleware" (intermediário), ou interceptor, que permite executar código antes de uma requisição ser enviada e depois que a resposta é recebida. Use middleware para preocupações transversais, como logging, retentativas personalizadas, anotação de requisições e tratamento de fallback em caso de recusa.

```mermaid
sequenceDiagram
    accTitle: How a request and its response pass through middleware
    accDescr: Your code sends the request to Middleware A. Middleware A calls next(request) to pass it to Middleware B, and Middleware B calls next(request) to pass it to the SDK core. The SDK core sends the HTTP request to the Claude API and receives the HTTP response. The response returns through Middleware B, then Middleware A, to your code.
    autonumber
    participant App as Your code
    participant M1 as Middleware A
    participant M2 as Middleware B
    participant Core as SDK core
    participant API as Claude API
    App->>M1: request
    M1->>M2: next(request)
    M2->>Core: next(request)
    Core->>API: HTTP request
    API-->>Core: HTTP response
    Core-->>M2: response
    M2-->>M1: response
    M1-->>App: response
```

Cada middleware pode inspecionar ou substituir a requisição antes de chamar `next()`, e a resposta depois que `next()` retorna.

## Registrando middleware

Cada middleware é uma função que recebe a requisição de saída e o próximo handler. Chame `call_next(request)` (typescript: `next(request)`; csharp: `next(request, cancellationToken)`; go: `next(req)`; java: `nextClient.execute(request, requestOptions)`; php: `$next($request)`; ruby: `call_next.call(request)`) para encaminhar a requisição para o restante da cadeia (ou diretamente para o núcleo do SDK, se este for o último middleware) e retorne sua resposta. Tudo o que vem antes dessa chamada é executado na ida; tudo o que vem depois é executado na volta.

<CodeGroup exclude="shell">
  ```python Python
  def logging_middleware(request: APIRequest, call_next: CallNext) -> APIResponse[Any]:
      # Antes da requisição
      print(f"-> {request.method} {request.url}")

      # Encaminha a requisição para o restante da cadeia
      response = call_next(request)

      # Depois da requisição
      print(f"<- {response.status_code}")

      return response


  client = Anthropic(middleware=[logging_middleware])
  ```

  ```typescript TypeScript
  import type { Middleware } from "@anthropic-ai/sdk";

  const loggingMiddleware: Middleware = async (request, next, ctx) => {
    // Antes da requisição
    ctx.logger.debug("->", request.method, request.url);

    // Encaminha a requisição para o restante da cadeia
    const response = await next(request);

    // Depois da requisição
    ctx.logger.debug("<-", response.status, request.url);

    return response;
  };

  const client = new Anthropic({ middleware: [loggingMiddleware] });
  ```

  ```csharp C#
  AnthropicClient client = new()
  {
      Handlers =
      [
          Handler.Create(async (request, next, cancellationToken) =>
          {
              // Antes da requisição
              Console.WriteLine($"Sending {request.Method} {request.RequestUri}");

              // Encaminha a requisição para o próximo handler
              var response = await next(request, cancellationToken);

              // Depois da requisição
              Console.WriteLine($"Received {(int)response.StatusCode}");

              return response;
          }),
      ],
  };
  ```

  ```go Go
  client := anthropic.NewClient(
  	option.WithMiddleware(func(req *http.Request, next option.MiddlewareNext) (*http.Response, error) {
  		// Antes da requisição
  		start := time.Now()
  		slog.Info("sending request", "method", req.Method, "url", req.URL)

  		// Encaminha a requisição para o restante da cadeia
  		res, err := next(req)
  		if err != nil {
  			return nil, err
  		}

  		// Depois da requisição
  		slog.Info("received response", "status", res.StatusCode, "duration", time.Since(start))

  		return res, nil
  	}),
  )
  ```

  ```java Java
  AnthropicClient client = AnthropicOkHttpClient.builder()
      .fromEnv()
      .addInterceptor(Interceptor.syncOnly((nextClient, request, requestOptions) -> {
          // Antes da requisição
          IO.println(request.method() + " /" + String.join("/", request.pathSegments()));

          // Encaminha a requisição para o próximo handler
          HttpResponse response = nextClient.execute(request, requestOptions);

          // Depois da requisição
          IO.println(response.statusCode());

          return response;
      }))
      .build();
  ```

  ```php PHP
  $loggingMiddleware = function (RequestInterface $request, callable $next): ResponseInterface {
      // Antes da requisição
      error_log("-> {$request->getMethod()} {$request->getUri()}");

      // Encaminha a requisição para o restante da cadeia
      $response = $next($request);

      // Depois da requisição
      error_log("<- {$response->getStatusCode()}");

      return $response;
  };

  $client = new Client(requestOptions: ['middleware' => [$loggingMiddleware]]);
  ```

  ```ruby Ruby
  logging_middleware = lambda do |request, call_next|
    # Antes da requisição
    puts "-> #{request.method.upcase} #{request.url}"

    # Encaminha a requisição para o restante da cadeia
    response = call_next.call(request)

    # Depois da requisição
    puts "<- #{response.status}"

    response
  end

  client = Anthropic::Client.new(middleware: [logging_middleware])
  ```
</CodeGroup>

## Ordem dos middlewares

Quando você registra vários middlewares, eles são aplicados na ordem fornecida: o código "antes" do primeiro middleware é executado primeiro, e seu código "depois" é executado por último. Middlewares registrados no cliente são executados antes dos middlewares passados como opção por requisição.

No SDK Go, chamadas repetidas a `option.WithMiddleware` são concatenadas (primeiro as do cliente, depois as do método). Nos outros SDKs, passe um array; as entradas posteriores envolvem as internas.

## Substituindo o cliente HTTP

O SDK também aceita um cliente HTTP personalizado (para configuração de proxy, TLS personalizado ou pool de conexões). Apenas um cliente HTTP é usado por cliente do SDK; defini-lo substitui o padrão. O cliente HTTP personalizado recebe as requisições depois que todos os middlewares foram executados.

## Middleware integrado

O SDK inclui um middleware de fallback em caso de recusa que repete automaticamente, em um modelo de fallback, uma requisição que Claude recusa (`stop_reason: "refusal"`). [Recusas e fallback](https://platform.claude.com/docs/pt-BR/build-with-claude/refusals-and-fallback) lista os modelos cujos classificadores de segurança podem recusar requisições, e [Detectar e repetir em um modelo de fallback](https://platform.claude.com/docs/pt-BR/build-with-claude/refusals-and-fallback#client-side-fallback) aborda a configuração e exemplos por linguagem.
