CodeGym /Cursos /ChatGPT Apps /Como o GPT decide acionar uma ferramenta: o modelo de too...

Como o GPT decide acionar uma ferramenta: o modelo de tool-call e o papel das descrições

ChatGPT Apps
Nível 4 , Lição 0
Disponível

1. Por que entender o tool-call

Simplificando, um aplicativo web comum funciona no esquema “o usuário clica no botão — nós chamamos a função”. No mundo dos ChatGPT Apps, é diferente: o usuário diz algo, o modelo reflete e, se achar necessário, forma uma chamada estruturada de ferramenta (tool-call).

Ou seja, você não escreve:

onClick={() => callSuggestGiftsApi(formData)}

e em vez disso:

  1. Descreve a ferramenta suggest_gifts (nome, descrição, esquema dos argumentos).
  2. Explica ao modelo no system-prompt por que essa ferramenta é útil.
  3. Entrega o controle ao modelo: ele decide quando e como chamá-la.

Daí a importância de entender cedo duas coisas:

  1. O GPT não vê o seu código de backend. Ele vê apenas o “cabeçalho” da ferramenta: nome, descrição e esquema de parâmetros.
  2. O quão “inteligentemente” o modelo usará seu App depende quase diretamente de como você escreveu essas descrições. Boas descrições são o seu “prompt para a ferramenta”.

A aula de hoje é justamente sobre esse “cérebro” entre o usuário e o seu servidor.

2. Modelo mental do tool-call: o que realmente acontece

Comecemos com a visão geral. Um cenário típico para o GiftGenius:

  1. Usuário: “Sugira um presente para um amigo de 30 anos, orçamento de 100 dólares, ele gosta de videogames”.
  2. O GPT lê essa mensagem e olha quais ferramentas existem. No nosso App, por exemplo, há suggest_gifts.
  3. O GPT decide: “Para responder bem, preciso chamar essa ferramenta”.
  4. Em vez de uma resposta textual normal, ele gera uma estrutura: nome da ferramenta + argumentos em JSON.
  5. O cliente do ChatGPT vê: “Ok, isso é um tool-call”, e o envia para o seu MCP/servidor.
  6. Seu servidor executa a lógica de negócio e retorna um output estruturado.
  7. O GPT recebe o resultado, lê e, com base na resposta da ferramenta, forma uma resposta clara ao usuário e/ou atualiza o widget.

Do ponto de vista da OpenAI API, é o mesmo mecanismo de LLM-function-calling: na resposta do modelo, em vez de texto comum, aparece um objeto com o name da ferramenta e os arguments, e o finish_reason é marcado como tool_calls. O modelo não executa código por conta própria — ele apenas propõe qual ferramenta chamar, e a chamada real é feita pelo cliente (ChatGPT/Apps SDK).

Parece mais ou menos assim (sequência simplificada):

sequenceDiagram
    participant U as Usuário
    participant G as GPT (modelo)
    participant C as Cliente do ChatGPT
    participant S as Seu MCP/Backend

    U->>G: "Sugira um presente para um amigo..."
    G->>C: tool-call: { name: "suggest_gifts", args: {...} }
    C->>S: HTTP /mcp tools/call (suggest_gifts, args)
    S-->>C: Resultado (JSON com a lista de presentes)
    C-->>G: resultado da ferramenta
    G-->>U: Resposta + widget atualizado

Conclusão principal: você não escreve if (userAskedAboutGifts) callSuggestGifts(). Você cria a ferramenta e a sua descrição; a decisão é tomada pelo modelo.

3. O que o modelo vê: System Prompt + lista de ferramentas

Para entender como o GPT decide o que fazer, é preciso saber claramente qual conjunto de informações ele tem no momento da escolha.

De forma simplificada, o modelo vê:

  • o system‑prompt do seu App (vamos detalhar no módulo 5);
  • o histórico do diálogo: mensagens do usuário, as próprias respostas do modelo, resultados de tool-calls anteriores;
  • a lista de ferramentas disponíveis (tools) com seus nomes, descrições e esquemas de parâmetros;
  • anotações adicionais das ferramentas (readOnly/destructive etc.).

