Blog

Function calling vs RAG para dados em tempo real

Quando um usuário pergunta "cadê meu pedido?", nenhuma base de conhecimento no mundo tem a resposta: o status muda a cada minuto e vive no banco transacional, não num documento. Ainda assim, muita gente tenta resolver tudo com RAG, indexa FAQ, políticas e manuais, e depois se frustra quando o bot inventa um prazo de entrega que não existe. O problema não é o RAG: é usar retrieval para um dado que não é recuperável, e sim consultável. Function calling resolve exatamente essa classe: em vez de buscar um trecho parecido, o modelo chama uma função que executa a consulta ao vivo e recebe o dado fresco de volta. Este artigo separa as duas ferramentas por natureza do dado, mostra os fluxos lado a lado, quando cada uma vence, um exemplo real de tool use e como rotear entre elas numa arquitetura única.

2026-07-07 / IA Aplicada / 12 min

01

O eixo que separa as duas: dado estático x dado vivo

RAG e function calling não competem pelo mesmo trabalho; eles resolvem perguntas de naturezas diferentes. RAG é para conhecimento: texto que já existe escrito em algum lugar (uma política de troca, um trecho de manual, um artigo) e que você quer recuperar por similaridade semântica. Function calling é para ação e consulta: um dado que só existe no momento em que você pergunta (o saldo de hoje, o status atual do pedido, o clima agora) ou uma operação que muda o mundo (criar um chamado, agendar uma visita, emitir um boleto).

A pergunta que separa as duas é simples: a resposta está escrita em algum documento ou precisa ser calculada/consultada agora? Se está escrita, RAG recupera. Se precisa ser consultada, function calling chama uma API. Confundir os dois é a raiz de metade dos bots que alucinam: eles tentam recuperar por similaridade um dado que muda a cada segundo, e o trecho mais parecido que o retrieval encontra é sempre uma versão velha ou genérica.

02

Comparação direta

A decisão entre function calling e RAG cai em poucas dimensões que puxam claramente para um lado. A tabela abaixo coloca as que mais pesam na hora de desenhar o sistema.

DimensãoRAGFunction calling
Natureza do dadoEstático: texto já escrito (FAQ, políticas, manuais, artigos)Vivo: consultado ou calculado no momento da pergunta (status, saldo, estoque)
FrescorDepende da última reindexação; entre reindexações o dado envelheceSempre atual: a tool consulta a fonte da verdade a cada chamada
Efeito colateralNenhum: retrieval só lê documentosPode agir: criar chamado, agendar, emitir, alterar estado no sistema
Fonte da verdadeUm corpus de documentos indexado em vector storeA API/banco transacional que já é a autoridade sobre aquele dado
Risco típicoRecuperar o trecho errado ou desatualizado e responder em cima deleChamar a função errada ou com argumento inválido; exige validação dos args
RastreabilidadeCita o documento e a seção de origemRegistra a chamada, os argumentos e a resposta bruta da API

03

Os dois fluxos lado a lado

Ver os dois caminhos deixa clara a diferença de mecanismo: RAG recupera texto parecido e injeta no prompt; function calling faz o modelo decidir chamar uma função, executa a chamada no seu backend e devolve o resultado para o modelo redigir a resposta final.

RAG (dado estático)
  Pergunta  ->  Embed  ->  Retrieve top-k  ->  Injeta chunks  ->  Gerar  ->  Resposta
                            (vector store)

Function calling (dado vivo)
  Pergunta  ->  Modelo decide a tool  ->  Seu backend executa a chamada (API/banco)
                                                |
                                                v
                          Resultado fresco  ->  Modelo redige  ->  Resposta

A diferença central está no meio do caminho: em RAG o que entra no contexto é um trecho de texto que já existia; em function calling o que entra é o retorno de uma execução que aconteceu agora. Por isso function calling nunca esbarra em dado velho: ele não busca uma versão, ele provoca uma consulta.

04

Quando function calling vence

