---
title: "Como integrar inteligência artificial em um bot do Discord"
description: "Faça seu bot do Discord responder com IA via fetch na API de um provedor: contexto por canal, limite por usuário, corte de 2000 caracteres e chave segura."
url: "https://streethosting.com.br/guias/bots-discord/bot-discord-integrar-inteligencia-artificial"
category: "bots-discord"
slug: "bot-discord-integrar-inteligencia-artificial"
datePublished: "2026-11-13"
dateModified: "2026-11-13"
author: "Equipe StreetHosting"
difficulty: "intermediario"
language: "pt-BR"
keywords:
  - "bot discord inteligência artificial"
  - "bot discord chatgpt"
  - "integrar IA bot discord.js"
  - "bot discord responde com IA"
  - "api de chat compatível com openai"
---

# Bot do Discord com inteligência artificial: como integrar e controlar o custo

Um bot que responde quando é mencionado, lembra da conversa recente do canal e não estoura o orçamento. O código usa fetch puro contra uma API compatível com a de chat da OpenAI, com URL, chave e modelo em variáveis de ambiente.

> **Resposta rápida**
>
> O bot escuta mensagens que o mencionam, monta uma lista com o histórico curto do canal e faz um `POST` com `fetch` para a API de chat do provedor, usando URL, chave e modelo de variáveis de ambiente. A resposta é cortada em 2000 caracteres e enviada com `message.reply`. O modelo roda no provedor, não na hospedagem do bot, e o custo é controlado por limite de uso por usuário, histórico curto e teto de tokens.

## Como funciona e onde o modelo roda

Antes do código, vale entender o desenho, porque é aqui que nascem as dúvidas de custo e de hospedagem. Um bot com IA tem três peças separadas:

1. O Discord, que entrega a mensagem do usuário ao seu bot.
2. O seu bot, um processo Node.js que recebe a mensagem e monta o pedido.
3. O provedor de IA, que roda o modelo nos servidores dele e devolve o texto.

O modelo de linguagem **não roda dentro do plano de bot**. Quem faz o trabalho pesado é o provedor que você contratou, e é ele quem cobra, em geral por quantidade de texto processado. A sua hospedagem só executa um programa pequeno que conversa com o Discord de um lado e com a API do provedor do outro. Isso explica duas coisas: o plano de bot não precisa de muita RAM, e a conta de IA chega à parte, no provedor.

Como o formato de chat da OpenAI virou um padrão de fato, muitos provedores e programas aceitam o mesmo pedido: um POST em um endereço de chat completions, com a lista de mensagens e o nome do modelo. É por isso que o código deste guia não usa SDK nenhum e não fixa o nome de um modelo. O que muda de um provedor para outro vai para variáveis de ambiente.

## URL, chave e modelo em variáveis de ambiente

Crie um arquivo `.env` na pasta do bot com quatro valores. Os três da IA saem da documentação e do painel do provedor:

| Variável | O que guarda | Exemplo |
| --- | --- | --- |
| DISCORD_TOKEN | Token do bot, do portal de desenvolvedores do Discord | (seu token) |
| IA_API_URL | Endereço completo do endpoint de chat do provedor | https://api.seuprovedor.com/v1/chat/completions |
| IA_API_KEY | Chave de API gerada no painel do provedor | (sua chave) |
| IA_MODEL | Nome do modelo, exatamente como o provedor lista | (nome do modelo) |

O nome do modelo fica fora do código de propósito: provedores renomeiam e aposentam modelos com frequência, e trocar uma variável é bem mais fácil do que mexer no programa. No Node 20.6 ou mais novo, você pode carregar o arquivo sem biblioteca extra, iniciando o bot com `node --env-file=.env index.js`.