Ele não vê:

  • a implementação das funções;
  • consultas SQL;
  • a estrutura das suas tabelas;
  • o conteúdo de um repositório privado com o serviço.

Falaremos sobre MCP em breve. Por ora, basta saber que, no nível do MCP, as ferramentas são declaradas como descritores: cada uma tem name, description e inputSchema (JSON Schema). No handshake, o ChatGPT solicita ao servidor MCP a lista de ferramentas e passa a considerá-las como “ações” disponíveis.

Exemplo de um descritor para o GiftGenius (JSON simplificado):

{
  "name": "suggest_gifts",
  "description": "Seleciona ideias de presentes com base na idade, nos interesses e no orçamento",
  "inputSchema": {
    "type": "object",
    "properties": {
      "age": { "type": "integer" },
      "budget": { "type": "number" }
    },
    "required": ["age", "budget"]
  }
}

O modelo “lê” aqui apenas o texto e a estrutura: o que é age, o que é budget, o que a ferramenta faz em geral. A próxima aula será exatamente sobre como descrever bem o inputSchema. Agora — sobre como, a partir dessa descrição, nasce a decisão “vou chamar suggest_gifts”.

4. Como o tool-call parece aos olhos da API

O ChatGPT chama as ferramentas (tools) do seu servidor MCP de forma semelhante a como um Agent da OpenAI chama funções no seu backend. No ChatGPT Apps SDK, é um pouco mais encapsulado, mas a mecânica básica é a mesma.

Imagine que, no nosso backend, fazemos uma requisição comum à OpenAI API e, ao mesmo tempo, passamos a ferramenta suggest_gifts, que o modelo pode chamar em sua resposta:

const response = await openai.responses.create({
  model: 'gpt-5-mini',
  messages: [
    {
      role: 'user',
      content: 'Preciso de um presente para um amigo de 30 anos, orçamento de 100 dólares'
    }
  ],
  tools: [ // aqui passamos a lista de funções que a LLM pode "chamar"
    {
      name: 'suggest_gifts',
      description: 'Seleciona presentes por idade, orçamento e interesses',
      parameters: {
        type: 'object',
        properties: {
          age: { type: 'integer' },
          budget: { type: 'number' }
        },
        required: ['age', 'budget']
      }
    }
  ]
});

Se o modelo decidir chamar a ferramenta, você receberá, em vez de texto, uma mensagem do assistente com algo como:

{
  "role": "assistant",
  "tool_calls": [
    {
      "id": "call_1",
      "name": "suggest_gifts",
      "arguments": "{\"age\":30,\"budget\":100}"
    }
  ],
  "content": []
}

Dessa forma, a LLM diz ao seu backend que precisa chamar a função suggest_gifts(30,100).

Aqui, três coisas são importantes:

  1. O nome da ferramenta (name) — o modelo realmente insere aqui a string que você especificou em tools ao enviar a primeira requisição.
  2. Os argumentos (arguments) — uma string JSON montada com base em parameters/inputSchema.
  3. A ausência de resposta textual normal (por enquanto) — em vez disso, você recebe a estrutura para chamar a ferramenta.

No ChatGPT App, é a mesma coisa: o modelo retorna “quero chamar suggest_gifts com estes parâmetros”, e o cliente (ChatGPT) faz uma requisição HTTP ao seu MCP/servidor: tools/call com o nome da ferramenta e os argumentos.

5. Como exatamente o modelo decide: ferramenta ou texto

Agora o mais interessante: quando o GPT lembra das suas ferramentas?

A mecânica, simplificada, é esta:

  1. O modelo vê a próxima mensagem do usuário e o contexto atual.
  2. Internamente, há uma “camada” que gera a próxima mensagem do assistente, mas, em vez de sempre produzir texto, o modelo pode escolher uma entre as opções de término:
    • resposta textual normal (finish_reason: "stop");
    • uma ou mais tool-calls (finish_reason: "tool_calls");
    • às vezes, outras opções (por exemplo, “preciso de mais uma mensagem do usuário”).
  3. Essa escolha é influenciada por:
    • o quão parecido o pedido do usuário é com as tarefas descritas nas suas ferramentas;
    • o quão claramente a descrição da ferramenta diz “use-me exatamente neste caso”;
    • os dados do system prompt do app, definidos na configuração do Apps SDK.

