Chamada de função assíncrona com a API Gemini Live

Ao criar agentes de voz em tempo real, algumas chamadas de função podem bloquear a execução do modelo, o que faz com que o stream de áudio fique em silêncio e o usuário precise esperar. Com a API Gemini Live, todas as chamadas de função são não bloqueadoras por padrão, o que permite executar funções em paralelo com o fluxo principal da conversa. Esse processo é chamado de chamada de função assíncrona. Seu back-end pode processar tarefas pesadas, como pesquisar preços de voos em tempo real ou consultar APIs externas complexas em segundo plano, enquanto o modelo continua ouvindo, falando e conversando naturalmente com o usuário. A API Gemini Live permite que as chamadas de função sejam processadas em segundo plano sem interromper a interação do usuário com o modelo, possibilitando interações mais fluidas e em tempo real.

Com a chamada de função assíncrona, é possível concluir tarefas como agendar consultas, definir lembretes ou buscar dados sem pausar a conversa. Por exemplo, um usuário pode pedir para reservar um voo e imediatamente solicitar informações meteorológicas enquanto a reserva é processada em segundo plano.

Exemplo de chamada de função assíncrona

Este exemplo mostra um usuário reservando um voo e perguntando as horas em Nova York enquanto a função book_ticket é executada de forma assíncrona em segundo plano:

User: Please book the 2:00 PM flight to New York for me.

Model: function_call: {name: "book_ticket"}
//(The "book_ticket" function call is sent to the client.)
//(Right after the "book_ticket" function call is received, the client sends a text message to the model: "repeat this sentence 'I'm booking your ticket now, please wait.'")
//(The client runs the function call asynchronously in the background.)
Model: I'm booking your ticket now, please wait.

User: What is the current time in New York?

Model: The current time in New York is 12:00pm.

//(Once the book_ticket function finishes, the client sends the result.)
Function_response: {name: "book_ticket", response: {booking_status: "booked"}}

Model: Your flight has been booked. Expect a confirmation text on your phone within 5 minutes.

Implementar chamadas de função assíncronas

Esta seção oferece uma série de exemplos usando a versão em Python do SDK da Agent Platform para criar uma arquitetura altamente responsiva e simultânea que usa a capacidade de chamada de função assíncrona da API Gemini Live. Os exemplos são divididos nas seguintes tarefas:

Defina suas ferramentas

A chamada de função assíncrona é ativada no nível do modelo. Assim, é possível especificar quais ferramentas você quer usar na configuração da solicitação, como faria com qualquer API Gemini padrão em uma chamada da plataforma de agentes do Gemini Enterprise. Isso permite que o modelo continue conversando enquanto sua ferramenta é executada:

from google import genai
from google.genai import types

# 1. A tool that takes a long time to execute
search_live_flights = {
    "name": "search_live_flights",
    "description": "Searches airlines for current flight prices. Can take up to 10 seconds."
}

# 2. A tool that executes instantly
get_current_weather = {
    "name": "get_current_weather",
    "description": "Gets the current weather for a given city."
}

tools = [{"function_declarations": [search_live_flights, get_current_weather]}]

Processar chamadas de função do fluxo de mensagens

Quando um ou mais funções precisam ser chamadas pelo modelo, a API Gemini Live envia um evento tool_call pelo fluxo de mensagens em tempo real.

O back-end não pode bloquear o fluxo, porque o modelo espera continuar em execução. Quando você recebe uma chamada para uma função lenta (como search_live_flights), é necessário transmiti-la para um worker em segundo plano. Se você usar um await diretamente no loop de mensagens principal para uma tarefa de 10 segundos, a conexão será congelada. Tarefas rápidas (como get_current_weather) podem ser aguardadas com segurança.

import asyncio

async def handle_stream(session):
    async for response in session.receive():
        # Check if the model is asking to use a tool
        if response.tool_call is not None:
            for fc in response.tool_call.function_calls:

                if fc.name == "search_live_flights":
                    # Pass to a background task so we don't block the receive loop!
                    asyncio.create_task(background_flight_search(fc.id, fc.args, session))

                elif fc.name == "get_current_weather":
                    # Instant lookups can be safely awaited directly
                    await instant_weather_lookup(fc.id, fc.args, session)

Gerenciar as expectativas dos usuários

