Dê aos modelos acesso a novas funcionalidades e dados que eles possam usar para seguir instruções e responder a prompts.
Responses
A chamada de função (também conhecida como chamada de ferramenta) oferece uma maneira poderosa e flexível de os modelos da OpenAI interagirem com sistemas externos e acessarem dados além daqueles usados em seu treinamento. Este guia mostra como conectar um modelo aos dados e às ações disponibilizados pelo seu aplicativo. Mostraremos como usar ferramentas de função (definidas por um esquema JSON) e ferramentas personalizadas que trabalham com entradas e saídas de texto em formato livre.
Para sessões da API de Agentes, use Funções para registrar funções e lidar com solicitações de ação da sessão. Os exemplos deste guia mostram as integrações com a API Responses e o Chat Completions.
Se seu aplicativo tiver muitas funções ou esquemas grandes, você pode combinar a chamada de função com a pesquisa de ferramentas para adiar o carregamento de ferramentas pouco usadas e carregá-las apenas quando o modelo precisar delas. Somente gpt-5.4 e modelos posteriores oferecem suporte a tool_search.
O GPT-6 Astra exige a Responses API para chamadas de ferramentas. Os exemplos de Chat Completions
usam GPT-5.6 por compatibilidade. Consulte o guia de
migração para atualizar uma integração
existente.
Como funciona
Vamos começar entendendo alguns termos essenciais sobre chamadas de ferramentas. Depois de estabelecer esse vocabulário comum, mostraremos como fazer essas chamadas com exemplos práticos.
Uma função ou ferramenta se refere, de forma abstrata, a uma funcionalidade à qual informamos ao modelo que ele tem acesso. Ao gerar uma resposta a um prompt, o modelo pode decidir que precisa de dados ou funcionalidades fornecidos por uma ferramenta para seguir as instruções do prompt.
Você poderia dar ao modelo acesso a ferramentas que:
Consultem o tempo de hoje em um local
Acessem os detalhes da conta de um determinado ID de usuário
Emitam reembolsos por um pedido extraviado
Ou qualquer outra coisa que você gostaria que o modelo pudesse saber ou fazer ao responder a um prompt.
Ao fazer uma requisição de API ao modelo com um prompt, podemos incluir uma lista de ferramentas que ele pode considerar usar. Por exemplo, se quiséssemos que o modelo pudesse responder a perguntas sobre o tempo atual em algum lugar do mundo, poderíamos dar a ele acesso a uma ferramenta get_weather que recebe location como argumento.
Uma chamada de função ou chamada de ferramenta se refere a um tipo especial de resposta que podemos receber do modelo quando ele analisa um prompt e determina que, para seguir suas instruções, precisa chamar uma das ferramentas que disponibilizamos.
Se o modelo receber um prompt como "como está o tempo em Paris?" em uma requisição de API, ele poderá responder com uma chamada à ferramenta get_weather, usando Paris como argumento location.
Uma saída de chamada de função ou saída de chamada de ferramenta se refere à resposta que uma ferramenta gera usando a entrada de uma chamada de ferramenta feita pelo modelo. Essa saída pode ser JSON estruturado ou texto simples e deve conter uma referência a uma chamada de ferramenta específica do modelo (identificada por call_id nos exemplos a seguir).
Para completar nosso exemplo sobre o tempo:
O modelo tem acesso a uma ferramentaget_weather que recebe location como argumento.
Em resposta a um prompt como "como está o tempo em Paris?", o modelo retorna uma chamada de ferramenta que contém um argumento location com o valor Paris
A saída da chamada de ferramenta pode retornar um objeto JSON (por exemplo, {"temperature": "25", "unit": "C"}, indicando uma temperatura atual de 25 graus), conteúdo de imagem ou conteúdo de arquivo.
Em seguida, enviamos de volta ao modelo a definição completa da ferramenta, o prompt original, a chamada de ferramenta feita pelo modelo e a saída dessa chamada para, finalmente, receber uma resposta de texto como:
The weather in Paris today is 25C.
Uma função é um tipo específico de ferramenta, definido por um esquema JSON. A definição de uma função permite que o modelo passe dados ao seu aplicativo, onde seu código pode acessar dados ou executar ações sugeridas pelo modelo.
Além das ferramentas de função, existem ferramentas personalizadas (descritas neste guia) que trabalham com entradas e saídas de texto livre.
A chamada de ferramenta é uma conversa em várias etapas entre seu aplicativo e um modelo por meio da API da OpenAI. Esse fluxo tem cinco etapas principais:
Faça uma requisição ao modelo com ferramentas que ele possa chamar
Receba uma chamada de ferramenta do modelo
Execute código no aplicativo com a entrada da chamada de ferramenta
Faça uma segunda requisição ao modelo com a saída da ferramenta
Receba uma resposta final do modelo (ou mais chamadas de ferramentas)
Com a Responses, seu aplicativo pode continuar esse fluxo por quantas chamadas de ferramentas a tarefa exigir. Se você quiser um framework que reúna a orquestração recorrente desse ciclo, veja como a Responses API se compara ao Agents SDK.
Exemplo de ferramenta de função
Vamos ver um fluxo completo de chamadas de ferramentas para uma função get_horoscope que consulta o horóscopo diário de um signo astrológico.
Exemplo completo de chamada de ferramenta
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70import OpenAI from "openai";const openai = new OpenAI();// 1. Define a list of callable tools for the modelconst tools = [ { type: "function", function: { name: "get_horoscope", description: "Get today's horoscope for an astrological sign.", parameters: { type: "object", properties: { sign: { type: "string", description: "An astrological sign like Taurus or Aquarius", }, }, required: ["sign"], additionalProperties: false, }, strict: true, }, },];function getHoroscope(sign) { return `${sign}: Next Tuesday you will befriend a baby otter.`;}const messages = [ { role: "user", content: "What is my horoscope? I am an Aquarius." },];// 2. Prompt the model with tools definedlet response = await openai.chat.completions.create({ model: "gpt-5.6", messages, tools,});messages.push(response.choices[0].message);for (const toolCall of response.choices[0].message.tool_calls ?? []) { if (toolCall.type !== "function") continue; if (toolCall.function.name === "get_horoscope") { // 3. Execute the function logic for get_horoscope const args = JSON.parse(toolCall.function.arguments); const horoscope = getHoroscope(args.sign); // 4. Provide function call results to the model messages.push({ role: "tool", tool_call_id: toolCall.id, content: JSON.stringify({ horoscope }), }); }}response = await openai.chat.completions.create({ model: "gpt-5.6", messages, tools,});// 5. The model should be able to give a response!console.log(response.choices[0].message.content);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67from openai import OpenAIimport jsonclient = OpenAI()# 1. Define a list of callable tools for the modeltools = [ {"type": "function","function": {"name": "get_horoscope","description": "Get today's horoscope for an astrological sign.","parameters": {"type": "object","properties": {"sign": {"type": "string","description": "An astrological sign like Taurus or Aquarius", }, },"required": ["sign"],"additionalProperties": False, },"strict": True, }, },]defget_horoscope(sign):returnf"{sign}: Next Tuesday you will befriend a baby otter."messages = [{"role": "user", "content": "What is my horoscope? I am an Aquarius."}]# 2. Prompt the model with tools definedresponse = client.chat.completions.create(model="gpt-5.6",messages=messages,tools=tools,)messages.append(response.choices[0].message)for tool_call in response.choices[0].message.tool_calls or []:if tool_call.function.name =="get_horoscope":# 3. Execute the function logic for get_horoscope args = json.loads(tool_call.function.arguments) horoscope = get_horoscope(args["sign"])# 4. Provide function call results to the model messages.append( {"role": "tool","tool_call_id": tool_call.id,"content": json.dumps({"horoscope": horoscope}), } )response = client.chat.completions.create(model="gpt-5.6",messages=messages,tools=tools,)# 5. The model should be able to give a response!print(response.choices[0].message.content)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77import OpenAI from "openai";import { toResponseInputItems } from "openai/lib/responses/ResponseInputItems";const openai = new OpenAI();// 1. Define a list of callable tools for the modelconst tools = [ { type: "function", name: "get_horoscope", description: "Get today's horoscope for an astrological sign.", parameters: { type: "object", properties: { sign: { type: "string", description: "An astrological sign like Taurus or Aquarius", }, }, required: ["sign"], additionalProperties: false, }, strict: true, },];function getHoroscope(sign) { return `${sign}: Next Tuesday you will befriend a baby otter.`;}// Create a running input list we will add to over timelet input = [ { role: "user", content: "What is my horoscope? I am an Aquarius." },];// 2. Prompt the model with tools definedlet response = await openai.responses.create({ model: "gpt-6-astra", tools, input,});// Preserve model output for the next turninput.push(...toResponseInputItems(response.output));for (const item of response.output) { if (item.type !== "function_call") continue; if (item.name === "get_horoscope") { // 3. Execute the function logic for get_horoscope const { sign } = JSON.parse(item.arguments); const horoscope = getHoroscope(sign); // 4. Provide function call results to the model input.push({ type: "function_call_output", call_id: item.call_id, output: horoscope, }); }}console.log("Final input:");console.log(JSON.stringify(input, null, 2));response = await openai.responses.create({ model: "gpt-6-astra", instructions: "Respond only with a horoscope generated by a tool.", tools, input,});// 5. The model should be able to give a response!console.log("Final output:");console.log(response.output_text);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72from openai import OpenAIimport jsonclient = OpenAI()# 1. Define a list of callable tools for the modeltools = [ {"type": "function","name": "get_horoscope","description": "Get today's horoscope for an astrological sign.","parameters": {"type": "object","properties": {"sign": {"type": "string","description": "An astrological sign like Taurus or Aquarius", }, },"required": ["sign"], }, },]defget_horoscope(sign):returnf"{sign}: Next Tuesday you will befriend a baby otter."# Create a running input list we will add to over timeinput_list = [{"role": "user", "content": "What is my horoscope? I am an Aquarius."}]# 2. Prompt the model with tools definedresponse = client.responses.create(model="gpt-6-astra",tools=tools,input=input_list,)# Save function call outputs for subsequent requestsinput_list += response.outputfor item in response.output:if item.type =="function_call":if item.name =="get_horoscope":# 3. Execute the function logic for get_horoscope sign = json.loads(item.arguments)["sign"] horoscope = get_horoscope(sign)# 4. Provide function call results to the model input_list.append( {"type": "function_call_output","call_id": item.call_id,"output": horoscope, } )print("Final input:")print(input_list)response = client.responses.create(model="gpt-6-astra",instructions="Respond only with a horoscope generated by a tool.",tools=tools,input=input_list,)# 5. The model should be able to give a response!print("Final output:")print(response.model_dump_json(indent=2))print("\n"+ response.output_text)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75package mainimport ( "context" "encoding/json" "fmt" "github.com/openai/openai-go/v3" "github.com/openai/openai-go/v3/responses")func main() { client := openai.NewClient() tool := horoscopeResponseTool() response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{ Model: "gpt-6-astra", Input: responses.ResponseNewParamsInputUnion{OfString: openai.String("What is my horoscope? I am an Aquarius.")}, Tools: []responses.ToolUnionParam{tool}, }) if err != nil { panic(err) } var functionOutput responses.ResponseInputItemUnionParam for _, output := range response.Output { if output.Type != "function_call" { continue } call := output.AsFunctionCall() if call.Name != "get_horoscope" { continue } var arguments struct { Sign string `json:"sign"` } if err := json.Unmarshal([]byte(call.Arguments), &arguments); err != nil { panic(err) } functionOutput = responses.ResponseInputItemParamOfFunctionCallOutput(getHoroscope(arguments.Sign)) functionOutput.OfFunctionCallOutput.CallID = openai.String(call.CallID) } if functionOutput.OfFunctionCallOutput == nil { panic("the model did not call get_horoscope") } response, err = client.Responses.New(context.Background(), responses.ResponseNewParams{ Model: "gpt-6-astra", PreviousResponseID: openai.String(response.ID), Instructions: openai.String("Respond only with a horoscope generated by a tool."), Input: responses.ResponseNewParamsInputUnion{OfInputItemList: responses.ResponseInputParam{functionOutput}}, Tools: []responses.ToolUnionParam{tool}, }) if err != nil { panic(err) } fmt.Println(response.OutputText())}func horoscopeResponseTool() responses.ToolUnionParam { parameters := map[string]any{ "type": "object", "properties": map[string]any{ "sign": map[string]any{"type": "string", "description": "An astrological sign like Taurus or Aquarius"}, }, "required": []string{"sign"}, "additionalProperties": false, } tool := responses.ToolParamOfFunction("get_horoscope", parameters, true) tool.OfFunction.Description = openai.String("Get today's horoscope for an astrological sign.") return tool}func getHoroscope(sign string) string { return fmt.Sprintf("%s: Next Tuesday you will befriend a baby otter.", sign)}
Observe que, para modelos de raciocínio como GPT-5 ou o4-mini, todos os itens de raciocínio
retornados nas respostas do modelo com chamadas de ferramentas também devem ser enviados de volta com as saídas
dessas chamadas.
Definição de funções
As funções geralmente são declaradas no parâmetro tools de cada requisição de API. Com a pesquisa de ferramentas, seu aplicativo também pode carregar funções cujo carregamento foi adiado em um momento posterior da interação. Em ambos os casos, cada função disponível para chamada usa a mesma estrutura de esquema. A definição de uma função tem as seguintes propriedades:
Campo
Descrição
type
Deve ser sempre function
name
O nome da função (por exemplo, get_weather)
description
Detalhes sobre quando e como usar a função
parameters
Esquema JSON que define os argumentos de entrada da função
strict
Indica se o modo estrito deve ser aplicado à chamada de função
Veja um exemplo de definição da função get_weather
12345678910111213141516171819202122{ "type": "function", "name": "get_weather", "description": "Retrieves current weather for the given location.", "parameters": { "type": "object", "properties": { "location": { "type": "string", "description": "City and country e.g. Bogotá, Colombia" }, "units": { "type": "string", "enum": ["celsius", "fahrenheit"], "description": "Units the temperature will be returned in." } }, "required": ["location", "units"], "additionalProperties": false }, "strict": true}
Como os parameters são definidos por um esquema JSON, você pode aproveitar seus diversos recursos, como tipos de propriedades, enumerações, descrições, objetos aninhados e objetos recursivos.
Definição de espaços de nomes
Use espaços de nomes para agrupar ferramentas relacionadas por domínio, como crm, billing ou shipping. Os espaços de nomes ajudam a organizar ferramentas semelhantes e são especialmente úteis quando o modelo precisa escolher entre ferramentas que atendem a sistemas ou finalidades diferentes, como uma ferramenta de pesquisa para seu CRM e outra para seu sistema de chamados de suporte.
Se você precisar dar ao modelo acesso a um grande ecossistema de ferramentas, poderá adiar o carregamento de algumas ou de todas elas com tool_search. A ferramenta tool_search permite que o modelo pesquise ferramentas relevantes, adicione-as ao contexto e depois as use. Somente gpt-5.4 e modelos posteriores oferecem suporte a ela. Leia o guia de pesquisa de ferramentas para saber mais.
Embora recomendemos que você defina os esquemas das funções diretamente, nossos SDKs têm utilitários para converter objetos pydantic e zod em esquemas. Nem todos os recursos de pydantic e zod são compatíveis.
Defina objetos para representar o esquema da função
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26import OpenAI from "openai";import { z } from "zod";import { zodFunction } from "openai/helpers/zod";const openai = new OpenAI();const GetWeatherParameters = z.object({ location: z.string().describe("City and country e.g. Bogotá, Colombia"),});const tools = [ zodFunction({ name: "getWeather", parameters: GetWeatherParameters }),];const messages = [ { role: "user", content: "What's the weather like in Paris today?" },];const response = await openai.chat.completions.create({ model: "gpt-5.6", messages, tools, store: true,});console.log(response.choices[0].message.tool_calls);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19from openai import OpenAI, pydantic_function_toolfrom pydantic import BaseModel, Fieldclient = OpenAI()classGetWeather(BaseModel): location: str= Field(..., description="City and country e.g. Bogotá, Colombia")tools = [pydantic_function_tool(GetWeather)]completion = client.chat.completions.create(model="gpt-5.6",messages=[{"role": "user", "content": "What's the weather like in Paris today?"}],tools=tools,)print(completion.choices[0].message.tool_calls)
Práticas recomendadas para definir funções
Escreva nomes de funções, descrições de parâmetros e instruções claros e detalhados.
Descreva explicitamente a finalidade da função e de cada parâmetro (e seu formato), além do que a saída representa.
Use o prompt do sistema para descrever quando usar (e quando não usar) cada função. Em geral, diga ao modelo exatamente o que fazer.
Inclua exemplos e casos extremos, especialmente para corrigir falhas recorrentes. (Observação: adicionar exemplos pode prejudicar o desempenho dos modelos de raciocínio.)
Para ferramentas com carregamento adiado, inclua orientações detalhadas na descrição da função e mantenha a descrição do espaço de nomes concisa. O espaço de nomes ajuda o modelo a escolher o que carregar; a descrição da função ajuda a usar corretamente a ferramenta carregada.
Aplique as práticas recomendadas de engenharia de software.
Use enumerações e a estrutura dos objetos para evitar estados inválidos. Por exemplo, toggle_light(on: bool, off: bool) permite chamadas inválidas.
Passe no teste do estagiário. Um estagiário ou outra pessoa consegue usar a função corretamente apenas com as informações que você deu ao modelo? (Se não, quais perguntas essa pessoa faz? Adicione as respostas ao prompt.)
Reduza a carga sobre o modelo e use código sempre que possível.
Não faça o modelo preencher argumentos cujos valores você já conhece. Por exemplo, se você já tem um order_id obtido de um menu anterior, não inclua um parâmetro order_id. Em vez disso, defina submit_refund() sem parâmetros e passe o order_id no seu código.
Combine funções que são sempre chamadas em sequência. Por exemplo, se você sempre chama mark_location() após query_location(), basta mover a lógica de marcação para a chamada da função de consulta.
Mantenha pequeno o número de funções disponíveis inicialmente para obter maior precisão.
Avalie o desempenho com diferentes quantidades de funções.
Procure disponibilizar menos de 20 funções no início de cada turno ao mesmo tempo, embora essa seja apenas uma sugestão flexível.
Use a pesquisa de ferramentas para adiar o carregamento de partes grandes ou pouco usadas do seu conjunto de ferramentas, em vez de expor tudo desde o início.
Considere o ajuste fino para aumentar a precisão das chamadas de função quando houver muitas funções ou tarefas difíceis. (cookbook)
Uso de tokens
Internamente, as funções são inseridas na mensagem do sistema em uma sintaxe com a qual o modelo foi treinado. Isso significa que as definições de funções disponíveis para chamada contam para o limite de contexto do modelo e são cobradas como tokens de entrada. Se você atingir os limites de tokens, sugerimos limitar o número de funções carregadas inicialmente, encurtar as descrições quando possível ou usar a pesquisa de ferramentas para que as ferramentas com carregamento adiado sejam carregadas apenas quando necessário.
Também é possível usar o ajuste fino para reduzir o número de tokens usados se houver muitas funções definidas na sua especificação de ferramentas.
Tratamento de chamadas de função
Quando o modelo chama uma função, você deve executá-la e retornar o resultado. Como as respostas do modelo podem incluir nenhuma, uma ou várias chamadas, a prática recomendada é assumir que haverá várias.
A resposta contém um array de tool_calls, cada uma com um id (usado posteriormente para enviar o resultado da função) e um objeto function que contém um name e arguments codificados em JSON.
O array output da resposta contém uma entrada com o campo type definido como function_call. Cada entrada contém um call_id (usado posteriormente para enviar o resultado da função), um name e arguments codificados em JSON.
Se você estiver usando a pesquisa de ferramentas, também poderá ver itens tool_search_call e tool_search_output antes de um function_call. Depois que a função for carregada, trate a chamada de função da mesma forma mostrada aqui.
Execute as chamadas de função e acrescente os resultados
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16def call_function(name, arguments) case name when "get_weather" FunctionCallingExample.get_weather( arguments.fetch("latitude"), arguments.fetch("longitude") ) when "send_email" FunctionCallingExample.send_email( arguments.fetch("to"), arguments.fetch("body") ) else raise ArgumentError, "Unknown function: #{name}" endend
Formatação dos resultados
O resultado que você passa na mensagem function_call_output normalmente deve ser uma string, em um formato à sua escolha (JSON, códigos de erro, texto simples etc.). O modelo interpretará essa string conforme necessário.
"It's about 15°C in Paris, 18°C in Bogotá, and I've sent that email to Bob."
Configurações adicionais
Escolha de ferramentas
Por padrão, o modelo determina quando e quantas ferramentas usar. Você pode impor um comportamento específico com o parâmetro tool_choice.
Automático: (Padrão) Chama zero, uma ou várias funções. tool_choice: "auto"
Obrigatório: Chama uma ou mais funções.
tool_choice: "required"
Função forçada: Chama exatamente uma função específica.
tool_choice: {"type": "function", "name": "get_weather"}
Ferramentas permitidas: Restringe as chamadas de ferramentas que o modelo pode fazer a um subconjunto
das ferramentas disponíveis para ele.
Quando usar allowed_tools
Você pode configurar uma lista allowed_tools se quiser disponibilizar apenas
um subconjunto de ferramentas nas requisições ao modelo, sem modificar a lista de ferramentas enviada, para maximizar a economia com o cache de prompts.
Você também pode definir tool_choice como "none" para simular o comportamento de não enviar nenhuma função.
Quando você usa a pesquisa de ferramentas, tool_choice continua se aplicando às ferramentas que podem ser chamadas naquele momento do turno. Isso é especialmente útil depois de carregar um subconjunto de ferramentas, quando você quer limitar o modelo a esse subconjunto.
Chamada de funções em paralelo
Nos modelos compatíveis a partir do GPT-5, as funções podem ser chamadas em paralelo
quando ferramentas integradas também estão disponíveis. As ferramentas
integradas não podem ser incluídas em um lote de chamadas de funções em paralelo.
O modelo pode optar por chamar várias funções em um único turno. Você pode impedir isso definindo parallel_tool_calls como false, o que garante que sejam chamadas exatamente zero ou uma ferramenta.
Observação: Atualmente, se você estiver usando um modelo com ajuste fino e ele chamar várias funções em um turno, o modo estrito será desativado para essas chamadas.
Observação sobre gpt-4.1-nano-2025-04-14: Esta versão de gpt-4.1-nano pode, às vezes, incluir várias chamadas à mesma ferramenta se as chamadas de ferramentas em paralelo estiverem ativadas. Recomendamos desativar esse recurso ao usar esta versão.
Modo estrito
Definir strict como true garante que as chamadas de funções sigam o esquema da função de forma confiável, em vez de apenas tentarem segui-lo sem garantia de conformidade. Recomendamos sempre ativar o modo estrito.
Internamente, o modo estrito usa nosso recurso de saídas estruturadas e, por isso, impõe alguns requisitos:
additionalProperties deve ser definido como false para cada objeto em parameters.
Todos os campos em properties devem ser marcados como required.
Você pode indicar campos opcionais adicionando null como uma opção de type (veja o exemplo abaixo).
Se você enviar strict: true e seu esquema não atender aos requisitos acima,
a requisição será rejeitada com detalhes sobre as restrições ausentes. Se
você omitir strict, o comportamento padrão dependerá da API: as requisições à Responses tentarão
normalizar seu esquema para o modo estrito quando possível e recorrerão
à chamada de funções sem modo estrito, sem garantia de conformidade, se não for possível tornar o esquema
compatível com o modo estrito. Quando isso acontecer, a ferramenta na resposta mostrará
strict: false. As requisições à Chat Completions continuam sem modo estrito por padrão. Para
desativar o modo estrito na Responses e manter a chamada de funções sem modo estrito e sem garantia de conformidade,
defina explicitamente strict: false.
Modo estrito ativado
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24{"type": "function","function": {"name": "get_weather","description": "Retrieves current weather for the given location.","strict": true,"parameters": {"type": "object","properties": {"location": {"type": "string","description": "City and country e.g. Bogotá, Colombia" },"units": {"type": ["string", "null"],"enum": ["celsius", "fahrenheit"],"description": "Units the temperature will be returned in." } },"required": ["location", "units"],"additionalProperties": false } }}
Modo estrito desativado
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22{"type": "function","function": {"name": "get_weather","description": "Retrieves current weather for the given location.","parameters": {"type": "object","properties": {"location": {"type": "string","description": "City and country e.g. Bogotá, Colombia" },"units": {"type": "string","enum": ["celsius", "fahrenheit"],"description": "Units the temperature will be returned in." } },"required": ["location"], } }}
Modo estrito ativado
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22{"type": "function","name": "get_weather","description": "Retrieves current weather for the given location.","strict": true,"parameters": {"type": "object","properties": {"location": {"type": "string","description": "City and country e.g. Bogotá, Colombia" },"units": {"type": ["string", "null"],"enum": ["celsius", "fahrenheit"],"description": "Units the temperature will be returned in." } },"required": ["location", "units"],"additionalProperties": false }}
Modo estrito desativado
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20{"type": "function","name": "get_weather","description": "Retrieves current weather for the given location.","parameters": {"type": "object","properties": {"location": {"type": "string","description": "City and country e.g. Bogotá, Colombia" },"units": {"type": "string","enum": ["celsius", "fahrenheit"],"description": "Units the temperature will be returned in." } },"required": ["location"], }}
Todos os esquemas gerados no
playground têm o modo estrito ativado.
Embora recomendemos ativar o modo estrito, ele tem algumas limitações:
Alguns recursos de esquemas JSON não são compatíveis. (Veja os esquemas compatíveis.)
Especificamente para modelos com ajuste fino:
Os esquemas passam por processamento adicional na primeira requisição e depois são armazenados em cache. Se seus esquemas variarem entre as requisições, isso poderá aumentar a latência.
Os esquemas são armazenados em cache para melhorar o desempenho e não são elegíveis para zero retenção de dados.
Streaming
O streaming pode ser usado para mostrar o progresso, indicando qual função é chamada enquanto o modelo preenche seus argumentos e até exibindo os argumentos em tempo real.
O streaming de chamadas de funções é muito semelhante ao streaming de respostas comuns: você define stream como true e recebe fragmentos com objetos delta.
Streaming de chamadas de funções
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40import { OpenAI } from "openai";const openai = new OpenAI();const tools = [ { type: "function", function: { name: "get_weather", description: "Get current temperature for a given location.", parameters: { type: "object", properties: { location: { type: "string", description: "City and country e.g. Bogotá, Colombia", }, }, required: ["location"], additionalProperties: false, }, strict: true, }, },];const stream = await openai.chat.completions.create({ model: "gpt-5.6", messages: [ { role: "user", content: "What's the weather like in Paris today?" }, ], tools, stream: true, store: true,});for await (const chunk of stream) { const delta = chunk.choices[0].delta; console.log(delta.tool_calls);}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36from openai import OpenAIclient = OpenAI()tools = [ {"type": "function","function": {"name": "get_weather","description": "Get current temperature for a given location.","parameters": {"type": "object","properties": {"location": {"type": "string","description": "City and country e.g. Bogotá, Colombia", } },"required": ["location"],"additionalProperties": False, },"strict": True, }, }]stream = client.chat.completions.create(model="gpt-5.6",messages=[{"role": "user", "content": "What's the weather like in Paris today?"}],tools=tools,stream=True,)for chunk in stream: delta = chunk.choices[0].deltaprint(delta.tool_calls)
O streaming pode ser usado para mostrar o progresso, indicando qual função é chamada enquanto o modelo preenche seus argumentos e até exibindo esses argumentos em tempo real.
O streaming de chamadas de função é muito semelhante ao streaming de respostas comuns: você define stream como true e recebe diferentes objetos event.
No entanto, em vez de agregar os fragmentos em uma única string content, você os agrega em um objeto JSON arguments codificado.
Quando o modelo chama uma ou mais funções, um evento do tipo response.output_item.added é emitido para cada chamada de função. Esse evento contém os seguintes campos:
Campo
Descrição
response_id
O ID da resposta à qual a chamada de função pertence
output_index
O índice do item de saída na resposta. Ele representa as chamadas de função individuais na resposta.
item
O item da chamada de função em andamento, que inclui os campos name, arguments e id
Em seguida, você recebe uma série de eventos do tipo response.function_call_arguments.delta que contêm o delta do campo arguments. Esses eventos contêm os seguintes campos:
Campo
Descrição
response_id
O ID da resposta à qual a chamada de função pertence
item_id
O ID do item da chamada de função ao qual o delta pertence
output_index
O índice do item de saída na resposta. Ele representa as chamadas de função individuais na resposta.
delta
O delta do campo arguments.
Veja abaixo um trecho de código que demonstra como agregar os deltas em um objeto tool_call final.
Quando o modelo termina de chamar as funções, um evento do tipo response.function_call_arguments.done é emitido. Esse evento contém a chamada de função completa, incluindo os seguintes campos:
Campo
Descrição
response_id
O ID da resposta à qual a chamada de função pertence
output_index
O índice do item de saída na resposta. Ele representa as chamadas de função individuais na resposta.
item
O item da chamada de função, que inclui os campos name, arguments e id.
Ferramentas personalizadas
As ferramentas personalizadas funcionam de forma muito semelhante às ferramentas de função baseadas em esquemas JSON. Porém, em vez de receber instruções explícitas sobre a entrada exigida pela ferramenta, o modelo pode enviar uma string arbitrária como entrada para ela. Isso é útil para evitar encapsular uma resposta em JSON sem necessidade ou para aplicar uma gramática personalizada à resposta (mais detalhes abaixo).
O exemplo de código a seguir mostra como criar uma ferramenta personalizada que espera receber, como resposta, uma string de texto contendo código Python.
Exemplo de chamada de ferramenta personalizada
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16import OpenAI from "openai";const client = new OpenAI();const response = await client.responses.create({ model: "gpt-6-astra", input: "Use the code_exec tool to print hello world to the console.", tools: [ { type: "custom", name: "code_exec", description: "Executes arbitrary Python code.", }, ],});console.log(response.output);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16from openai import OpenAIclient = OpenAI()response = client.responses.create(model="gpt-6-astra",input="Use the code_exec tool to print hello world to the console.",tools=[ {"type": "custom","name": "code_exec","description": "Executes arbitrary Python code.", } ],)print(response.output)
Assim como antes, o array output contém uma chamada de ferramenta gerada pelo modelo. Desta vez, porém, a entrada da chamada de ferramenta é fornecida como texto simples.
Uma gramática livre de contexto (CFG) é um conjunto de regras que definem como produzir texto válido em um determinado formato. Para ferramentas personalizadas, você pode fornecer uma CFG que restrinja o texto que o modelo envia como entrada para a ferramenta.
Você pode fornecer uma CFG personalizada usando o parâmetro grammar ao configurar uma ferramenta personalizada. Atualmente, oferecemos suporte a duas formas de sintaxe de CFG para definir gramáticas: lark e regex.
As gramáticas são especificadas usando uma variação de Lark. A amostragem do modelo é restringida pelo LLGuidance. Alguns recursos do Lark não são compatíveis:
Asserções de contexto nas expressões regulares do analisador léxico
Modificadores não gulosos (*?, +?, ??) nas expressões regulares do analisador léxico
Prioridades dos terminais
Modelos
Importações (exceto a importação integrada %import common)
Diretivas %declare
Recomendamos usar o Lark IDE para experimentar gramáticas personalizadas.
Limite a complexidade da gramática
Limite sua gramática às regras e aos padrões de que sua ferramenta precisa. A API da OpenAI pode retornar um erro se a gramática for complexa demais. Por isso, verifique se a gramática desejada é compatível antes de usá-la na API.
Aperfeiçoar gramáticas Lark pode ser difícil. Gramáticas menos complexas funcionam com mais confiabilidade, enquanto as mais complexas costumam exigir ajustes sucessivos na própria definição da gramática, no prompt e na descrição da ferramenta para garantir que o modelo não opere fora da distribuição.
Padrões corretos e incorretos
Correto (um único terminal com limites definidos):
NÃO faça isto (dividir entre regras/terminais). Essa abordagem tenta fazer com que as regras dividam o texto livre entre terminais. O analisador léxico fará a correspondência dos trechos de texto livre de forma gulosa, e você perderá o controle:
Regras em minúsculas não influenciam como os terminais são extraídos da entrada; somente as definições dos terminais fazem isso. Quando precisar de “texto livre entre âncoras”, use um único terminal com uma expressão regular que abranja tudo, para que o analisador léxico faça a correspondência exatamente uma vez, com a estrutura desejada.
Terminais e regras
O Lark usa terminais para os tokens do analisador léxico (por convenção, UPPERCASE) e regras para as produções do analisador sintático (por convenção, lowercase). A maneira mais prática de se manter dentro do subconjunto compatível e evitar surpresas é manter a gramática explícita, evitar complexidade desnecessária e usar terminais e regras com uma separação clara de responsabilidades.
O analisador léxico é executado antes do analisador sintático
O analisador léxico faz a correspondência dos terminais de forma gulosa (a correspondência mais longa prevalece) antes que qualquer lógica das regras da CFG seja aplicada. Se você tentar “moldar” um terminal dividindo-o entre várias regras, essas regras não poderão orientar o analisador léxico; somente as expressões regulares dos terminais poderão fazer isso.
Prefira um único terminal ao extrair texto de trechos em formato livre
Se você precisar reconhecer um padrão inserido em um texto arbitrário (por exemplo, linguagem natural com “qualquer coisa” entre âncoras), expresse esse padrão como um único terminal. Não tente intercalar terminais de texto livre com regras do analisador sintático; o analisador léxico guloso não respeitará os limites pretendidos, e é muito provável que o modelo opere fora da distribuição.
Use regras para combinar tokens distintos
As regras são ideais para combinar terminais explicitamente delimitados (números, palavras-chave, pontuação) em estruturas maiores. Elas não são a ferramenta adequada para restringir “o conteúdo entre” dois terminais.
Mantenha os terminais com propósito específico, limites definidos e estrutura autossuficiente
Prefira classes de caracteres explícitas e quantificadores limitados ({0,10}, em vez de usar * sem limites por toda parte). Se precisar de “qualquer texto até um ponto final”, prefira algo como /[^.\n]{0,10}*\./ em vez de /.+\./ para evitar crescimento descontrolado.
Use regras para combinar tokens, não para controlar o funcionamento interno das expressões regulares
Exemplo de uso adequado de regras:
start: exprNUMBER: /[0-9]+/PLUS: "+"MINUS: "-"expr: term (("+"|"-") term)*term: NUMBER
Trate os espaços em branco explicitamente
Não dependa de diretivas %ignore sem limites definidos. Usar diretivas de ignorar sem limites pode tornar a gramática complexa demais e/ou fazer com que o modelo saia da distribuição. Prefira inserir terminais explícitos em todos os pontos em que espaços em branco forem permitidos.
Solução de problemas
Se a API rejeitar a gramática por ser complexa demais, simplifique as regras e os terminais e remova as diretivas %ignore sem limites definidos.
Se as ferramentas personalizadas forem chamadas com tokens inesperados, confirme se os terminais não se sobrepõem e verifique o comportamento guloso do analisador léxico.
Quando o modelo sai da distribuição (isso se manifesta em saídas excessivamente longas ou repetitivas, sintaticamente válidas, mas semanticamente incorretas):
Torne a gramática mais restritiva.
Ajuste o prompt (adicione exemplos few-shot) e a descrição da ferramenta (explique a gramática e instrua o modelo a raciocinar e segui-la).
Experimente um esforço de raciocínio maior (por exemplo, aumente de médio para alto).
CFG com expressões regulares
Exemplo de gramática livre de contexto com expressões regulares
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25import OpenAI from "openai";const client = new OpenAI();const grammar = "^(?P<month>January|February|March|April|May|June|July|August|September|October|November|December)\\s+(?P<day>\\d{1,2})(?:st|nd|rd|th)?\\s+(?P<year>\\d{4})\\s+at\\s+(?P<hour>0?[1-9]|1[0-2])(?P<ampm>AM|PM)$";const response = await client.responses.create({ model: "gpt-6-astra", input: "Use the timestamp tool to save a timestamp for August 7th 2025 at 10AM.", tools: [ { type: "custom", name: "timestamp", description: "Saves a timestamp in date + time in 24-hr format.", format: { type: "grammar", syntax: "regex", definition: grammar, }, }, ],});console.log(response.output);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23from openai import OpenAIclient = OpenAI()grammar =r"^(?P<month>January|February|March|April|May|June|July|August|September|October|November|December)\s+(?P<day>\d{1,2})(?:st|nd|rd|th)?\s+(?P<year>\d{4})\s+at\s+(?P<hour>0?[1-9]|1[0-2])(?P<ampm>AM|PM)$"response = client.responses.create(model="gpt-6-astra",input="Use the timestamp tool to save a timestamp for August 7th 2025 at 10AM.",tools=[ {"type": "custom","name": "timestamp","description": "Saves a timestamp in date + time in 24-hr format.","format": {"type": "grammar","syntax": "regex","definition": grammar, }, } ],)print(response.output)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28package mainimport ( "context" "fmt" "github.com/openai/openai-go/v3" "github.com/openai/openai-go/v3/responses" "github.com/openai/openai-go/v3/shared")func main() { client := openai.NewClient() grammar := `^(?P<month>January|February|March|April|May|June|July|August|September|October|November|December)\s+(?P<day>\d{1,2})(?:st|nd|rd|th)?\s+(?P<year>\d{4})\s+at\s+(?P<hour>0?[1-9]|1[0-2])(?P<ampm>AM|PM)$` tool := responses.ToolParamOfCustom("timestamp") tool.OfCustom.Description = openai.String("Saves a timestamp in date and time format.") tool.OfCustom.Format = shared.CustomToolInputFormatParamOfGrammar(grammar, "regex") response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{ Model: "gpt-6-astra", Input: responses.ResponseNewParamsInputUnion{OfString: openai.String("Use the timestamp tool to save a timestamp for August 7th 2025 at 10AM.")}, Tools: []responses.ToolUnionParam{tool}, }) if err != nil { panic(err) } fmt.Println(response.Output)}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27import com.openai.client.OpenAIClient;import com.openai.client.okhttp.OpenAIOkHttpClient;import com.openai.models.CustomToolInputFormat;import com.openai.models.responses.CustomTool;import com.openai.models.responses.ResponseCreateParams;String grammar = "^(January|February|March|April|May|June|July|August|September|October|November|December) " + "\\d{1,2}(st|nd|rd|th)? \\d{4} at (0?[1-9]|1[0-2])(AM|PM)$";ResponseCreateParams params = ResponseCreateParams.builder() .model("gpt-6-astra") .input("Use timestamp to save August 7th 2025 at 10AM.") .addTool( CustomTool.builder() .name("timestamp") .description("Saves a timestamp in date and time format.") .format( CustomToolInputFormat.Grammar.builder() .syntax(CustomToolInputFormat.Grammar.Syntax.REGEX) .definition(grammar) .build()) .build()) .build();client.responses().create(params).output().forEach(System.out::println);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22require "openai"client = OpenAI::Client.newgrammar = "^(January|February|March|April|May|June|July|August|September|October|November|December) \\d{1,2}(st|nd|rd|th)? \\d{4} at (0?[1-9]|1[0-2])(AM|PM)$"response = client.responses.create( model: "gpt-6-astra", input: "Use timestamp to save August 7th 2025 at 10AM.", tools: [ { type: :custom, name: "timestamp", description: "Saves a timestamp in date and time format.", format: { type: :grammar, syntax: :regex, definition: grammar } } ])puts(response.output)
A saída da ferramenta deverá então seguir a CFG com expressões regulares que você definiu:
Alguns recursos de expressões regulares não são compatíveis:
Asserções de contexto
Modificadores não gulosos (*?, +?, ??)
Conceitos principais e práticas recomendadas
O padrão deve estar em uma única linha
Se precisar corresponder a uma quebra de linha na entrada, use a sequência de escape \n. Não use o modo detalhado/estendido, que permite distribuir padrões por várias linhas.
Forneça a expressão regular como uma string contendo apenas o padrão