---
title: Ask AI
description: >-
  Um assistente na própria página fundamentado na sua documentação — perguntas sugeridas, instruções personalizadas, dimensionamento da recuperação, backends do Vercel AI Gateway a qualquer endpoint compatível com OpenAI, e a saída de servidor que ele exige.
---

Adicione um assistente que responde às perguntas dos leitores num painel de chat na própria página, apoiado por um endpoint de servidor com streaming e pelo [AI SDK](https://ai-sdk.dev). É opcional, e a documentação estática continua totalmente estática até você ativá-lo:

```ts blume.config.ts lineNumbers
ai: {
  ask: {
    enabled: true,
    provider: "gateway", // default
    model: "openai/gpt-5.5",
  },
}
```

## Perguntas sugeridas [#suggested-questions]

Preencha o estado vazio com alguns prompts iniciais. Cada um aparece como uma sugestão clicável — clique em uma para enviá-la — com um [ícone Lucide](/docs/content/components#icon) opcional ao lado do rótulo:

```ts blume.config.ts lineNumbers
ai: {
  ask: {
    enabled: true,
    suggestions: [
      { label: "What is Blume?", icon: "rocket" },
      { label: "How do I write a docs page?", icon: "file-text" },
      { label: "How do I configure the theme?", icon: "settings" },
    ],
  },
}
```

`label` é a pergunta que será feita; `icon` é opcional. Deixe `suggestions` sem definir (ou vazio) e o painel abre com um campo de entrada simples.

## Instruções personalizadas [#custom-instructions]

Adicione o seu próprio texto de system prompt com `instructions` — identidade, idioma, tom ou qualquer outra coisa que o assistente deva ter em mente:

```ts blume.config.ts lineNumbers
ai: {
  ask: {
    enabled: true,
    instructions:
      "You are Bloomy, the Acme docs assistant. Answer in the language the question was asked in, and keep answers under three paragraphs.",
  },
}
```

Seu texto é **acrescentado às** instruções internas em vez de substituí-las: a parte interna carrega o contrato de [fundamentação](#grounding) — responder apenas a partir das páginas recuperadas, citá-las como links Markdown — do qual as citações do painel de chat dependem, então ela permanece intacta independentemente do que você adicionar.

## Fundamentação [#grounding]

O Ask AI é **fundamentado na sua documentação**. Para cada pergunta ele recupera as páginas mais relevantes — usando o mesmo índice léxico do [Orama](/docs/configuration/search) que alimenta a busca na página — e as injeta no system prompt do modelo, de forma que as respostas venham do seu conteúdo e não do conhecimento próprio do modelo. O assistente é instruído a responder apenas a partir das páginas recuperadas, a dizer quando algo não está coberto e a citar as páginas de onde tirou a informação.

A página em que o leitor está no momento é adicionada primeiro ao contexto e usada para limitar a recuperação ao idioma daquela página, para que as respostas continuem relevantes ao ponto em que ele está na documentação. A recuperação roda no momento da requisição a partir de um snapshot embutido no build, então funciona independentemente do seu provedor de [busca](/docs/configuration/search) — até mesmo quando a busca está definida como `none` — e não precisa de configuração.

A fundamentação está ativa para todos os backends, exceto o **[Inkeep](#backends)**, que roda a própria recuperação sobre o conteúdo que você indexou no painel dele.

## Tamanho da recuperação [#retrieval-size]

Quanta documentação uma pergunta carrega é a maior alavanca sobre quanto tempo o leitor espera pela primeira palavra: o modelo lê cada caractere injetado antes de emitir um token. Em um modelo de fronteira hospedado isso é imperceptível, mas em um backend auto-hospedado é o fator dominante. `retrieval` dimensiona isso:

```ts blume.config.ts lineNumbers
ai: {
  ask: {
    enabled: true,
    retrieval: {
      maxResults: 3, // fewer pages retrieved per question
      excerptChars: 1200, // shorter excerpt from each one
      contextBudget: 3000, // smaller total injection
    },
  },
}
```

| Opção | Padrão | Descrição |
| --- | --- | --- |
| `maxResults` | `6` | Documentos recuperados por pergunta. |
| `excerptChars` | `2000` | Caracteres mantidos de cada página recuperada. |
| `contextBudget` | `10000` | Total de caracteres injetados, somando todos os trechos. |

Os três não são intercambiáveis. `contextBudget` limita toda a injeção, `excerptChars` decide quão fundo o trecho de uma única página longa vai — aumente quando uma página contém a resposta inteira e o trecho a corta — e `maxResults` limita quantas páginas a recuperação adiciona. A página que o leitor está vendo é injetada além das recuperadas, então uma resposta pode citar até uma página a mais que `maxResults`.

Os padrões servem bem para um modelo hospedado. Reduza-os quando você estiver servindo a partir do seu próprio hardware e o tempo até o primeiro token importar mais que a abrangência; as respostas continuam fundamentadas de qualquer forma, e o assistente é instruído a dizer quando algo não está coberto em vez de preencher a lacuna.

## Endpoint externo [#external-endpoint]

Já tem um backend de API para IA? Aponte o painel para ele e mantenha o build da documentação estático:

```ts blume.config.ts lineNumbers
ai: {
  ask: {
    enabled: true,
    endpoint: "https://api.example.com/v1/docs/ask",
  },
}
```

O Blume envia o mesmo corpo `POST` que a rota interna:

```json
{
  "messages": [{ "role": "user", "content": "How do I deploy?" }],
  "page": { "path": "/deployment" }
}
```

Retorne uma resposta bem-sucedida cujo corpo seja um fluxo de texto UTF-8 puro. Se o endpoint estiver em outra origem, permita a origem da documentação com CORS: aceite `OPTIONS` e `POST`, permita o cabeçalho de requisição `content-type` e retorne os cabeçalhos CORS tanto no preflight quanto na resposta com streaming. Com `endpoint` definido, o Blume gera a interface de chat mas nenhuma rota de servidor, snapshot de fundamentação, dependência de provedor ou aviso de segredo de provedor; seu backend fica responsável pela recuperação, autenticação, limitação de taxa, acesso ao modelo e citações.

## Saída de servidor obrigatória [#server-output-required]

O backend interno do Ask AI no Blume é uma rota de servidor (`POST /api/ask`), então ele não pode rodar num build estático. Mude para saída de servidor e escolha um adaptador:

```ts blume.config.ts lineNumbers
deployment: {
  output: "server",
  adapter: "vercel",
}
```

Um build estático com o Ask AI ativado e sem um `endpoint` externo falha imediatamente com uma mensagem dizendo para você definir `deployment.output` como `server`. Veja [Implantação](/docs/deployment) para os adaptadores.

## Backends

Por padrão o Ask AI passa pelo **Vercel AI Gateway**: `model` é uma string `provider/model`, então você troca de modelo alterando esse valor (`openai/gpt-5.5`, `anthropic/claude-sonnet-4-5` e assim por diante) sem nenhum SDK de provedor para instalar. O gateway lê `AI_GATEWAY_API_KEY` do seu ambiente e é configurado automaticamente quando você faz o deploy na Vercel.

Defina `provider` para apontar o Ask AI para outro lugar. Cada backend lê sua chave de API a partir de uma variável de ambiente e faz streaming por meio de um SDK de provedor que você instala no seu projeto — apenas o que você usar:

| `provider` | `model` | Variável de ambiente da chave de API | SDK a instalar |
| --- | --- | --- | --- |
| `gateway` (padrão) | uma string `provider/model` via o AI Gateway | `AI_GATEWAY_API_KEY` | nenhum — já vem com o Blume |
| `openrouter` | qualquer modelo do [OpenRouter](https://openrouter.ai) | `OPENROUTER_API_KEY` | `@openrouter/ai-sdk-provider` |
| `llmgateway` | qualquer modelo do [LLMGateway](https://llmgateway.io) | `LLMGATEWAY_API_KEY` | `@ai-sdk/openai-compatible` |
| `inkeep` | um modelo de QA do [Inkeep](https://inkeep.com) | `INKEEP_API_KEY` | `@ai-sdk/openai-compatible` |
| `openai-compatible` | o que o seu endpoint servir | definida com `apiKeyEnv` | `@ai-sdk/openai-compatible` |

Os SDKs são dependências de par opcionais, então adicione ao seu projeto aquele de que o seu backend precisa (por exemplo, `npm install @openrouter/ai-sdk-provider`). Se estiver faltando, o build avisa com o nome exato do pacote antes que o Vite falhe ao resolver o import.

Por exemplo, para usar o OpenRouter:

```ts blume.config.ts lineNumbers
ai: {
  ask: {
    enabled: true,
    provider: "openrouter",
    model: "anthropic/claude-sonnet-4-5",
  },
}
```

Qualquer endpoint compatível com OpenAI funciona através de `openai-compatible` — informe a `baseUrl` e a variável de ambiente que contém a chave dele:

```ts blume.config.ts lineNumbers
ai: {
  ask: {
    enabled: true,
    provider: "openai-compatible",
    baseUrl: "https://my-gateway.example.com/v1",
    apiKeyEnv: "MY_GATEWAY_API_KEY",
    model: "gpt-4o",
  },
}
```

Defina `apiKeyEnv` (e, para os provedores nomeados, `baseUrl`) em qualquer backend para apontar para uma variável de ambiente ou proxy diferente.

:::note
O **Inkeep** responde a partir do conteúdo que você indexou no painel do Inkeep — ele roda a própria recuperação — então o Blume o deixa sem fundamentação. Todos os outros backends são [fundamentados](#grounding) nas páginas deste site.
:::

As chaves são lidas com `process.env`, o que cobre os adaptadores Node, Vercel e Netlify. No Cloudflare, exponha a chave através do [runtime binding](https://docs.astro.build/en/guides/integrations-guide/cloudflare/#environment-variables-and-secrets) da plataforma. Ativar o Ask AI também liga o React para a ilha na página — veja [Personalização](/docs/configuration/customization#interactive-islands).

## Limitação de taxa [#rate-limiting]

O endpoint `POST /api/ask` é **não autenticado** — ele precisa ser, para que o assistente na página possa chamá-lo. O Blume valida cada requisição — rejeitando corpos malformados, limitando a 1–40 mensagens e aceitando apenas os papéis `user`/`assistant` para que quem chama não possa injetar o próprio system prompt e reaproveitar a rota como um proxy genérico de LLM — para limitar quanto uma única chamada pode gastar com o seu modelo, mas isso não impede alguém de chamar o endpoint repetidamente. Se o abuso de custos for uma preocupação, coloque a rota atrás de um limitador de taxa — a limitação de taxa na borda do seu host (a da Vercel, por exemplo), um middleware, ou os limites de gasto por chave do seu provedor de modelos.

O endpoint é anunciado no [manifesto de legibilidade para agentes](/docs/discoverability/agent-discovery#agent-readability) junto com o restante da superfície legível por máquina do site.