Para gerenciar as expectativas durante chamadas de função assíncronas de longa duração, é recomendável que o cliente inicie uma mensagem de texto. Essa mensagem precisa solicitar que o sistema informe ao usuário que a solicitação está sendo processada e pedir paciência. Por exemplo, depois que uma chamada de função é recebida pelo cliente, ele pode enviar uma mensagem de texto ao modelo, como: "repita esta frase: 'Estou reservando sua passagem agora, aguarde.'".

A caixa de diálogo de exemplo a seguir mostra essa troca:

User: Please book the 2:00 PM flight to New York for me.
Model: function_call: {name: "book_ticket"}
//(The "book_ticket" function call is sent to the client.)
//(Right after the "book_ticket" function call is received, the client sends a text message to the model: "repeat this sentence 'I'm booking your ticket now, please wait.'")
//(The client runs the function call asynchronously in the background.)
Model: I'm booking your ticket now, please wait.
User: What is the current time in New York?
Model: The current time in New York is 12:00pm.
//(Once the "book_ticket" function call finishes, the client sends in the response.)
Function_response: {name: "book_ticket", response: {booking_status: "booked"}}
Model: Your flight has been booked. Expect a confirmation text on your phone within 5 minutes.

Essa estratégia de mensagens proativas tem os seguintes benefícios:

  • Informa o usuário sobre as operações atuais do sistema, gerenciando as expectativas durante chamadas de função de longa duração.
  • Reduz a frequência de comandos curtos e redundantes do usuário, como "olá?" ou "você está aí?". Isso geralmente acontece durante longos períodos de silêncio do sistema enquanto as chamadas de função assíncronas estão sendo processadas. Isso pode minimizar o risco de chamadas de função duplicadas acionadas por essas consultas repetidas do usuário.
  • Fornecer um comando extra do sistema pode diminuir a probabilidade de criar chamadas duplicadas em interações subsequentes.

Lidar com chamadas de função duplicadas

Há uma pequena chance de o modelo gerar chamadas de função duplicadas antes de receber uma resposta para a primeira chamada. Se o caso de uso permitir, o aplicativo poderá ignorar chamadas de função duplicadas se uma resposta para a mesma chamada ainda estiver pendente.

O exemplo a seguir mostra como um cliente pode ignorar uma chamada de função duplicada:

User: Please book the 2:00 PM flight to New York for me.

Model: function_call: {name: "book_ticket"}
//(The "book_ticket" function call is sent to the client. It is running asynchronously in the background.)

User: What is the current time in New York?
Model: The current time in New York is 12:00pm. + function_call: {name: "book_ticket"}
//(The duplicated "book_ticket" can be ignored by the client since the response for the first "book_ticket" has not been sent to the model yet.)

//(The first "book_ticket" function call finishes, and client sends in the response.)
Function_response: {name: "book_ticket", response: {booking_status: "booked"}}

Model: Your flight has been booked. Expect a confirmation text on your phone within 5 minutes.

Processar respostas de funções assíncronas

Quando uma chamada de função assíncrona é concluída, o aplicativo envia o resultado ao modelo em um function_response. Enquanto o back-end processa uma chamada de função, como a pesquisa de voos, o usuário pode fazer uma pergunta completamente diferente ao modelo, como: Como está o clima em Londres?. O modelo vai responder à solicitação em tempo real, em paralelo com a execução da chamada de função. Como o usuário pode estar em uma interação contínua com o modelo quando a execução da função for concluída, é possível especificar uma política que defina como o modelo deve lidar com essa resposta recebida. Você pode especificar uma das seguintes políticas:

Para especificar uma política, inclua o campo scheduling no payload function_response:

{
  "name": "book_ticket",
  "scheduling": "WHEN_IDLE",
  "response": {
    "booking_status": "booked"
  }
}

Se você omitir o campo scheduling, a API Gemini Live usará o método original para processar respostas de função por compatibilidade com versões anteriores.

O exemplo em Python a seguir mostra como formatar e enviar um function_response com scheduling="WHEN_IDLE" para aguardar uma pausa natural na conversa antes de anunciar os resultados:

aearcync def background_flight_search(call_id, args, session):
    # 1. Simulate a slow API call taking 5 seconds
    await asyncio.sleep(5)
    flight_data = ["Air Canada AC758: $350", "WestJet WS12: $290"]

    # 2. Format the response
    function_response = types.FunctionResponse(
        id=call_id,
        name="search_live_flights",
        response={ "status": "success", "flights": flight_data },
        scheduling="WHEN_IDLE" # Wait for a moment to tell the user
    )

    # 3. Send it back into the live session
    await session.send_tool_response(function_responses=[function_response])