Em termos humanos, o modelo “testa” sua ferramenta contra o pedido atual. Se a descrição diz: “Seleciona presentes por idade e interesses”, e o usuário pede “análise do orçamento do governo”, o modelo nem tentará chamá-la. Se a descrição for vaga — “faz coisas legais” —, o modelo não entenderá quando usá-la.

Um detalhe interessante: o modelo não é obrigado a chamar a ferramenta, mesmo que você a tenha descrito. O GPT pode decidir: “Aqui dá para responder sozinho, sem tool‑call”. Por isso, ao longo do curso, nós vamos treinar bastante a escrever descrições de ferramentas que tornem o uso da ferramenta o mais óbvio e vantajoso possível para o modelo.

6. Nome da ferramenta: por que tool1 é uma má ideia

O nome da ferramenta é, na prática, o identificador que o modelo usará em suas chamadas. Parece um campo puramente técnico, mas, na prática, o nome influencia muito o comportamento do modelo.

Se você chamar a ferramenta de tool1, o modelo não entenderá nada a partir disso. Para ele, é apenas uma sequência de caracteres. Se, em vez disso, você a chamar de suggest_gifts, search_products ou fetch_user_orders, o próprio nome já dá um forte sinal do que a ferramenta faz.

Pense em como você lê um código desconhecido. Ao ver uma função calculateCartTotal, você já tem uma ideia do que esperar. O modelo precisa do mesmo “âncora semântica”.

Para o GiftGenius, nomes de ferramentas razoáveis podem ser:

suggest_gifts
search_products
get_product_details
create_order

É bom quando o nome:

  • é curto, mas informativo;
  • segue um estilo único (snake_case, latim, verbo_substantivo);
  • reflete uma ação específica.

Má ideia — misturar ações diferentes em uma única ferramenta, como do_all_gift_stuff. O modelo terá mais dificuldade em entender quando usá-la, e veremos nas próximas aulas como isso quebra o esquema de argumentos e complica a depuração.

7. Descrição da ferramenta: seu prompt para o modelo

Se o nome é o título, a description é uma mini documentação — não para o desenvolvedor humano, mas para o GPT. O desenvolvedor lê o código; o modelo — não. Ele se baseia no texto da descrição ao decidir quando chamar a ferramenta e quais argumentos preencher.

É importante escrever a descrição como um “manual de uso”:

  • quando usar a ferramenta;
  • quais são as limitações;
  • o que ela não deve fazer.

Tomemos a suggest_gifts. Três variantes de descrição.

Ampla demais:

"Seleciona presentes."

O modelo não entenderá para que ocasião, para quem, com quais parâmetros. Essa ferramenta pode “competir” com o conhecimento geral do modelo sobre presentes, e ele muitas vezes optará por responder em texto.

Estreita demais:

"Seleciona presentes apenas para irmãos mais novos no aniversário."

Aqui, praticamente proibimos o uso da ferramenta na maioria das vezes. Qualquer outro cenário — mãe, colega, aniversário de casamento — já “não se encaixa”, e o modelo evitará chamá-la.

Ideal:

"Use esta ferramenta quando precisar selecionar presentes para uma pessoa com base em idade, tipo de relacionamento (amigo, parceiro, colega etc.), orçamento e interesses.
Não a chame para perguntas que não estejam relacionadas a presentes (por exemplo, política ou clima)."

Aqui está claro o que a ferramenta faz, quais parâmetros existem e quando chamá-la, além de uma condição negativa — para quais pedidos é melhor não usá-la.

O modelo “gosta” desses limites claros. Quanto mais explicitamente você indicar para quais formulações do usuário (intents) a ferramenta é adequada, mais previsível será o comportamento do App.

Mini exercício

Você pode, agora mesmo, pegar o seu futuro App (talvez, não de presentes) e criar para uma de suas ferramentas três descrições: muito ampla, muito estreita e balanceada. Depois, teste como o GPT se comporta com as versões diferentes.

