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

# Bots

> Descubra bots do WhatsApp, envie prompts e receba respostas em stream com o zapo. Funciona com qualquer bot do WhatsApp, incluindo Meta AI e terceiros.

O `client.bot` ([`WaBotCoordinator`](/pt-br/reference/client#bot)) funciona com **bots** do WhatsApp - qualquer conta no domínio `@bot`. O Meta AI é o mais comum, mas **não** é o único bot; `listBots()` retorna todos os bots disponíveis para a sua conta. O coordinator descobre bots, lê seus perfis, envia prompts e descriptografa os chunks em **stream** da resposta de um bot.

<h2 id="discovering-bots--getting-a-bot-jid">
  Descobrindo bots e obtendo um JID de bot
</h2>

Você não fixa JIDs de bot no código - você os descobre com `listBots()` e escolhe um:

```ts theme={null}
const bots = await client.bot.listBots()
// WaBotInfo[]: { jid, fbidJid, personaId, isDefault, section?, count? }

// Escolha o bot padrão (tipicamente o Meta AI), ou escolha outro por section/name
const bot = bots.find((b) => b.isDefault) ?? bots[0]
const botJid = bot.jid // ex.: '13135550002@bot'

// Inspecione o perfil de um bot (comandos, prompts, metadados do criador)
const profile = await client.bot.getBotProfile(botJid)
// WaBotProfileResult | null: name, description, category, prompts, commands, creator…
```

O `WaBotInfo.jid` é o valor que você passa abaixo como `to` (caminho direto) ou `options.botJid` (caminho de menção).

<h2 id="sending-a-prompt">
  Enviando um prompt
</h2>

`sendPrompt(to, content, options?)` invoca um bot. Há dois caminhos, dependendo de `to`:

<h3 id="direct-path--chat-with-the-bot">
  Caminho direto — conversar com o bot
</h3>

Quando `to` é um JID `@bot`, você está conversando com o bot diretamente. O zapo gera um novo `aiThreadId` (um id de conversa); reutilize-o em prompts posteriores para manter o contexto:

```ts theme={null}
// Inicie uma conversa
const first = await client.bot.sendPrompt(botJid, 'Explain WebSockets in one line')

// Continue-a — passe o mesmo aiThreadId para manter o contexto
await client.bot.sendPrompt(botJid, 'Now in two lines', {
  aiThreadId: myThreadId
})
```

<h3 id="mention-path--invoke-a-bot-inside-a-group">
  Caminho de menção — invocar um bot dentro de um grupo
</h3>

Quando `to` é um JID de **grupo/chat**, você precisa nomear o bot via `options.botJid`. O bot é invocado indiretamente através de uma menção:

```ts theme={null}
// botJid vem de listBots() — veja "Descobrindo bots" acima
await client.bot.sendPrompt(groupJid, '@MetaAI summarize the last messages', {
  botJid,
  extraMentionedJids: [] // menções extras opcionais junto com o bot
})
```

<Note>
  No caminho de menção, `aiThreadId` / `aiThreadType` são ignorados — os bots descartam a requisição se metadados de persona/thread forem anexados a uma menção.
</Note>

O `WaBotPromptOptions` estende [`WaSendMessageOptions`](/pt-br/guides/sending-messages#send-options-reference) e adiciona `botJid`, `personaId`, `capabilities`, `extraMentionedJids`, `aiThreadId` e `aiThreadType`.

<h2 id="receiving-the-streamed-reply">
  Recebendo a resposta em stream
</h2>

A resposta de um bot **não** chega como uma única `message`. Ela chega em stream como múltiplos chunks criptografados, expostos no evento `message_bot_chunk`. O zapo os descriptografa automaticamente a cada mensagem de entrada, então você só escuta:

```ts theme={null}
const buffers = new Map<string, string>()

client.on('message_bot_chunk', (event) => {
  // WaIncomingBotChunkEvent
  const text = event.message?.conversation ?? ''

  // Concatena os chunks na ordem de chegada usando editType
  const prev = buffers.get(event.targetMessageId) ?? ''
  buffers.set(event.targetMessageId, prev + text)

  if (event.editType === 'last' || event.editType === 'full') {
    console.log('full reply:', buffers.get(event.targetMessageId))
    buffers.delete(event.targetMessageId)
  }
})
```

Os campos do evento de chunk:

| Campo                               | Significado                                                       |
| ----------------------------------- | ----------------------------------------------------------------- |
| `key.participant` / `key.remoteJid` | O bot (sender = `key.participant ?? key.remoteJid`).              |
| `targetMessageId`                   | O id do prompt que esta resposta responde — sua chave de stream.  |
| `editType`                          | Posição do chunk: `first` → `inner` → `last`, ou um único `full`. |
| `message`                           | O conteúdo do chunk descriptografado (`Proto.IMessage`).          |
| `plaintext`                         | Bytes brutos descriptografados.                                   |

<Tip>
  Reconstrua a resposta completa concatenando os chunks de um dado `targetMessageId` na ordem de chegada até ver `last` (ou um único `full`).
</Tip>

<h2 id="manual-chunk-decryption">
  Descriptografia manual de chunk
</h2>

O zapo chama `tryDecryptChunk` para você a cada mensagem de entrada, então você raramente precisa dele. Se você gerencia os eventos de entrada por conta própria, pode invocá-lo explicitamente:

```ts theme={null}
client.on('message', async (event) => {
  await client.bot.tryDecryptChunk(event)
})
```

Ele silenciosamente não faz nada (no-op) quando o chunk não é endereçado a você ou o segredo do prompt pai não está disponível.