As seguintes políticas podem ser especificadas no campo scheduling para gerenciar respostas de função:

Política de resposta SILENT

Com a política SILENT, a resposta da função é adicionada ao contexto do modelo, mas ele não gera uma resposta para ela, e nenhuma interação do usuário em andamento é interrompida.

User: Please book the 2:00 PM flight to New York for me.

Model: function_call: {name: "book_ticket"}
//(The book_ticket function call is sent to the client and starts running asynchronously in the background.)

User: What is the current time in New York?
Model: The current time in New York is 12:00pm.

//(The book_ticket function finishes, and client sends the result with scheduling: "SILENT".)
Function_response: {name: "book_ticket", scheduling: "SILENT", response: {booking_status: "booked"}}
//(The model doesn't generate a response for the function response.)

User: Is my flight ticket booked?
Model: Yes. Your flight has been booked.

Política de resposta WHEN_IDLE

Com a política WHEN_IDLE, o modelo gera uma resposta à resposta da função somente quando não há uma interação ativa do usuário. Se uma interação do usuário estiver em andamento, o modelo vai esperar que ela seja concluída antes de gerar uma resposta para evitar interrupções.

User: Please book the 2:00 PM flight to New York for me.

Model: function_call: {name: "book_ticket"}
//(The book_ticket function call is sent to the client and starts running asynchronously in the background.)

User: What is the current time in New York?

//(The book_ticket function finishes, and client sends the result with scheduling: "WHEN_IDLE".)
Function_response: {name: "book_ticket", scheduling: "WHEN_IDLE", response: {booking_status: "booked"}}
//(The ongoing interaction about the time is not interrupted.)

Model: The current time in New York is 12:00pm.
//(After responding to the user's time query, the model issues the response for the book_ticket function.)
Model: Your flight has been booked. Expect a confirmation text on your phone within 5 minutes.

Política de resposta INTERRUPT

Com a política INTERRUPT, o modelo gera uma resposta à função imediatamente, interrompendo qualquer interação do usuário em andamento.

User: Please book the 2:00 PM flight to New York for me.

Model: function_call: {name: "book_ticket"}
//(The book_ticket function call is sent to the client and starts running asynchronously in the background.)

User: What is the current time in New York?

//(The book_ticket function finishes, and client sends the result with scheduling: "INTERRUPT".)
Function_response: {name: "book_ticket", scheduling: "INTERRUPT", response: {booking_status: "booked"}}
//(The ongoing interaction about the time is interrupted, and model skips responding to it.)

Model: Your flight has been booked. Expect a confirmation text on your phone within 5 minutes.

Práticas recomendadas

  • Projetar para simultaneidade: sempre descarregue ferramentas lentas (como consultas de APIs externas ou execução de pipelines RAG) para tarefas em segundo plano no back-end. Deixe o modelo continuar processando o stream de áudio ativo.
  • Evite INTERRUPT, a menos que seja necessário: use INTERRUPT para alertas críticos. Para tarefas em segundo plano, SILENT ou WHEN_IDLE proporcionam uma experiência do usuário muito mais tranquila e agradável.
  • Turnos de conversa independentes: na API Gemini Live, a execução de ferramentas é completamente independente dos turnos de conversa. A conversa pode se ramificar, continuar e fluir naturalmente enquanto sua ferramenta é processada em segundo plano.
  • A ressalva "Silencioso": o modelo ainda pode tentar narrar verbalmente a execução de uma ferramenta, mesmo que ela esteja programada como SILENT. Para impor o silêncio total, adicione restrições explícitas às instruções do sistema (por exemplo, "Ao usar [Nome da ferramenta], faça uma EXECUÇÃO SILENCIOSA e não diga nada") ou use um padrão de back-end "fire-and-forget" em que você não envia um FunctionResponse de volta ao modelo.

A seguir

Visão geral

Confira uma visão geral da API Live.

Referência

Guia de referência da API Live.

Guia

Aprenda a iniciar e gerenciar sessões ao vivo com a API Live.

Guia

Saiba como configurar os recursos do Gemini para a API Live.