Function calling é a escolha certa sempre que a resposta não está escrita em lugar nenhum e precisa ser consultada ao vivo, ou quando o usuário quer que algo aconteça, não apenas ser informado.

  • Estado transacional em tempo real: status de pedido, saldo, posição de entrega, disponibilidade de agenda. Muda a cada minuto e vive no sistema, não num documento.
  • Dados de terceiros ao vivo: cotação, clima, rastreamento de transportadora, consulta de CEP. A fonte da verdade é uma API externa, não um corpus indexado.
  • Ações com efeito colateral: abrir chamado, agendar visita, emitir segunda via, cancelar pedido. RAG só lê; aqui é preciso executar.
  • Cálculos determinísticos: frete, juros, parcelas, conversão de unidade. Você quer o número exato de uma função, não uma aproximação gerada pelo modelo.
  • Personalização por identidade: "meus dados", "minha fatura", "meu contrato". A resposta depende de quem pergunta e só a consulta parametrizada resolve.

05

Quando RAG vence

RAG continua sendo a ferramenta certa quando a resposta já existe escrita em algum lugar e o trabalho é encontrar o trecho certo dentro de um volume grande de texto.

  • Conhecimento textual estável: políticas de troca, termos de uso, manuais, documentação. O dado não muda a cada minuto e já está redigido.
  • Base grande demais para o contexto: milhares de documentos, anos de artigos. Você precisa recuperar por similaridade, não consultar por chave.
  • Perguntas abertas e explicativas: "como funciona a garantia estendida?", "qual a diferença entre os planos?". A resposta é explicação, não um valor vivo.
  • Necessidade de citar a fonte: quando cada afirmação deve apontar para o documento e a seção de origem, o retrieval entrega esse rastro naturalmente.

06

Exemplo prático com tool use

O coração do function calling é a definição da tool: você descreve para o modelo qual função existe, o que ela faz e quais argumentos ela aceita. O modelo decide quando chamá-la e com quais argumentos; o seu backend executa a chamada de verdade e devolve o resultado. No exemplo abaixo, usando a Anthropic Messages API, uma tool consulta o status atual do pedido no seu banco. O modelo nunca inventa o status: ele delega a consulta e só redige a resposta com o dado que voltou.

import Anthropic from '@anthropic-ai/sdk';

const client = new Anthropic();

// A tool que expoe a consulta de status ao modelo.
// O modelo NAO executa nada: ele so decide chamar e com quais argumentos.
const tools = [
  {
    name: 'get_order_status',
    description:
      'Consulta o status atual de um pedido pelo numero. Use sempre que o usuario perguntar sobre um pedido especifico; nunca invente o status.',
    input_schema: {
      type: 'object',
      properties: {
        order_id: { type: 'string', description: 'Numero do pedido, ex: PED-10293' },
      },
      required: ['order_id'],
    },
  },
];

// Execucao real da tool no SEU backend: consulta a fonte da verdade.
async function runTool(name, input) {
  if (name === 'get_order_status') {
    const order = await db.orders.findByPublicId(input.order_id);
    if (!order) return { found: false };
    return {
      found: true,
      status: order.status, // 'em_separacao' | 'enviado' | 'entregue'
      carrier: order.carrier,
      eta: order.estimatedDelivery,
    };
  }
  throw new Error('Tool desconhecida: ' + name);
}

async function ask(question) {
  const messages = [{ role: 'user', content: question }];

  // 1o turno: o modelo decide se chama a tool.
  let res = await client.messages.create({
    model: 'claude-sonnet-4-5',
    max_tokens: 512,
    tools,
    messages,
  });

  // Enquanto o modelo pedir tools, executa e devolve o resultado.
  while (res.stop_reason === 'tool_use') {
    const toolUse = res.content.find((b) => b.type === 'tool_use');
    const result = await runTool(toolUse.name, toolUse.input);

    messages.push({ role: 'assistant', content: res.content });
    messages.push({
      role: 'user',
      content: [
        {
          type: 'tool_result',
          tool_use_id: toolUse.id,
          content: JSON.stringify(result),
        },
      ],
    });

    res = await client.messages.create({
      model: 'claude-sonnet-4-5',
      max_tokens: 512,
      tools,
      messages,
    });
  }

  return res.content.find((b) => b.type === 'text')?.text;
}