8. Esquema de argumentos: como ele ajuda na decisão

Falaremos em detalhes sobre JSON Schema na próxima aula, mas, para entender tool-calls, vale ter uma noção de alto nível.

Quando o modelo decide chamar uma ferramenta, ele precisa:

  1. Entender quais argumentos a ferramenta espera.
  2. Extrair esses valores do texto do usuário (ou do contexto).
  3. Formar o JSON com esses argumentos.

Para isso, a descrição da ferramenta tem o esquema de parâmetros (inputSchema), que informa ao modelo:

  • quais campos existem (age, budget, relationship_type, interests etc.);
  • quais campos são obrigatórios (required);
  • quais são os tipos (integer, number, string, arrays etc.);
  • às vezes — quais valores são válidos (enum) e explicações de campos (description).

Uma interface TypeScript simples para os parâmetros de suggest_gifts pode ser assim:

interface SuggestGiftsParams {
  age: number;
  relationship_type: 'friend' | 'partner' | 'colleague';
  budget: number;
  interests?: string[];
}

No nível do modelo, isso vira um JSON Schema, e o modelo, pelo nome e pela descrição de cada campo, infere que:

  • age deve ser obtido de frases como “30 anos”, “para um adolescente” etc.;
  • budget de “orçamento de 100 dólares”, “até 50 euros”;
  • relationship_type de “amigo”, “colega”;
  • interests — de “gosta de videogames”.

Se você fornecer um esquema sem descrições e com nomes de campos abstratos (a, b, c), o modelo errará com muito mais frequência ao preencher os argumentos. Voltaremos a isso no módulo sobre localização e dicas de UX. A ideia-chave aqui é simples: o esquema não é apenas validação no backend — é, antes de tudo, uma dica ao modelo sobre o que colocar em cada lugar.

Já vimos como o esquema ajuda o modelo a montar os argumentos. Mas além de “o que e como chamar”, importa também “se pode ser chamado agora e o quão seguro é”. É aí que entram permissões e metainformações da ferramenta.

9. Permissões e contexto: nem toda ferramenta está sempre disponível

Além de nome, descrição e esquema de argumentos, há outra dimensão importante — segurança e acesso. Em um App real, as ferramentas variam muito em nível de “risco”. Uma coisa é buscar presentes em um catálogo público; outra é cobrar do cartão do usuário.

O Apps SDK e o MCP permitem refletir isso na descrição e nas anotações — por exemplo, marcando-as como read-only ou destructive.

A ideia é:

  • Ferramentas que apenas leem dados públicos (search_products, get_weather) podem ser chamadas sem confirmações extras.
  • Ferramentas que modificam algo (create_order, cancel_order, charge_user) são marcadas como “destrutivas”. A UI do ChatGPT pode pedir confirmação adicional ao usuário (“Tem certeza de que deseja fazer o pedido?”), e o próprio modelo tenderá a sugeri-las com menos frequência sem um pedido explícito.

Nos módulos futuros, ao configurarmos o MCP, você verá como essas anotações (_meta, destructiveHint, readOnlyHint) aparecem em descritores JSON reais, como influenciam a UX e como o ChatGPT forma diálogos “Are you sure?” antes da chamada. Por ora, basta entender:

  • O GPT leva em conta não apenas o texto da descrição, mas também metainformações de segurança.
  • Uma ferramenta que exige autenticação não será usada até que o usuário esteja logado (ou até que o App obtenha o token necessário).

Esse é mais um fator que influencia a decisão “chamar a ferramenta ou não”: mesmo que, semânticamente, a ferramenta sirva, ela pode estar indisponível por permissões, e o modelo escolherá outro caminho.

10. De onde vêm as ferramentas no ChatGPT

Do ponto de vista arquitetural, uma ferramenta pode chegar ao modelo por dois caminhos principais.

Primeiro, pela configuração do seu ChatGPT App. Ao registrar o App, você indica quais servidores MCP (e suas ferramentas) estão vinculados a ele, ou quais tools embutidas existem no próprio aplicativo. Ao iniciar a sessão, o ChatGPT obtém essa configuração e entende quais ferramentas estão disponíveis.

