---
title: Middleware del SDK
url: https://platform.claude.com/docs/es/cli-sdks-libraries/middleware
description: Intercepta y modifica las solicitudes y respuestas del SDK.
---

El SDK de Claude proporciona un hook de "middleware" (software intermedio), o interceptor, que te permite ejecutar código antes de que se envíe una solicitud y después de recibir la respuesta. Usa middleware para aspectos transversales como el registro, reintentos personalizados, anotación de solicitudes y manejo de respaldo ante rechazos.

```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 puede inspeccionar o reemplazar la solicitud antes de llamar a `next()`, y la respuesta después de que `next()` retorne.

## Registrar middleware

Cada middleware es una función que recibe la solicitud saliente y el siguiente manejador. Llama a `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 reenviar la solicitud al resto de la cadena (o directamente al núcleo del SDK si este es el último middleware), y devuelve su respuesta. Todo lo que está antes de esa llamada se ejecuta a la ida; todo lo que está después se ejecuta a la vuelta.

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

      # Reenvía la solicitud al resto de la cadena
      response = call_next(request)

      # Después de la solicitud
      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 de la solicitud
    ctx.logger.debug("->", request.method, request.url);

    // Reenvía la solicitud al resto de la cadena
    const response = await next(request);

    // Después de la solicitud
    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 de la solicitud
              Console.WriteLine($"Sending {request.Method} {request.RequestUri}");

              // Reenvía la solicitud al siguiente manejador
              var response = await next(request, cancellationToken);

              // Después de la solicitud
              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 de la solicitud
  		start := time.Now()
  		slog.Info("sending request", "method", req.Method, "url", req.URL)

  		// Reenvía la solicitud al resto de la cadena
  		res, err := next(req)
  		if err != nil {
  			return nil, err
  		}

  		// Después de la solicitud
  		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 de la solicitud
          IO.println(request.method() + " /" + String.join("/", request.pathSegments()));

          // Reenvía la solicitud al siguiente manejador
          HttpResponse response = nextClient.execute(request, requestOptions);

          // Después de la solicitud
          IO.println(response.statusCode());

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

  ```php PHP
  $loggingMiddleware = function (RequestInterface $request, callable $next): ResponseInterface {
      // Antes de la solicitud
      error_log("-> {$request->getMethod()} {$request->getUri()}");

      // Reenvía la solicitud al resto de la cadena
      $response = $next($request);

      // Después de la solicitud
      error_log("<- {$response->getStatusCode()}");

      return $response;
  };

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

  ```ruby Ruby
  logging_middleware = lambda do |request, call_next|
    # Antes de la solicitud
    puts "-> #{request.method.upcase} #{request.url}"

    # Reenvía la solicitud al resto de la cadena
    response = call_next.call(request)

    # Después de la solicitud
    puts "<- #{response.status}"

    response
  end

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

## Orden del middleware

Cuando registras varios middleware, se aplican en el orden dado: el código "antes" del primer middleware se ejecuta primero, y su código "después" se ejecuta al final. El middleware registrado en el cliente se ejecuta antes que el middleware pasado como opción por solicitud.

En el SDK de Go, las llamadas repetidas a `option.WithMiddleware` se concatenan (primero las del cliente, luego las del método). En los demás SDKs, pasa un arreglo; las entradas posteriores envuelven a las internas.

## Reemplazar el cliente HTTP

El SDK también acepta un cliente HTTP personalizado (para configuración de proxy, TLS personalizado o "connection pooling" (agrupación de conexiones)). Solo se usa un cliente HTTP por cliente del SDK; configurarlo reemplaza el predeterminado. El cliente HTTP personalizado recibe las solicitudes después de que se haya ejecutado todo el middleware.

## Middleware integrado

El SDK incluye un middleware de respaldo ante rechazos que reintenta automáticamente en un modelo de respaldo una solicitud que Claude rechaza (`stop_reason: "refusal"`). [Rechazos y respaldo](https://platform.claude.com/docs/es/build-with-claude/refusals-and-fallback) enumera los modelos cuyos clasificadores de seguridad pueden rechazar solicitudes, y [Detectar y reintentar en un modelo de respaldo](https://platform.claude.com/docs/es/build-with-claude/refusals-and-fallback#client-side-fallback) cubre la configuración y ejemplos por lenguaje.