// O modelo chama get_order_status('PED-10293'), recebe o status FRESCO
// do banco e so entao redige a resposta. Nada e recuperado por similaridade.
await ask('Cade meu pedido PED-10293?');

Repare no ponto que muda tudo: o dado do status nunca passou por embedding nem por vector store. O modelo apenas decidiu chamar a função, o seu backend consultou o banco (a fonte da verdade) e o resultado voltou fresco para o modelo redigir. É impossível o bot responder um status desatualizado, porque ele não busca uma versão antiga: ele provoca uma consulta nova a cada pergunta.

07

Arquitetura combinada: roteie por intenção

Num bot de atendimento real, as duas ferramentas convivem: o mesmo usuário pergunta "qual o prazo de troca?" (RAG, conhecimento estável) e "cadê meu pedido?" (function calling, dado vivo) na mesma conversa. A arquitetura robusta não escolhe uma; ela roteia por intenção. Na prática moderna, você nem precisa de um classificador separado: expor tanto a base de conhecimento quanto as tools ao mesmo modelo deixa ele próprio decidir se recupera um documento ou chama uma função.

  1. Modele o conhecimento estável como RAG: políticas, FAQ, manuais viram um corpus indexado ou uma tool de busca semântica que retorna trechos com fonte.
  2. Modele o dado vivo e as ações como tools: status, saldo, agendamento, emissão. Cada tool tem schema explícito de argumentos e valida a entrada.
  3. Exponha ambos ao mesmo modelo: dê a ele tanto a busca semântica quanto as tools transacionais. Ele decide, por pergunta, qual caminho seguir.
  4. Valide os argumentos antes de executar: nunca confie cegamente nos args gerados. Cheque tipo, formato e permissão (o usuário pode ver aquele pedido?) antes de tocar o backend.
  5. Registre a decisão: logue se a resposta veio de retrieval ou de tool, com os argumentos e o retorno. Isso é o que torna o sistema auditável e depurável.

O ganho dessa arquitetura é que cada pergunta cai na ferramenta certa pela sua natureza: conhecimento estável pelo RAG, dado vivo e ação pela tool. O bot para de alucinar prazo de entrega porque nunca mais tenta recuperar por similaridade um dado que só o banco transacional conhece.

FAQ

Perguntas frequentes

Function calling substitui RAG?

Não. Eles resolvem naturezas diferentes de pergunta. Function calling é para dado vivo (consultado ou calculado agora) e para ações com efeito colateral; RAG é para conhecimento textual já escrito que você recupera por similaridade. Um bot de atendimento sério usa os dois: RAG para políticas e manuais, function calling para status, saldo e agendamento. A arquitetura ideal roteia por intenção entre as duas.

Como o modelo sabe qual tool chamar?

Pela descrição. Cada tool tem um nome, uma descrição em linguagem natural do que faz e um schema dos argumentos que aceita. O modelo lê essas descrições junto com a pergunta e decide se alguma tool se aplica e com quais argumentos chamá-la. Por isso a qualidade da descrição importa tanto quanto o código: uma descrição vaga leva o modelo a chamar a tool errada ou a não chamá-la quando deveria.

Function calling é seguro para ações que mudam dados?

É seguro desde que você não confie cegamente nos argumentos gerados pelo modelo. O modelo decide chamar e sugere os argumentos, mas quem executa é o seu backend. Antes de tocar o banco, valide tipo e formato dos args, cheque a permissão do usuário sobre aquele recurso e, para ações de alto impacto, exija confirmação explícita. O modelo propõe; o seu código autoriza e executa.

Escolha pela natureza do dado, não pela ferramenta da moda

RAG e function calling resolvem perguntas diferentes: retrieval para conhecimento estável já escrito, tool use para dado vivo e ações que mudam o mundo. Posso avaliar o seu fluxo de atendimento e desenhar a arquitetura certa, roteando cada pergunta para a ferramenta que de fato tem a resposta.