Segundo, diretamente do MCP. O MCP (Model Context Protocol) define um modo padrão para o cliente (no nosso caso, ChatGPT/Apps SDK) descobrir o que o seu servidor sabe fazer: ele faz a requisição tools/list, recebe um JSON com as descrições das ferramentas e as guarda como capabilities. Analisaremos a mecânica em um módulo específico sobre MCP; agora, o importante é a ideia geral.

Esquematicamente:

flowchart LR
  A[ChatGPT Client] -->|handshake| B[MCP Server]
  B -->|tools/list| A
  A -->|envia a lista| G[GPT Model]

Depois disso, a lista de ferramentas passa a fazer parte do contexto do modelo. Se você alterar o esquema ou a descrição de uma ferramenta no servidor e reiniciar o App, o novo descritor chegará ao ChatGPT no próximo handshake, e o modelo começará a decidir de forma diferente sobre a chamada.

E um ponto prático importante: quando você altera apenas o backend (a implementação da ferramenta), o modelo não sabe disso. Mas quando você muda o name/description/schema, você realmente muda o “cérebro” do App. Às vezes, é mais útil ajustar uma linha na description do que escrever 200 linhas de código com heurísticas.

11. Aplicando ao GiftGenius: criando uma ferramenta que o modelo queira chamar

Vamos ligar tudo ao nosso App didático, o GiftGenius. Suponha que já temos um servidor MCP ou uma camada de backend na qual registramos ferramentas. Vamos registrar a ferramenta suggest_gifts usando server.registerTool(...).

Esboço simples em TypeScript (ainda sem lógica real):

// pseudo-mcp-server/tools/suggestGifts.ts
server.registerTool(
  'suggest_gifts', // nome da ferramenta
  {
    title: 'Seleção de presentes',
    description:
      'Use esta ferramenta para selecionar ideias de presentes por idade, ' +
      'tipo de relacionamento e orçamento. Não a chame para perguntas não relacionadas a presentes.',
    inputSchema: { // descrição dos parâmetros da ferramenta
      type: 'object',
      properties: {
        age: { type: 'integer', description: 'Idade do destinatário em anos' },
        relationship_type: {
          type: 'string',
          description: 'Tipo de relacionamento: friend, partner, colleague'
        },
        budget: {
          type: 'number',
          description: 'Orçamento máximo para o presente na moeda do usuário'
        }
      },
      required: ['age', 'budget']
    }
  },
  async ({ age, relationship_type, budget }) => { // código da função/ferramenta
    // A lógica real virá depois
    return { suggestions: [] };
  }
);

Repare nos detalhes que já pensamos nesta fase, embora a lógica ainda seja um “stub”:

  • Nome: suggest_gifts, e não tool1.
  • Descrição: explica explicitamente quando chamar a ferramenta e quando não chamar.
  • Descrições dos campos: ajudam o modelo a mapear corretamente o texto do usuário para os argumentos.

Como resultado, quando o usuário escrever “Escolha um presente para um colega por 50 dólares”, o modelo verá que:

  • há uma ferramenta chamada suggest_gifts com descrição sobre seleção de presentes;
  • ela tem os campos age, relationship_type, budget;
  • budget — “orçamento máximo para o presente”, relationship_type — “tipo de relacionamento: friend, partner, colleague”.

Mesmo que os usuários se expressem de forma imprecisa (“até cinquenta”, “para o parceiro de projeto”), o modelo terá contexto suficiente para tentar montar o JSON de argumentos corretamente.

Quando a nossa ferramenta estiver funcionando de verdade (no módulo sobre backend e MCP), você já estará bem orientado no tema: o GPT vai chamá-la de forma previsível, simplesmente porque projetamos a interface e a descrição com cuidado.

12. Pequena prática para você

Para que o tema não fique apenas teórico, recomendo um pequeno experimento logo após a aula.

Primeiro, pegue um dos seus cenários do GiftGenius ou invente um novo App. Anote, no papel ou no editor, uma função que você quer claramente disponibilizar ao modelo — algo como search_products, find_hotels, calculate_shipping.

