Com chamadas assíncronas, o modelo pode chamar uma ferramenta e continuar trabalhando sem esperar pelo resultado. Use esse recurso para iniciar consultas demoradas com antecedência, responder às partes independentes de uma solicitação e enviar os resultados assim que estiverem disponíveis no aplicativo.
Como funcionam as ferramentas assíncronas
Uma chamada de função comum interrompe o turno do modelo até que a ferramenta responda. Defina async: true na definição de uma função ou de uma ferramenta personalizada para que o modelo possa continuar trabalhando após fazer a chamada, antes que o aplicativo retorne o resultado.
Seu aplicativo continua responsável por executar a ferramenta. As ferramentas assíncronas não transferem a execução para a OpenAI nem gerenciam as tarefas em segundo plano do aplicativo.
Esse recurso difere do modo em segundo plano, que gera respostas de forma assíncrona. Com chamadas assíncronas de ferramentas, o modelo continua trabalhando enquanto o aplicativo executa uma ferramenta.
Quando uma tarefa terminar, inclua o resultado em uma solicitação posterior à API Responses. Use o call_id original da API para associar o resultado à chamada correspondente.
| Tipo de ferramenta | Item de chamada | Item de saída |
|---|---|---|
| Função | function_call |
function_call_output |
| Personalizada | custom_tool_call |
custom_tool_call_output |
Chame uma ferramenta assíncrona
Adicione async: true à definição da ferramenta. Os itens de chamada correspondentes em response.output incluem async: true.
import json
from concurrent.futures import ThreadPoolExecutor
from openai import OpenAI
from openai.types.responses import FunctionToolParam
def get_weather(city):
# Demo data. Replace this function with your weather service.
weather = {
"Paris": {
"city": "Paris",
"temperature_c": 22,
"condition": "Clear",
"source": "demo weather snapshot",
}
}
return weather[city]
worker = ThreadPoolExecutor()
def main():
client = OpenAI()
model = "gpt-6-astra"
tools: list[FunctionToolParam] = [
{
"type": "function",
"name": "get_weather",
"description": "Read the demo weather snapshot for a city.",
"async": True,
"strict": True,
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
"additionalProperties": False,
},
},
]
instructions = (
"Start the weather lookup and answer the independent packing "
"question without waiting. Use the actual tool result when it "
"arrives; never invent it. Identify the weather as demo data."
)
response = client.responses.create(
model=model,
tools=tools,
instructions=instructions,
input=(
"Check the demo weather in Paris. Meanwhile, "
"list three essentials for any city trip."
),
)
call = next(item for item in response.output if item.type == "function_call")
arguments = json.loads(call.arguments)
if call.name != "get_weather" or arguments != {"city": "Paris"}:
raise ValueError("Expected a weather lookup for Paris")
latest_response_id = response.id
if call.async_:
job = worker.submit(get_weather, **arguments)
print(response.output_text)
# Independent work or conversation turns can happen here.
# Update latest_response_id after each continuation.
result = job.result()
else:
result = get_weather(**arguments)
response = client.responses.create(
model=model,
tools=tools,
instructions=instructions,
previous_response_id=latest_response_id,
input=[
{
"type": "function_call_output",
"call_id": call.call_id,
"output": json.dumps(result),
},
],
)
print(response.output_text)
if __name__ == "__main__":
try:
main()
finally:
worker.shutdown(wait=True)A resposta pode conter tanto a chamada assíncrona quanto uma resposta ao usuário. Se houver outros turnos na conversa antes que a tarefa termine, atualize latest_response_id para continuar a partir da resposta mais recente e mantenha o call_id original da ferramenta.
Com streaming, você pode iniciar a tarefa mais cedo. Assim que receber o item de chamada completo, inicie a tarefa e continue lendo o restante da resposta.
Adicione uma ferramenta de espera
Com uma ferramenta de espera, o modelo decide quando precisa de um resultado pendente. Por exemplo, ele pode iniciar duas consultas de preço, trabalhar em algo que não dependa delas e esperar pelos resultados só quando for comparar os preços.
Adicione um argumento task_handle a cada ferramenta assíncrona. O modelo atribui um identificador a cada chamada, e o aplicativo associa esse identificador ao call_id original da API e à tarefa em execução. Use identificadores únicos em toda a conversa, inclusive para tarefas concluídas e consultas repetidas.
Defina a ferramenta de espera como uma função síncrona comum. Omita async ou defina seu valor como false. Seu aplicativo define o schema e o comportamento da ferramenta. wait_for_tasks não é uma ferramenta integrada à API Responses.
Use as definições a seguir no array tools da solicitação.
[
{
"type": "function",
"name": "lookup_price",
"async": true,
"description": "Look up a product price in the background. Choose a fresh task_handle unique within this conversation, including completed tasks.",
"strict": true,
"parameters": {
"type": "object",
"properties": {
"sku": { "type": "string" },
"task_handle": { "type": "string" }
},
"required": ["sku", "task_handle"],
"additionalProperties": false
}
},
{
"type": "function",
"name": "wait_for_tasks",
"description": "Wait for selected tasks whose results you need. Pass a nonempty list of distinct task_handles from your earlier async tool calls. Results arrive on their original calls; this tool returns status only. Do not wait again for results that have already arrived.",
"strict": true,
"parameters": {
"type": "object",
"properties": {
"task_handles": {
"type": "array",
"items": { "type": "string" }
}
},
"required": ["task_handles"],
"additionalProperties": false
}
}
]
Registre cada tarefa
Registre e inicie cada tarefa antes de processar uma chamada de espera que dependa dela. As chamadas podem chegar juntas ou em respostas diferentes. Os itens de saída do exemplo a seguir mostram duas chamadas que iniciam tarefas e uma chamada de espera que depende das duas.
[
{
"type": "function_call",
"name": "lookup_price",
"async": true,
"call_id": "call_widget",
"arguments": "{\"sku\":\"WIDGET\",\"task_handle\":\"widget_price_1\"}"
},
{
"type": "function_call",
"name": "lookup_price",
"async": true,
"call_id": "call_gadget",
"arguments": "{\"sku\":\"GADGET\",\"task_handle\":\"gadget_price_1\"}"
},
{
"type": "function_call",
"name": "wait_for_tasks",
"call_id": "call_wait",
"arguments": "{\"task_handles\":[\"widget_price_1\",\"gadget_price_1\"]}"
}
]
O aplicativo mantém um registro que associa cada identificador à chamada original e à tarefa em execução.
| Identificador da tarefa | ID da chamada original | Tarefa |
|---|---|---|
widget_price_1 |
call_widget |
Consulta de preço de WIDGET |
gadget_price_1 |
call_gadget |
Consulta de preço de GADGET |
Mantenha esse registro durante toda a conversa para evitar que um identificador de tarefa concluída seja reutilizado.
Envie os resultados antes do status da chamada de espera
Localize no registro as tarefas correspondentes aos identificadores solicitados e aguarde apenas essas tarefas. Envie o resultado de cada tarefa recém-concluída usando o call_id original. Em seguida, envie o status usando o call_id da própria chamada de espera. Assim, o modelo terá os resultados quando retomar o trabalho.
Por exemplo, envie os itens de saída a seguir no array input da próxima solicitação. Os preços são ilustrativos.
[
{
"type": "function_call_output",
"call_id": "call_widget",
"output": "{\"task_handle\":\"widget_price_1\",\"price_cents\":1200,\"currency\":\"USD\"}"
},
{
"type": "function_call_output",
"call_id": "call_gadget",
"output": "{\"task_handle\":\"gadget_price_1\",\"price_cents\":1500,\"currency\":\"USD\"}"
},
{
"type": "function_call_output",
"call_id": "call_wait",
"output": "{\"status\":\"completed\",\"completed_task_handles\":[\"widget_price_1\",\"gadget_price_1\"]}"
}
]
Defina previous_response_id como o ID da resposta mais recente e inclua as ferramentas e as instruções na solicitação de continuação. O aplicativo também pode enviar os resultados à medida que ficarem disponíveis, sem uma chamada de espera. Use a ferramenta de espera apenas quando o próximo passo do modelo depender de resultados que ainda não chegaram.
Adicione uma ferramenta para fazer perguntas ao usuário
Uma ferramenta assíncrona pode fazer uma pergunta ao usuário enquanto o modelo continua trabalhando em tarefas independentes. Por exemplo, o modelo pode perguntar a quem se destina um relatório, reunir informações enquanto o usuário responde e usar a resposta para adaptar o relatório ao público.
Defina uma função com async: true para pedir uma informação que falta ou perguntar sobre uma preferência. O aplicativo exibe a pergunta, recebe a resposta do usuário e a retorna como resultado da ferramenta. Seu aplicativo define o schema e o comportamento da ferramenta. request_user_input_async não é uma ferramenta integrada à API Responses.
Adicione a definição a seguir ao array tools da solicitação, junto com wait_for_tasks.
{
"type": "function",
"name": "request_user_input_async",
"async": true,
"description": "Ask the user for missing information or a preference. Choose a fresh task_handle unique within this conversation, including completed tasks. Continue independent work while the answer is pending. Use wait_for_tasks when your next step depends on the answer.",
"strict": true,
"parameters": {
"type": "object",
"properties": {
"question": { "type": "string" },
"task_handle": { "type": "string" }
},
"required": ["question", "task_handle"],
"additionalProperties": false
}
}
Exiba a pergunta
Ao receber o item de chamada completo, registre o task_handle da pergunta e o call_id original. Em seguida, exiba a pergunta ao usuário. No item de saída a seguir, o modelo pergunta a quem se destina o relatório.
{
"type": "function_call",
"name": "request_user_input_async",
"async": true,
"call_id": "call_audience",
"arguments": "{\"question\":\"Who is the report for: executives or engineers?\",\"task_handle\":\"report_audience_1\"}"
}
Mantenha a pergunta pendente no mesmo registro que a ferramenta de espera usa. Enquanto o usuário responde, continue lendo a resposta do modelo. Não conclua a chamada da ferramenta com uma confirmação de que a pergunta foi exibida. O resultado da chamada é a resposta do usuário.
Retorne a resposta do usuário
Quando o usuário responder, envie a resposta usando o call_id original da pergunta. Por exemplo, inclua o item de saída a seguir no array input da próxima solicitação.
[
{
"type": "function_call_output",
"call_id": "call_audience",
"output": "{\"task_handle\":\"report_audience_1\",\"answer\":\"Executives\"}"
}
]
Defina previous_response_id como o ID da resposta mais recente e inclua as ferramentas e as instruções na solicitação de continuação. Se o modelo chamou wait_for_tasks para aguardar report_audience_1, envie a resposta antes do status da chamada de espera, como no exemplo da ferramenta de espera.
A execução assíncrona não mantém uma resposta do modelo aberta até que o usuário responda. Oriente o modelo a continuar trabalhando em tarefas independentes e a aguardar antes de executar uma etapa que dependa da resposta do usuário. Se o aplicativo permitir que o usuário dispense a pergunta ou se houver um limite de tempo para responder, retorne um resultado que indique explicitamente a ausência de resposta para que o modelo possa decidir como prosseguir.
Compatibilidade
O GPT-6 Astra e os modelos posteriores oferecem suporte a chamadas assíncronas de ferramentas.
A execução assíncrona se aplica às ferramentas do tipo função e às ferramentas personalizadas que o aplicativo executa. Ela não se aplica às ferramentas integradas hospedadas. Faça chamadas diretas às ferramentas. Não configure ferramentas assíncronas para chamadas programáticas de ferramentas.
No modo multiagente, não combine ferramentas assíncronas com chamadas de ferramentas em paralelo.