> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mka1.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Búsqueda web

> Permite que un modelo busque en la web y lea páginas, y consulta qué proveedor atiende esas solicitudes y qué datos recibe.

Agrega una herramienta de búsqueda web a una solicitud de [Respuestas](https://docs.mka1.com/docs/responses.md) cuando el modelo necesite información actual de la web pública. La API de MKA1 envía las búsquedas y las solicitudes de páginas del modelo a [Serper](https://serper.dev), una API de búsqueda de terceros que devuelve resultados de búsqueda de Google.

Esta página explica cómo habilitar la búsqueda web, qué contiene cada solicitud saliente y cómo limitar la búsqueda web a dominios específicos.

## Habilitar la búsqueda web

Agrega a `tools` una herramienta con tipo `web_search`. La API también acepta `web_search_2025_08_26`, `web_search_preview` y `web_search_preview_2025_03_11`, que le dan al modelo las mismas herramientas.

Una herramienta de búsqueda web le da al modelo tres herramientas. El modelo decide cuándo llamar a cada una:

| Herramienta | Qué hace | Cómo aparece la llamada en la salida de la respuesta |
| - | - | - |
| `web_search` | Ejecuta una consulta de búsqueda y devuelve títulos, enlaces y fragmentos | Elemento `web_search_call` con `action.type` igual a `search` y la consulta |
| `scrape` | Lee el texto de una página en una URL | Elemento `web_search_call` con `action.type` igual a `open_page` y la URL |
| `web_find` | Busca las líneas de una página que coinciden con una palabra o un patrón | Elemento `web_search_call` con `action.type` igual a `find`, la URL y el patrón |

Revisa los elementos `web_search_call` de la salida de la respuesta para ver cada consulta y cada URL que solicitó el modelo.

Esta solicitud hace una pregunta que necesita información actual:

```ts TypeScript SDK theme={null}
import { SDK } from '@meetkai/mka1';

const sdk = new SDK({ bearerAuth: 'Bearer <mka1-api-key>' });

const response = await sdk.llm.responses.create({
  xOnBehalfOf: '<end-user-id>', // opcional — atribuye la solicitud a uno de tus usuarios finales
  responsesCreateRequest: {
    model: 'meetkai:functionary-es-mini',
    input: '¿Cuál es la versión estable más reciente de Python? Cita tus fuentes.',
    tools: [{ type: 'web_search', searchContextSize: 'low', userLocation: { country: 'US' } }],
  },
});
console.log(response);
```

```ts OpenAI SDK theme={null}
import OpenAI from 'openai';

const openai = new OpenAI({
  apiKey: '<mka1-api-key>',
  baseURL: 'https://apigw.mka1.com/api/v1/llm/',
  defaultHeaders: { 'X-On-Behalf-Of': '<end-user-id>' },
});

const response = await openai.responses.create({
  model: 'meetkai:functionary-es-mini',
  input: '¿Cuál es la versión estable más reciente de Python? Cita tus fuentes.',
  tools: [{ type: 'web_search', search_context_size: 'low', user_location: { type: 'approximate', country: 'US' } }],
});
console.log(response);
```

```python Python SDK theme={null}
from meetkai_mka1 import SDK

sdk = SDK(bearer_auth="Bearer <mka1-api-key>")

response = sdk.llm.responses.create(
    x_on_behalf_of="<end-user-id>",  # opcional — atribuye la solicitud a uno de tus usuarios finales
    model="meetkai:functionary-es-mini",
    input="¿Cuál es la versión estable más reciente de Python? Cita tus fuentes.",
    tools=[{"type": "web_search", "search_context_size": "low", "user_location": {"type": "approximate", "country": "US"}}],
)
print(response)
```

```csharp C# SDK theme={null}
using System.Collections.Generic;
using MeetKai.MKA1;
using MeetKai.MKA1.Types.Components;

var sdk = new SDK(bearerAuth: "Bearer <mka1-api-key>");

var response = await sdk.Llm.Responses.CreateAsync(
    new ResponsesCreateRequest()
    {
        Model = "meetkai:functionary-es-mini",
        Input = ResponsesCreateRequestInput.CreateStr("¿Cuál es la versión estable más reciente de Python? Cita tus fuentes."),
        Tools = new List<ResponsesCreateRequestTool>
        {
            ResponsesCreateRequestTool.CreateWebSearchToolDefinition(new WebSearchToolDefinition()
            {
                Type = WebSearchToolDefinitionType.WebSearch,
                SearchContextSize = WebSearchToolDefinitionSearchContextSize.Low,
                UserLocation = new UserLocation() { Country = "US" },
            }),
        },
    },
    xOnBehalfOf: "<end-user-id>" // opcional — atribuye la solicitud a uno de tus usuarios finales
);
System.Console.WriteLine(response);
```

```bash CLI theme={null}
mka1 llm responses create \
  -H 'X-On-Behalf-Of: <end-user-id>' \
  --model meetkai:functionary-es-mini \
  --input '"¿Cuál es la versión estable más reciente de Python? Cita tus fuentes."' \
  --tools '[{"type": "web_search", "search_context_size": "low", "user_location": {"country": "US"}}]'
```

```bash Bash theme={null}
curl https://apigw.mka1.com/api/v1/llm/responses \
  --request POST \
  --header 'Authorization: Bearer <mka1-api-key>' \
  --header 'X-On-Behalf-Of: <end-user-id>' \
  --header 'Content-Type: application/json' \
  --data '{
  "model": "meetkai:functionary-es-mini",
  "input": "¿Cuál es la versión estable más reciente de Python? Cita tus fuentes.",
  "tools": [
    {
      "type": "web_search",
      "search_context_size": "low",
      "user_location": { "country": "US" }
    }
  ]
}'
```

### Opciones de la herramienta

| Campo | Efecto |
| - | - |
| `search_context_size` | Cantidad de resultados que pide cada búsqueda: `low` pide 5, `medium` pide 10 y `high` pide 20. En `web_search`, el valor predeterminado es `medium`. En `web_search_preview`, si lo omites, se piden 20 resultados. |
| `user_location` | Localiza los resultados. La API usa `city`, `region` y `country`. No envía `timezone` al proveedor. |
| `filters.allowed_domains` | Restringe los resultados de búsqueda, la lectura de páginas y las citas a los dominios indicados. Consulta [Restringir la búsqueda web a dominios específicos](#restringir-la-búsqueda-web-a-dominios-específicos). Disponible solo en `web_search` y `web_search_2025_08_26`. |

Para ver el esquema completo, consulta [Crear una respuesta](https://docs.mka1.com/es/api-reference/responses/create-an-agent-powered-response-with-tool-support).

## Qué recibe el proveedor

Todo el tráfico de búsqueda web va de la plataforma MKA1 al proveedor por HTTPS. Los dispositivos de tus usuarios finales no se comunican con el proveedor, así que el proveedor no ve sus direcciones IP.

### Búsquedas

Cada llamada a `web_search` envía una solicitud a `google.serper.dev` con estos campos:

| Campo | Valor |
| - | - |
| `q` | La consulta de búsqueda que escribió el modelo. Si defines `filters.allowed_domains`, la API agrega operadores `site:` para tantos dominios indicados como quepan dentro de los límites de consulta de Google; los resultados se filtran por dominio de todos modos. |
| `num` | La cantidad de resultados, definida por `search_context_size`. |
| `gl` | Un código de país de dos letras. El modelo puede definirlo. Si no lo hace, la API lo obtiene de `user_location.country` y, si no puede, usa `us`. |
| `hl` | Un código de idioma. El modelo puede definirlo. El valor predeterminado es `en`. |
| `location` | Una cadena de ubicación. El modelo puede definirla. Si no lo hace, la API une `user_location.city`, `region` y `country` con comas. El campo se omite cuando ninguna de las dos fuentes da un valor. |
| `safe` | Siempre `active`, lo que activa SafeSearch. |

El modelo escribe la consulta a partir de la conversación. Por eso, una consulta puede incluir texto de la entrada o de las instrucciones, como un nombre, un producto o un lugar que mencionó el usuario.

### Lectura de páginas

Cada llamada a `scrape` o `web_find` envía a `scrape.serper.dev` la URL que eligió el modelo. Serper obtiene la página y devuelve su texto. En `web_find`, la plataforma MKA1 compara el patrón con ese texto por su cuenta; el patrón no se envía al proveedor.

### Búsquedas de país

Si el modelo indica un país que no es un código de dos letras ni un nombre de país que la API reconozca, la API envía ese texto a la API pública de ubicaciones de SerpApi (`serpapi.com/locations.json`) para obtener su código de país. Esta solicitud contiene solo el texto del país y un límite de 1 resultado. Si la búsqueda falla o no encuentra nada, la búsqueda web usa `us`.

### Qué no se envía

La plataforma no reenvía a estos proveedores tus encabezados de autenticación de MKA1 ni los encabezados de identidad, como `X-On-Behalf-Of`. No agrega identificadores de organización, equipo o usuario del contexto de la solicitud a los datos que envía al proveedor. Se autentica ante Serper con la clave de Serper del propio clúster, y las búsquedas de país no llevan clave.

La plataforma no envía la conversación, las instrucciones ni los archivos como datos separados. Sin embargo, el modelo puede copiar su contenido en una consulta, una URL o un valor de ubicación, idioma o país. Esos valores se envían sin ocultar las credenciales ni los identificadores que contengan. Por ejemplo, una URL de página puede contener un token de acceso o un ID de usuario en sus parámetros de consulta, incluso si su dominio está permitido. Las URL que llevan credenciales antes del host (`user:password@`) se rechazan cuando hay una lista de dominios definida.

Aparte del proveedor, la plataforma MKA1 registra en el clúster cada llamada a una herramienta de búsqueda web. Los argumentos de la llamada (consulta, URL, patrón, ubicación, idioma y país) y su salida (resultados de búsqueda, texto de la página o líneas coincidentes) se escriben en el registro de auditoría de la plataforma y, de forma abreviada, en las trazas de solicitud. Los elementos `web_search_call` de la salida de la respuesta llevan la consulta, la URL y el patrón, y se guardan con la respuesta cuando esta se almacena. Serper ve la dirección IP saliente del clúster, no la de tus usuarios finales.

## Caché

Los resultados de búsqueda no se guardan en caché. Cada llamada a `web_search` envía una nueva solicitud al proveedor.

El texto de las páginas que leen `scrape` y `web_find` se guarda en la caché de la plataforma durante 5 minutos. La clave de caché es solo la URL, así que la caché la comparten todos los usuarios del clúster. Si se vuelve a leer la misma URL dentro de ese plazo, no se envía una nueva solicitud al proveedor. Las comprobaciones de la [lista de dominios](#restringir-la-búsqueda-web-a-dominios-específicos) y de la [política de red](#políticas-de-red-salientes) se siguen ejecutando antes de leer la caché.

## Uso y facturación

Cada llamada a `web_search` cuenta como una búsqueda. Cada llamada a `scrape` o `web_find` que no se atiende desde la caché también cuenta como una búsqueda. Las búsquedas se cobran con la entrada de precio `serper`, y su costo cuenta para los [presupuestos](https://docs.mka1.com/docs/budgets.md). Las búsquedas de país no se facturan.

## Restringir la búsqueda web a dominios específicos

Define `filters.allowed_domains` para limitar la búsqueda web a una lista de dominios. El campo `filters` está disponible en `web_search` y `web_search_2025_08_26`. Una solicitud que define `filters` en un tipo `web_search_preview` falla con HTTP 400.

Escribe cada entrada como un nombre de host, como `python.org`, y omite el esquema. Si una entrada empieza con `http://` o `https://` o termina en `/`, la API quita esa parte. Cada entrada también cubre sus subdominios: `python.org` cubre `docs.python.org`, pero no `notpython.org`. La comparación no distingue mayúsculas de minúsculas.

Una lista puede tener hasta 100 entradas. Una solicitud con una entrada que contiene una ruta, una cadena de consulta, un puerto, credenciales, una dirección IP o un comodín, o cuyo nombre de host no tiene punto (como `localhost`), falla con HTTP 400. Un objeto `filters` con una clave desconocida, como `allowedDomains`, también falla con HTTP 400. Una lista vacía u omitida deja la búsqueda web sin restricciones.

Con una lista de dominios definida:

* La API quita los resultados de búsqueda que no están en los dominios indicados, así que el modelo puede recibir menos resultados de los que pide `search_context_size`.
* `scrape` y `web_find` rechazan las URL que están fuera de los dominios indicados antes de enviar nada al proveedor, y el modelo recibe un error para esa llamada.
* La API quita de la salida las citas de URL (anotaciones `url_citation`) que apuntan fuera de los dominios indicados.
* Cada búsqueda ejecuta como máximo 4 búsquedas en el proveedor, y cada una cuenta como una búsqueda. Una lista larga se reparte entre esas búsquedas en el orden en que la indicas. Si la lista no cabe, la API ejecuta 3 búsquedas restringidas a los primeros dominios más una búsqueda sin restricción filtrada con toda la lista, así que los dominios posteriores aún pueden aparecer, pero con menos fiabilidad. Pon primero los dominios más importantes.

```ts TypeScript SDK theme={null}
const response = await sdk.llm.responses.create({
  xOnBehalfOf: '<end-user-id>',
  responsesCreateRequest: {
    model: 'meetkai:functionary-es-mini',
    input: 'Resume las novedades de la versión más reciente de Python.',
    tools: [{ type: 'web_search', filters: { allowedDomains: ['python.org'] } }],
  },
});
console.log(response);
```

```ts OpenAI SDK theme={null}
const response = await openai.responses.create({
  model: 'meetkai:functionary-es-mini',
  input: 'Resume las novedades de la versión más reciente de Python.',
  tools: [{ type: 'web_search', filters: { allowed_domains: ['python.org'] } }],
});
console.log(response);
```

```python Python SDK theme={null}
response = sdk.llm.responses.create(
    x_on_behalf_of="<end-user-id>",
    model="meetkai:functionary-es-mini",
    input="Resume las novedades de la versión más reciente de Python.",
    tools=[{"type": "web_search", "filters": {"allowed_domains": ["python.org"]}}],
)
print(response)
```

```csharp C# SDK theme={null}
var response = await sdk.Llm.Responses.CreateAsync(
    new ResponsesCreateRequest()
    {
        Model = "meetkai:functionary-es-mini",
        Input = ResponsesCreateRequestInput.CreateStr("Resume las novedades de la versión más reciente de Python."),
        Tools = new List<ResponsesCreateRequestTool>
        {
            ResponsesCreateRequestTool.CreateWebSearchToolDefinition(new WebSearchToolDefinition()
            {
                Type = WebSearchToolDefinitionType.WebSearch,
                Filters = new WebSearchFilters() { AllowedDomains = new List<string> { "python.org" } },
            }),
        },
    },
    xOnBehalfOf: "<end-user-id>"
);
System.Console.WriteLine(response);
```

```bash CLI theme={null}
mka1 llm responses create \
  --model meetkai:functionary-es-mini \
  --input '"Resume las novedades de la versión más reciente de Python."' \
  --tools '[{"type": "web_search", "filters": {"allowed_domains": ["python.org"]}}]'
```

```bash Bash theme={null}
curl https://apigw.mka1.com/api/v1/llm/responses \
  --request POST \
  --header 'Authorization: Bearer <mka1-api-key>' \
  --header 'X-On-Behalf-Of: <end-user-id>' \
  --header 'Content-Type: application/json' \
  --data '{
  "model": "meetkai:functionary-es-mini",
  "input": "Resume las novedades de la versión más reciente de Python.",
  "tools": [
    {
      "type": "web_search",
      "filters": { "allowed_domains": ["python.org"] }
    }
  ]
}'
```

Una lista de dominios no impide que se envíen datos al proveedor: las búsquedas y las lecturas de páginas permitidas se siguen enviando a Serper como se describe en [Qué recibe el proveedor](#qué-recibe-el-proveedor).

La lista de dominios se comprueba con la URL que solicita el modelo. La plataforma no ve las redirecciones que ocurren mientras el proveedor obtiene la página, así que si una página de un dominio permitido redirige a otro dominio, el contenido devuelto puede provenir de ese otro dominio.

La lista de dominios se aplica solo a `web_search`, `scrape` y `web_find`. Otras herramientas de la misma solicitud, como `shell`, `code_interpreter`, `mcp` y las herramientas OpenAPI, pueden seguir conectándose a otros hosts. Usa las [políticas de red salientes](#políticas-de-red-salientes) para restringir a dónde puede conectarse una solicitud.

## Políticas de red salientes

Si el clúster aplica políticas de red salientes y tu organización o equipo tiene una política que restringe los destinos, el tráfico de búsqueda web debe cumplir esa política:

* Permite `google.serper.dev` para las búsquedas y `scrape.serper.dev` para la lectura de páginas. Permite `serpapi.com` si el modelo puede necesitar búsquedas de país.
* Cada URL que el modelo pida leer con `scrape` o `web_find` también debe estar permitida. Una URL fuera de la política falla y el modelo recibe un error para esa llamada. Con una política en vigor, también se rechazan las URL con un puerto distinto de 80 o 443 o cuyo host es una dirección IP.
* Si la política no se puede verificar, se rechazan las solicitudes salientes.

Para gestionar las políticas, usa [Establecer la política de red del tenant](https://docs.mka1.com/es/api-reference/sessions/set-tenant-network-policy).

## Disponibilidad en un clúster

La búsqueda web solo está disponible cuando el operador del clúster ha configurado una clave de API de Serper (`SERPER_API_KEY`). En un clúster sin ella, una solicitud de Respuestas que incluya cualquier herramienta de búsqueda web falla con HTTP 400 y el código de error `feature_unavailable`. El campo `service` del error es `web_search` y su campo `param` indica la herramienta, por ejemplo `tools[0].type`. Las solicitudes sin herramienta de búsqueda web no se ven afectadas.

En un [lote](https://docs.mka1.com/es/docs/batch-processing.md), el elemento afectado falla con `code: feature_unavailable`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.