Depois, crie para essa mesma ferramenta três pares “nome + descrição”:

  1. Nome e descrição muito abstratos.
  2. Excessivamente específicos (quase um caso especial).
  3. Nome + descrição bem balanceados, dizendo claramente quando chamar a ferramenta e o que ela não deve fazer.

Em seguida — se quiser — usando o OpenAI SDK comum, faça uma requisição simples com essas variantes e observe como muda o comportamento do modelo: a ferramenta é chamada? Como ele preenche os argumentos? Em pesquisas sobre o tema, há exatamente um exercício desse tipo para suggest_gifts.

13. Erros comuns ao projetar tool-call e descrições

Erro nº 1: Dar nomes como tool1, handler, doStuff.
Esse tipo de naming é absolutamente inútil para o modelo. O GPT não adivinha “as intenções do desenvolvedor” pelo nome do arquivo; ele precisa de um nome semanticamente claro. Se você fornecer um conjunto tool1, tool2, tool3 sem descrições, a ferramenta praticamente não será chamada: o modelo simplesmente não entenderá o que cada uma faz e vai ignorá-las ou escolher ao acaso.

Erro nº 2: Tratar a description como comentário para humanos.
Muitos escrevem algo formal como “Função para seleção de presentes”, partindo do princípio de que os detalhes estão no código. Mas o modelo não vê o código — ele vê apenas o texto da descrição e o esquema de argumentos. Uma descrição imprecisa vira fonte de alucinações: o GPT pode tentar responder por conta própria quando deveria chamar a ferramenta, ou chamá-la em situações estranhas.

Erro nº 3: Tornar a descrição ampla demais ou estreita demais.
Se você escrever “Faz coisas legais”, o modelo não entende os limites de aplicação. Se escrever “Seleciona presentes apenas para o irmão mais novo no aniversário de 18 anos”, você praticamente proíbe o uso na maioria dos casos. A descrição ideal define claramente a área de tarefas (seleção de presentes por um conjunto de parâmetros), lista os parâmetros chave (idade, relacionamento, orçamento, interesses) e diz para quais tipos de perguntas a ferramenta não deve ser usada.

Erro nº 4: Ignorar o esquema de argumentos como parte do “prompt”.
Alguns desenvolvedores veem o JSON Schema apenas como validação no servidor. Na realidade, o modelo analisa ativamente os nomes dos campos, seus tipos e descrições para entender quais dados extrair do texto do usuário. Se você nomear um campo x sem descrição e torná-lo opcional, o GPT começará a preenchê-lo de forma caótica ou não o preencherá. Um esquema correto, com nomes claros e descrições sucintas, reduz bastante a quantidade de tool-calls inválidos.

Erro nº 5: Esperar que o modelo “seja obrigado” a chamar a ferramenta.
Desenvolvedores às vezes se surpreendem: “Por que o GPT não chamou minha ferramenta, se ela existe?”. A resposta quase sempre é: da descrição ou do system‑prompt não decorre que a ferramenta é necessária para aquele pedido, ou o texto caiu em uma zona em que o modelo julga ser mais simples responder sozinho.

Erro nº 6: Misturar várias ações diferentes em uma única ferramenta.
Às vezes dá vontade de criar uma manage_orders universal que busca pedidos, cria novos e cancela antigos. Para humanos, isso ainda dá para explicar, mas para o modelo vira uma ferramenta nebulosa, sem limites claros. O GPT entende pior quando exatamente chamá-la, e fica mais difícil preencher os argumentos — afinal, passa a existir um monte de campos opcionais. É melhor dividir em ferramentas mais específicas (get_order, create_order, cancel_order) com descrições e esquemas claros.

Erro nº 7: Não considerar permissões e segurança no design da ferramenta.
Se você descreve uma ferramenta que pode executar ações destrutivas (cobranças, exclusão de dados), mas não a marca como destrutiva e não limita o escopo de uso na descrição, você cria risco. A UI do ChatGPT não pedirá confirmação extra, e o modelo pode decidir chamá-la até em cenários “limítrofes”. As anotações corretas e uma descrição cuidadosa (“use somente após consentimento explícito do usuário”) ajudam a reduzir esses riscos já no nível do tool-call.

Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION