> ## 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.

# Pesquisa na web

> Permita que um modelo pesquise na web e leia páginas, e veja qual provedor atende essas solicitações e quais dados ele recebe.

Adicione uma ferramenta de pesquisa na web a uma solicitação de [Responses](https://docs.mka1.com/docs/responses.md) quando o modelo precisar de informações atuais da web pública. A API MKA1 envia as pesquisas e as solicitações de páginas do modelo ao [Serper](https://serper.dev), uma API de pesquisa de terceiros que retorna resultados de pesquisa do Google.

Esta página explica como habilitar a pesquisa na web, o que cada solicitação de saída contém e como limitar a pesquisa na web a domínios específicos.

## Habilitar a pesquisa na web

Adicione a `tools` uma ferramenta com tipo `web_search`. A API também aceita `web_search_2025_08_26`, `web_search_preview` e `web_search_preview_2025_03_11`, que dão ao modelo as mesmas ferramentas.

Uma ferramenta de pesquisa na web dá ao modelo três ferramentas. O modelo decide quando chamar cada uma:

| Ferramenta | O que faz | Como a chamada aparece na saída da resposta |
| - | - | - |
| `web_search` | Executa uma consulta de pesquisa e retorna títulos, links e trechos | Item `web_search_call` com `action.type` igual a `search` e a consulta |
| `scrape` | Lê o texto de uma página em uma URL | Item `web_search_call` com `action.type` igual a `open_page` e a URL |
| `web_find` | Encontra as linhas de uma página que correspondem a uma palavra ou um padrão | Item `web_search_call` com `action.type` igual a `find`, a URL e o padrão |

Verifique os itens `web_search_call` na saída da resposta para ver cada consulta e cada URL que o modelo solicitou.

Esta solicitação faz uma pergunta que precisa de informações atuais:

```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 — atribua a solicitação a um dos seus usuários finais
  responsesCreateRequest: {
    model: 'meetkai:functionary-pt',
    input: 'Qual é a versão estável mais recente do Python? Cite suas fontes.',
    tools: [{ type: 'web_search', searchContextSize: 'low', userLocation: { country: 'BR' } }],
  },
});
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-pt',
  input: 'Qual é a versão estável mais recente do Python? Cite suas fontes.',
  tools: [{ type: 'web_search', search_context_size: 'low', user_location: { type: 'approximate', country: 'BR' } }],
});
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 — atribua a solicitação a um dos seus usuários finais
    model="meetkai:functionary-pt",
    input="Qual é a versão estável mais recente do Python? Cite suas fontes.",
    tools=[{"type": "web_search", "search_context_size": "low", "user_location": {"type": "approximate", "country": "BR"}}],
)
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-pt",
        Input = ResponsesCreateRequestInput.CreateStr("Qual é a versão estável mais recente do Python? Cite suas fontes."),
        Tools = new List<ResponsesCreateRequestTool>
        {
            ResponsesCreateRequestTool.CreateWebSearchToolDefinition(new WebSearchToolDefinition()
            {
                Type = WebSearchToolDefinitionType.WebSearch,
                SearchContextSize = WebSearchToolDefinitionSearchContextSize.Low,
                UserLocation = new UserLocation() { Country = "BR" },
            }),
        },
    },
    xOnBehalfOf: "<end-user-id>" // opcional — atribua a solicitação a um dos seus usuários finais
);
System.Console.WriteLine(response);
```

```bash CLI theme={null}
mka1 llm responses create \
  -H 'X-On-Behalf-Of: <end-user-id>' \
  --model meetkai:functionary-pt \
  --input '"Qual é a versão estável mais recente do Python? Cite suas fontes."' \
  --tools '[{"type": "web_search", "search_context_size": "low", "user_location": {"country": "BR"}}]'
```

```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-pt",
  "input": "Qual é a versão estável mais recente do Python? Cite suas fontes.",
  "tools": [
    {
      "type": "web_search",
      "search_context_size": "low",
      "user_location": { "country": "BR" }
    }
  ]
}'
```

### Opções da ferramenta

| Campo | Efeito |
| - | - |
| `search_context_size` | Quantidade de resultados que cada pesquisa solicita: `low` solicita 5, `medium` solicita 10 e `high` solicita 20. Em `web_search`, o padrão é `medium`. Em `web_search_preview`, se você omitir o campo, são solicitados 20 resultados. |
| `user_location` | Localiza os resultados. A API usa `city`, `region` e `country`. Ela não envia `timezone` ao provedor. |
| `filters.allowed_domains` | Restringe os resultados de pesquisa, a leitura de páginas e as citações aos domínios listados. Veja [Restringir a pesquisa na web a domínios específicos](#restringir-a-pesquisa-na-web-a-domínios-específicos). Disponível apenas em `web_search` e `web_search_2025_08_26`. |

Para ver o esquema completo, consulte [Criar uma resposta](https://docs.mka1.com/pt/api-reference/responses/create-an-agent-powered-response-with-tool-support).

## O que o provedor recebe

Todo o tráfego de pesquisa na web vai da plataforma MKA1 ao provedor por HTTPS. Os dispositivos dos seus usuários finais não se comunicam com o provedor, então o provedor não vê os endereços IP deles.

### Pesquisas

Cada chamada a `web_search` envia uma solicitação a `google.serper.dev` com estes campos:

| Campo | Valor |
| - | - |
| `q` | A consulta de pesquisa que o modelo escreveu. Com `filters.allowed_domains` definido, a API acrescenta operadores `site:` para quantos domínios listados couberem nos limites de consulta do Google; os resultados são filtrados por domínio de qualquer forma. |
| `num` | A quantidade de resultados, definida por `search_context_size`. |
| `gl` | Um código de país de duas letras. O modelo pode defini-lo. Caso contrário, a API o obtém de `user_location.country` e, se não conseguir, usa `us`. |
| `hl` | Um código de idioma. O modelo pode defini-lo. O padrão é `en`. |
| `location` | Uma string de localização. O modelo pode defini-la. Caso contrário, a API junta `user_location.city`, `region` e `country` com vírgulas. O campo é omitido quando nenhuma das duas fontes fornece um valor. |
| `safe` | Sempre `active`, o que ativa o SafeSearch. |

O modelo escreve a consulta a partir da conversa. Por isso, uma consulta pode incluir texto da entrada ou das instruções, como um nome, um produto ou um lugar que o usuário mencionou.

### Leitura de páginas

Cada chamada a `scrape` ou `web_find` envia a `scrape.serper.dev` a URL que o modelo escolheu. O Serper busca a página e retorna o texto dela. Em `web_find`, a própria plataforma MKA1 compara o padrão com esse texto; o padrão não é enviado ao provedor.

### Consultas de país

Se o modelo informar um país que não seja um código de duas letras nem um nome de país que a API reconheça, a API envia esse texto à API pública de localizações do SerpApi (`serpapi.com/locations.json`) para obter o código do país. Essa solicitação contém apenas o texto do país e um limite de 1 resultado. Se a consulta falhar ou não encontrar nada, a pesquisa usa `us`.

### O que não é enviado

A plataforma não encaminha a esses provedores seus cabeçalhos de autenticação da MKA1 nem os cabeçalhos de identidade, como `X-On-Behalf-Of`. Ela não adiciona identificadores de organização, equipe ou usuário do contexto da solicitação aos dados enviados ao provedor. Ela se autentica no Serper com a chave do Serper do próprio cluster, e as consultas de país não levam chave.

A plataforma não envia a conversa, as instruções ou os arquivos como dados separados. Porém, o modelo pode copiar o conteúdo deles para uma consulta, uma URL ou um valor de localização, idioma ou país. Esses valores são enviados sem ocultar as credenciais ou os identificadores que contenham. Por exemplo, uma URL de página pode conter um token de acesso ou um ID de usuário nos parâmetros de consulta, mesmo quando seu domínio é permitido. URLs que levam credenciais antes do host (`user:password@`) são recusadas quando há uma lista de domínios definida.

Separadamente do provedor, a plataforma MKA1 registra no cluster cada chamada a uma ferramenta de pesquisa na web. Os argumentos da chamada (consulta, URL, padrão, localização, idioma e país) e a saída dela (resultados de pesquisa, texto da página ou linhas correspondentes) são gravados no log de auditoria da plataforma e, de forma abreviada, nos rastreamentos de solicitação. Os itens `web_search_call` na saída da resposta carregam a consulta, a URL e o padrão, e são armazenados com a resposta quando ela é armazenada. O Serper vê o endereço IP de saída do cluster, não o dos seus usuários finais.

## Cache

Os resultados de pesquisa não são armazenados em cache. Cada chamada a `web_search` envia uma nova solicitação ao provedor.

O texto das páginas lidas por `scrape` e `web_find` fica no cache da plataforma por 5 minutos. A chave do cache é apenas a URL, então o cache é compartilhado por todos os usuários do cluster. Uma nova leitura da mesma URL dentro desse período não envia uma nova solicitação ao provedor. As verificações da [lista de domínios](#restringir-a-pesquisa-na-web-a-domínios-específicos) e da [política de rede](#políticas-de-rede-de-saída) continuam sendo executadas antes da leitura do cache.

## Uso e cobrança

Cada chamada a `web_search` conta como uma pesquisa. Cada chamada a `scrape` ou `web_find` que não é atendida pelo cache também conta como uma pesquisa. As pesquisas são precificadas pela entrada de preço `serper`, e o custo delas conta para os [orçamentos](https://docs.mka1.com/docs/budgets.md). As consultas de país não são cobradas.

## Restringir a pesquisa na web a domínios específicos

Defina `filters.allowed_domains` para limitar a pesquisa na web a uma lista de domínios. O campo `filters` está disponível em `web_search` e `web_search_2025_08_26`. Uma solicitação que define `filters` em um tipo `web_search_preview` falha com HTTP 400.

Escreva cada entrada como um nome de host, como `python.org`, e omita o esquema. Se uma entrada começar com `http://` ou `https://` ou terminar com `/`, a API remove essa parte. Cada entrada também cobre os subdomínios dela: `python.org` cobre `docs.python.org`, mas não `notpython.org`. A comparação não diferencia maiúsculas de minúsculas.

Uma lista pode ter até 100 entradas. Uma solicitação com uma entrada que contenha um caminho, uma string de consulta, uma porta, credenciais, um endereço IP ou um curinga, ou cujo nome de host não tenha ponto (como `localhost`), falha com HTTP 400. Um objeto `filters` com uma chave desconhecida, como `allowedDomains`, também falha com HTTP 400. Uma lista vazia ou omitida deixa a pesquisa na web sem restrições.

Com uma lista de domínios definida:

* A API remove os resultados de pesquisa que não estão nos domínios listados, então o modelo pode receber menos resultados do que `search_context_size` solicita.
* `scrape` e `web_find` recusam URLs fora dos domínios listados antes de enviar qualquer coisa ao provedor, e o modelo recebe um erro para essa chamada.
* A API remove da saída as citações de URL (anotações `url_citation`) que apontam para fora dos domínios listados.
* Cada pesquisa executa no máximo 4 pesquisas no provedor, e cada uma conta como uma pesquisa. Uma lista longa é dividida entre essas pesquisas na ordem em que você a informa. Se a lista não couber, a API executa 3 pesquisas restritas aos primeiros domínios mais uma pesquisa sem restrição filtrada com a lista inteira, então os domínios posteriores ainda podem aparecer, mas com menos confiabilidade. Coloque os domínios mais importantes primeiro.

```ts TypeScript SDK theme={null}
const response = await sdk.llm.responses.create({
  xOnBehalfOf: '<end-user-id>',
  responsesCreateRequest: {
    model: 'meetkai:functionary-pt',
    input: 'Resuma as novidades da versão mais recente do 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-pt',
  input: 'Resuma as novidades da versão mais recente do 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-pt",
    input="Resuma as novidades da versão mais recente do 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-pt",
        Input = ResponsesCreateRequestInput.CreateStr("Resuma as novidades da versão mais recente do 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-pt \
  --input '"Resuma as novidades da versão mais recente do 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-pt",
  "input": "Resuma as novidades da versão mais recente do Python.",
  "tools": [
    {
      "type": "web_search",
      "filters": { "allowed_domains": ["python.org"] }
    }
  ]
}'
```

Uma lista de domínios não impede que dados sejam enviados ao provedor: as pesquisas e as leituras de páginas permitidas continuam indo para o Serper, como descrito em [O que o provedor recebe](#o-que-o-provedor-recebe).

A lista de domínios é verificada em relação à URL que o modelo solicita. A plataforma não vê os redirecionamentos que ocorrem enquanto o provedor busca a página, então, se uma página de um domínio permitido redirecionar para outro domínio, o conteúdo retornado pode vir desse outro domínio.

A lista de domínios se aplica apenas a `web_search`, `scrape` e `web_find`. Outras ferramentas na mesma solicitação, como `shell`, `code_interpreter`, `mcp` e ferramentas OpenAPI, ainda podem acessar outros hosts. Use as [políticas de rede de saída](#políticas-de-rede-de-saída) para restringir onde uma solicitação pode se conectar.

## Políticas de rede de saída

Se o cluster aplica políticas de rede de saída e sua organização ou equipe tem uma política que restringe destinos, o tráfego de pesquisa na web precisa passar por essa política:

* Permita `google.serper.dev` para pesquisas e `scrape.serper.dev` para leitura de páginas. Permita `serpapi.com` se o modelo puder precisar de consultas de país.
* Cada URL que o modelo pedir para ler com `scrape` ou `web_find` também precisa ser permitida. Uma URL fora da política falha e o modelo recebe um erro para essa chamada. Com uma política em vigor, URLs com uma porta diferente de 80 ou 443, ou cujo host é um endereço IP, também são recusadas.
* Se a política não puder ser verificada, as solicitações de saída são recusadas.

Para gerenciar as políticas, use [Definir a política de rede do tenant](https://docs.mka1.com/pt/api-reference/sessions/set-tenant-network-policy).

## Disponibilidade em um cluster

A pesquisa na web só fica disponível quando o operador do cluster configura uma chave de API do Serper (`SERPER_API_KEY`). Em um cluster sem essa chave, uma solicitação de Responses que inclua qualquer ferramenta de pesquisa na web falha com HTTP 400 e o código de erro `feature_unavailable`. O campo `service` do erro é `web_search` e o campo `param` indica a ferramenta, por exemplo `tools[0].type`. Solicitações sem ferramenta de pesquisa na web não são afetadas.

Em um [lote](https://docs.mka1.com/pt/docs/batch-processing.md), o item afetado falha com `code: feature_unavailable`.


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