> **Atenção**
>
> **Nunca coloque a chave no código.** Quem acessa a chave gasta o seu dinheiro. Deixe o `.env` no `.gitignore`, não imprima a chave em logs e, se ela vazar em um repositório público ou em um print, revogue no painel do provedor e gere outra na hora. O guia de [token seguro e variáveis de ambiente](https://streethosting.com.br/guias/bots-discord/bot-discord-token-seguro-variaveis-ambiente) detalha esse cuidado.

## Chamar a API de chat com fetch

O pedido tem sempre o mesmo formato: cabeçalho de autorização com a chave e um corpo JSON com o modelo e a lista de mensagens. Cada mensagem tem um papel (`system`, `user` ou `assistant`) e um texto. A resposta traz o texto gerado em `choices[0].message.content`.

```
const { IA_API_URL, IA_API_KEY, IA_MODEL } = process.env;

const SISTEMA =
  'Você é o assistente deste servidor de Discord. ' +
  'Responda em português do Brasil, de forma curta e direta.';

async function perguntarIA(mensagens) {
  const resposta = await fetch(IA_API_URL, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: 'Bearer ' + IA_API_KEY,
    },
    body: JSON.stringify({
      model: IA_MODEL,
      messages: [{ role: 'system', content: SISTEMA }, ...mensagens],
      max_tokens: 500,
    }),
    signal: AbortSignal.timeout(30000),
  });

  if (!resposta.ok) {
    throw new Error('O provedor respondeu com status ' + resposta.status);
  }

  const dados = await resposta.json();
  return dados.choices?.[0]?.message?.content?.trim() ?? '';
}
```

Três detalhes importam. O `AbortSignal.timeout` derruba a chamada depois de 30 segundos, para o bot não ficar esperando para sempre um provedor lento. O `max_tokens` limita o tamanho da resposta, que é o principal controle de custo por pergunta. Alguns modelos mais novos pedem o campo `max_completion_tokens` no lugar dele, então confira a documentação do seu provedor. Em modelos de raciocínio, esse teto inclui o raciocínio interno, e um valor baixo pode devolver uma resposta vazia. E o `system` define o comportamento: é ali que você pede respostas curtas e em português.

## O bot completo

Agora a parte do Discord. O bot só responde quando é mencionado, guarda as últimas mensagens de cada canal em um `Map`, mostra "digitando..." enquanto espera a IA, aplica o limite por usuário e corta a resposta em 2000 caracteres. Cole este trecho no mesmo arquivo, logo abaixo da função `perguntarIA` da seção anterior, porque ele usa as variáveis declaradas lá.

```
const { Client, GatewayIntentBits, Events } = require('discord.js');

const { DISCORD_TOKEN } = process.env;
if (!DISCORD_TOKEN || !IA_API_URL || !IA_API_KEY || !IA_MODEL) {
  console.error('Faltam variáveis de ambiente (veja o arquivo .env).');
  process.exit(1);
}

const MAX_HISTORICO = 8;      // mensagens guardadas por canal
const LIMITE_POR_HORA = 10;   // perguntas por usuário a cada hora

const client = new Client({
  intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages],
});

const historicos = new Map(); // canalId -> [{ role, content }]
const usos = new Map();       // usuarioId -> [timestamps]

function podeUsar(usuarioId) {
  const agora = Date.now();
  const recentes = (usos.get(usuarioId) ?? []).filter((t) => agora - t < 3600000);
  if (recentes.length >= LIMITE_POR_HORA) {
    usos.set(usuarioId, recentes);
    return false;
  }
  recentes.push(agora);
  usos.set(usuarioId, recentes);
  return true;
}

function cortar(texto) {
  return texto.length <= 2000 ? texto : texto.slice(0, 1997) + '...';
}

client.on(Events.MessageCreate, async (message) => {
  if (message.author.bot || !message.guild) return;
  if (!message.mentions.has(client.user, { ignoreEveryone: true, ignoreRoles: true })) return;

  const pergunta = message.content
    .replace(new RegExp('<@!?' + client.user.id + '>', 'g'), '')
    .trim();

  if (!pergunta) {
    await message.reply('Me mande uma pergunta junto da menção.');
    return;
  }

  if (!podeUsar(message.author.id)) {
    await message.reply('Você chegou ao limite de perguntas por hora. Tente mais tarde.');
    return;
  }

  const nome = message.member?.displayName ?? message.author.username;
  const historico = historicos.get(message.channelId) ?? [];
  historico.push({ role: 'user', content: nome + ': ' + pergunta });

  const digitando = setInterval(() => message.channel.sendTyping().catch(() => {}), 8000);
  message.channel.sendTyping().catch(() => {});

  try {
    const texto = await perguntarIA(historico);
    if (!texto) throw new Error('Resposta vazia do provedor');

    historico.push({ role: 'assistant', content: texto });
    while (historico.length > MAX_HISTORICO) historico.shift();
    historicos.set(message.channelId, historico);

    await message.reply({
      content: cortar(texto),
      allowedMentions: { parse: [], repliedUser: false },
    });
  } catch (erro) {
    console.error('Erro ao consultar a IA:', erro.message);
    historico.pop(); // descarta a pergunta que falhou
    await message.reply('Não consegui responder agora. Tente de novo em instantes.');
  } finally {
    clearInterval(digitando);
  }
});

client.login(DISCORD_TOKEN);
```

Em relação às intents, este bot usa só `Guilds` e `GuildMessages`. O Discord entrega o texto das mensagens que mencionam o bot mesmo sem a intent privilegiada de conteúdo de mensagem, e como o bot só reage a menções, não precisa mais que isso. Se um dia quiser que ele leia mensagens sem menção, aí sim será preciso ativar essa intent no portal de desenvolvedores. Se tiver problemas com ela, veja o guia de [slash commands](https://streethosting.com.br/guias/bots-discord/criar-bot-discord-slash-commands), que é um caminho alternativo: em vez de menção, o usuário digita `/perguntar`.

## Controlar o custo

A cobrança da IA costuma ser por volume de texto, somando o que você envia (o prompt do sistema, o histórico e a pergunta) e o que o modelo devolve. Cada chamada reenvia o histórico inteiro, então uma conversa longa fica mais cara a cada mensagem. Estas são as travas que o código acima já aplica, e mais uma que fica fora dele:

- **Limite por usuário:** o `podeUsar` permite 10 perguntas por hora por pessoa. Ajuste ao seu servidor, e considere um limite menor para membros novos.
- **Histórico curto:** com `MAX_HISTORICO = 8` o bot lembra só das últimas mensagens da conversa. Menos texto enviado significa menos custo e respostas mais rápidas.
- **Teto de tokens:** o `max_tokens` impede que uma única resposta consuma uma fortuna. Com 500 a resposta cabe na maior parte dos casos dentro dos 2000 caracteres do Discord.
- **Limite de gasto no provedor:** a maioria dos painéis permite definir um orçamento mensal ou alertas. Configure, porque é a única trava que continua valendo se o bot tiver um defeito.

> **Dica**
>
> O limite por hora vive na memória e zera quando o bot reinicia. Para um servidor pequeno isso basta. Se a conta preocupa, guarde os contadores em um banco de dados e some também um teto diário para o servidor inteiro.

## Cuidados com o que a IA escreve

O texto vem de um modelo, então trate como entrada não confiável. Dois cuidados já estão no código. O `allowedMentions: { parse: [] }` impede que a resposta marque `@everyone`, cargos ou pessoas, mesmo que alguém consiga induzir o modelo a escrever isso. E o corte em 2000 caracteres evita que o Discord rejeite a mensagem com erro.

- **Não dê poderes ao modelo:** use a IA só para gerar texto. Não execute comandos, banimentos ou consultas ao banco de dados com base no que ela escreve.
- **Prompt do sistema claro:** diga o tom, o idioma e o que o bot não deve fazer. Nenhum prompt é à prova de manipulação, por isso as travas de custo e de permissão importam mais.
- **Avise que é uma IA:** deixe explícito na descrição do bot e no comando de ajuda que as respostas podem conter erros.
- **Dados dos membros:** o texto das perguntas vai para o provedor. Não envie informações privadas e leia a política de dados dele antes de abrir o recurso para a comunidade.

Para respostas mais bonitas, você pode enviar o texto da IA dentro de um embed. Veja como em [embeds e mensagens formatadas](https://streethosting.com.br/guias/bots-discord/bot-discord-embeds-mensagens-formatadas), lembrando que a descrição de um embed aceita até 4096 caracteres.

## Onde hospedar o bot

Como o modelo roda no provedor, o seu bot é leve: um processo Node.js esperando mensagens e fazendo uma chamada HTTP de vez em quando. Na [hospedagem de bots da StreetHosting](https://streethosting.com.br/bots) o plano Discord Essential, a R$ 9,99 por mês, com 1 GB de RAM, 0,5 vCPU, 2 GB de NVMe e até 2 bots, já dá conta de rodar esse código. O plano hospeda o bot, não a inteligência artificial: o custo do modelo continua sendo o do provedor de IA que você escolher.

Se você quer rodar um modelo próprio em vez de pagar por uso, isso é outro tipo de projeto e pede uma máquina bem maior. Como o formato de chat é o mesmo, o código deste guia funciona apontando `IA_API_URL` para o seu servidor, e o guia sobre [rodar Ollama em uma VPS sem GPU](https://streethosting.com.br/guias/vps/rodar-ollama-llm-vps-cpu) mostra o que esperar de velocidade nesse caminho.

## Perguntas frequentes

### O modelo de IA roda no plano de hospedagem do bot?

Não. O modelo roda nos servidores do provedor de IA que você contratou. O bot só recebe a mensagem no Discord, manda o texto para a API do provedor pela internet e devolve a resposta. Por isso o plano de bot pode ser pequeno: ele só executa o Node.js.

### Preciso de um SDK do provedor para isso?

Não. A maioria dos provedores oferece uma API de chat compatível com a da OpenAI, e basta um POST com fetch, que já vem no Node 18 ou mais novo. Trocar de provedor vira só mudar a URL, a chave e o nome do modelo nas variáveis de ambiente.

### Por que o bot precisa ser mencionado para responder?

Porque assim ele só gasta chamadas quando alguém pede. Além disso, o Discord entrega o conteúdo das mensagens que mencionam o bot mesmo sem a intent privilegiada de conteúdo de mensagem, o que simplifica a configuração.

### Como evito uma conta alta no provedor de IA?

Combine quatro travas: limite de uso por usuário no próprio bot, histórico curto, teto de tokens na resposta e um limite de gasto configurado no painel do provedor. Com as quatro, mesmo um servidor em que todo mundo abusa tem um gasto máximo conhecido.

### A resposta da IA passou de 2000 caracteres. E agora?

O Discord recusa mensagens com mais de 2000 caracteres. Corte o texto antes de enviar ou divida em partes. Pedir respostas curtas no prompt do sistema e limitar os tokens de saída reduz a chance de isso acontecer, e também o custo.

## Guias relacionados

- [Token do bot Discord seguro: .env, .gitignore e o que fazer se vazar](https://streethosting.com.br/guias/bots-discord/bot-discord-token-seguro-variaveis-ambiente.md)
- [Como criar bot Discord com slash commands](https://streethosting.com.br/guias/bots-discord/criar-bot-discord-slash-commands.md)
- [Embeds no Discord com discord.js: como montar mensagens formatadas](https://streethosting.com.br/guias/bots-discord/bot-discord-embeds-mensagens-formatadas.md)
- [Rodar Ollama na VPS: modelo de linguagem só com CPU](https://streethosting.com.br/guias/vps/rodar-ollama-llm-vps-cpu.md)
- [Hospedagem de bot Discord 24/7 no Brasil](https://streethosting.com.br/guias/bots-discord/hospedagem-bot-discord-24-7.md)

## Produtos citados

- https://streethosting.com.br/bots

## Dados estruturados

```json
[
  {
    "@context": "https://schema.org",
    "@type": [
      "Article",
      "TechArticle"
    ],
    "headline": "Bot do Discord com inteligência artificial: como integrar e controlar o custo",
    "name": "Como integrar inteligência artificial em um bot do Discord",
    "abstract": "Um bot que responde quando é mencionado, lembra da conversa recente do canal e não estoura o orçamento. O código usa fetch puro contra uma API compatível com a de chat da OpenAI, com URL, chave e modelo em variáveis de ambiente.",
    "description": "Faça seu bot do Discord responder com IA via fetch na API de um provedor: contexto por canal, limite por usuário, corte de 2000 caracteres e chave segura.",
    "datePublished": "2026-11-13",
    "dateModified": "2026-11-13",
    "author": {
      "@type": "Organization",
      "name": "Equipe StreetHosting"
    },
    "publisher": {
      "@type": "Organization",
      "name": "StreetHosting",
      "url": "https://streethosting.com.br"
    },
    "inLanguage": "pt-BR",
    "mainEntityOfPage": {
      "@type": "WebPage",
      "@id": "https://streethosting.com.br/guias/bots-discord/bot-discord-integrar-inteligencia-artificial"
    }
  },
  {
    "@context": "https://schema.org",
    "@type": "FAQPage",
    "mainEntity": [
      {
        "@type": "Question",
        "name": "O modelo de IA roda no plano de hospedagem do bot?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "Não. O modelo roda nos servidores do provedor de IA que você contratou. O bot só recebe a mensagem no Discord, manda o texto para a API do provedor pela internet e devolve a resposta. Por isso o plano de bot pode ser pequeno: ele só executa o Node.js."
        }
      },
      {
        "@type": "Question",
        "name": "Preciso de um SDK do provedor para isso?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "Não. A maioria dos provedores oferece uma API de chat compatível com a da OpenAI, e basta um POST com fetch, que já vem no Node 18 ou mais novo. Trocar de provedor vira só mudar a URL, a chave e o nome do modelo nas variáveis de ambiente."
        }
      },
      {
        "@type": "Question",
        "name": "Por que o bot precisa ser mencionado para responder?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "Porque assim ele só gasta chamadas quando alguém pede. Além disso, o Discord entrega o conteúdo das mensagens que mencionam o bot mesmo sem a intent privilegiada de conteúdo de mensagem, o que simplifica a configuração."
        }
      },
      {
        "@type": "Question",
        "name": "Como evito uma conta alta no provedor de IA?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "Combine quatro travas: limite de uso por usuário no próprio bot, histórico curto, teto de tokens na resposta e um limite de gasto configurado no painel do provedor. Com as quatro, mesmo um servidor em que todo mundo abusa tem um gasto máximo conhecido."
        }
      },
      {
        "@type": "Question",
        "name": "A resposta da IA passou de 2000 caracteres. E agora?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "O Discord recusa mensagens com mais de 2000 caracteres. Corte o texto antes de enviar ou divida em partes. Pedir respostas curtas no prompt do sistema e limitar os tokens de saída reduz a chance de isso acontecer, e também o custo."
        }
      }
    ]
  }
]
```
