Durante la creazione di agenti vocali in tempo reale, alcune chiamate di funzione possono bloccare l'esecuzione del modello, causando l'interruzione dello stream audio e l'attesa dell'utente in silenzio. Con l'API Gemini Live, tutte le chiamate di funzione sono non bloccanti per impostazione predefinita, il che ti consente di eseguire le funzioni in parallelo con il flusso della conversazione principale. Questo processo è chiamato chiamata di funzione asincrona. Il backend può elaborare in background attività complesse come la ricerca di prezzi dei voli in tempo reale o l'esecuzione di query su API esterne complesse, mentre il modello continua ad ascoltare, parlare e conversare in modo naturale con l'utente. L'API Gemini Live consente l'elaborazione delle chiamate di funzione in background senza interrompere l'interazione dell'utente con il modello, consentendo interazioni più fluide e in tempo reale.
La chiamata di funzione asincrona ti consente di completare attività come la prenotazione di appuntamenti, l'impostazione di promemoria o il recupero di dati senza mettere in pausa la conversazione. Ad esempio, un utente può richiedere di prenotare un volo e chiedere immediatamente informazioni sul meteo mentre la prenotazione viene elaborata in background.
Esempio di chiamata di funzione asincrona
Questo esempio mostra un utente che prenota un volo e chiede l'ora a New York mentre la funzione book_ticket viene eseguita in modo asincrono in background:
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.
Implementa la chiamata di funzione asincrona
Questa sezione fornisce una serie di esempi che utilizzano la versione Python dell'SDK Agent Platform per creare un'architettura simultanea altamente reattiva che utilizza la funzionalità di chiamata di funzione asincrona dell'API Gemini Live. Gli esempi sono suddivisi nelle seguenti attività:
- Definisci gli strumenti
- Gestisci le chiamate di funzione dallo stream di messaggi
- Gestisci le aspettative degli utenti
Definisci gli strumenti
Puoi controllare il modo in cui viene eseguito ogni strumento impostando il campo behavior del relativo
FunctionDeclaration:
NON_BLOCKING(impostazione predefinita quandobehaviornon è impostato): il modello continua a conversare mentre lo strumento viene eseguito. Utilizza questa impostazione per ricerche di sola lettura o attività in background i cui risultati possono essere forniti in un secondo momento.BLOCKING: il modello si mette in pausa e attende il tuoFunctionResponseprima di generare un altro output. Utilizza questa impostazione per operazioni irreversibili o che modificano lo stato (come pagamenti, prenotazioni o aggiornamenti dell'account) in cui il modello non deve confermare un risultato prima di conoscerlo. Se un nuovo input dell'utente arriva mentre è in esecuzione una chiamata di blocco, il server annulla la chiamata, richiedendo l'idempotenza del backend.
Se utilizzi un framework basato sull'API Gemini Live, verifica che il framework trasmetta behavior nel messaggio di configurazione della sessione. Se omesso, gli strumenti vengono eseguiti come NON_BLOCKING per impostazione predefinita.
Il seguente esempio di Python mostra come dichiarare strumenti non bloccanti e bloccanti:
from google import genai
from google.genai import types
client = genai.Client()
# 1. A read-only lookup: safe to run in the background
search_live_flights = types.FunctionDeclaration(
name="search_live_flights",
description="Searches airlines for current flight prices. Can take up to 10 seconds.",
behavior=types.Behavior.NON_BLOCKING,
)
# 2. A state-changing operation: the model waits for the result before continuing
book_flight = types.FunctionDeclaration(
name="book_flight",
description="Books a flight ticket. Irreversible.",
behavior=types.Behavior.BLOCKING,
parameters=types.Schema(
type=types.Type.OBJECT,
properties={
"flight_id": types.Schema(type=types.Type.STRING),
},
required=["flight_id"],
),
)
tools = [types.Tool(function_declarations=[search_live_flights, book_flight])]
Gestisci le chiamate di funzione dal flusso di messaggi
Quando il modello deve chiamare una o più funzioni, l'API Gemini Live invia un evento tool_call tramite lo stream di messaggi in tempo reale.
Il backend non deve bloccare lo stream perché il modello deve continuare a funzionare. Quando ricevi una chiamata per una funzione lenta (come search_live_flights), devi passarla a un worker in background. Se utilizzi un
await direttamente nel loop dei messaggi principali per un'attività di 10 secondi, la connessione verrà bloccata. Le attività rapide (come get_current_weather) possono essere attese in sicurezza.
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)
Gestisci le aspettative degli utenti
Per gestire le aspettative durante le chiamate di funzione asincrone di lunga durata, invia un messaggio dal client che chiede al sistema di informare l'utente che la richiesta è in fase di elaborazione e di chiedere di avere pazienza. Ad esempio, dopo che il client riceve una chiamata di funzione, può inviare un messaggio al modello, ad esempio: "Ripeti questa frase: 'Sto prenotando il tuo biglietto, attendi'".
La seguente finestra di dialogo di esempio mostra questo scambio:
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.
Questa strategia di messaggistica proattiva offre i seguenti vantaggi:
- Informa l'utente delle operazioni di sistema in corso, gestendo le aspettative durante le chiamate di funzione a lunga esecuzione.
- Riduce la frequenza di prompt brevi e ridondanti degli utenti, come "Pronto?" o "Ci sei?". Questi si verificano spesso durante lunghi periodi di silenzio del sistema mentre vengono elaborate le chiamate di funzione asincrone. In questo modo, è possibile ridurre al minimo il rischio di chiamate di funzione duplicate attivate da queste richieste ripetute degli utenti.
- Fornire un prompt di sistema aggiuntivo può ridurre la probabilità di creare chiamate duplicate nelle interazioni successive.
Gestisci le chiamate di funzione duplicate
Esiste una piccola possibilità che il modello generi chiamate di funzione duplicate prima di ricevere una risposta per la prima chiamata. Se il tuo caso d'uso lo consente, la tua applicazione può ignorare le chiamate di funzione duplicate se una risposta per la stessa chiamata di funzione è ancora in attesa.
L'esempio seguente mostra come un client può ignorare una chiamata di funzione duplicata:
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.
Gestisci le risposte delle funzioni asincrone
Al termine di una chiamata di funzione asincrona, l'applicazione invia il risultato al modello in un function_response. Mentre il backend elabora una chiamata di funzione, ad esempio la ricerca di voli, l'utente potrebbe porre al modello una domanda completamente diversa, ad esempio "Che tempo fa a Londra?". Il modello risponde alla richiesta in tempo reale, in parallelo con l'esecuzione della chiamata di funzione. Poiché l'utente potrebbe essere impegnato in un'interazione in corso con il modello al termine dell'esecuzione della funzione, puoi specificare una policy che definisce il modo in cui il modello deve gestire questa risposta in arrivo. Puoi specificare una delle
seguenti policy:
Per specificare una policy, includi il campo scheduling nel payload function_response:
{
"name": "book_ticket",
"scheduling": "WHEN_IDLE",
"response": {
"booking_status": "booked"
}
}
Il supporto dei modelli per FunctionResponse.scheduling varia in base al modello:
Gemini 3.8 Live: supportascheduling(SILENT,WHEN_IDLEeINTERRUPT).gemini-3.8-live-extended-thinking-preview: non supporta configurazioni di pianificazione esplicite. L'invio dischedulingcausa la chiusura della sessione con l'errore WebSocket 1007. Per questo modello, ometti il camposcheduling.
Se scheduling viene omesso sui modelli supportati, l'API Gemini Live utilizza per impostazione predefinita
WHEN_IDLE. Ogni risposta della funzione in entrata attiva un nuovo turno del modello dopo che l'utente ha finito di parlare.
L'esempio di Python seguente mostra come formattare e inviare un function_response con scheduling="WHEN_IDLE" per attendere una pausa naturale nella conversazione prima di annunciare i risultati:
async 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])
Nel campo scheduling è possibile specificare le seguenti policy per la gestione delle risposte della funzione:
Policy di risposta SILENT
Con la policy SILENT, la risposta della funzione viene aggiunta al contesto del modello, ma il modello non genera una risposta e l'interazione dell'utente in corso non viene interrotta.
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.
Policy di risposta WHEN_IDLE
Con la policy WHEN_IDLE, il modello genera una risposta alla risposta della funzione solo quando non è presente un'interazione utente attiva. Se è in corso un'interazione con l'utente, il modello attende il completamento prima di generare una risposta per evitare interruzioni.
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.
Policy di risposta INTERRUPT
Con la policy INTERRUPT, il modello genera immediatamente una risposta alla risposta della funzione, interrompendo qualsiasi interazione utente in corso.
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.
Aggrega più risposte non bloccanti
Quando il modello chiama contemporaneamente più strumenti non bloccanti (ad esempio ricerche di dati parallele), l'invio di ogni risultato singolarmente con WHEN_IDLE fa sì che il modello generi più turni di conversazione separati. Per fornire una singola risposta consolidata, applica uno dei seguenti pattern:
- Utilizza SILENT per i risultati intermedi: invia tutte le risposte intermedie dello strumento con
scheduling="SILENT". Invia la risposta finale conscheduling="WHEN_IDLE"in modo che il modello riassuma tutti i dati raccolti in un unico turno. - Risposte in batch: attendi il completamento di tutte le attività simultanee dello strumento e inviale insieme in una singola chiamata
send_tool_responseconfunction_responses=[...].
Best practice
- Dichiara esplicitamente il comportamento dello strumento: imposta gli strumenti che modificano lo stato o irreversibili su
BLOCKINGe le ricerche di sola lettura o in background suNON_BLOCKING. - Progetta per la concorrenza: delega sempre gli strumenti lenti (come l'esecuzione di query su API esterne o l'esecuzione di pipeline RAG) alle attività in background nel tuo backend. Lascia che il modello continui a gestire lo stream audio attivo.
- Pianifica deliberatamente risposte non bloccanti: utilizza
SILENTper le risposte intermedie,WHEN_IDLEper il risultato finale che dovrebbe attivare l'output vocale eINTERRUPTsolo per gli avvisi critici. Se non impostischeduling, il valore predefinito èWHEN_IDLEe viene avviato un turno del modello per ogni risposta. - Turni di chat indipendenti: nell'API Gemini Live, l'esecuzione degli strumenti è completamente indipendente dai turni di chat. La conversazione può ramificarsi, continuare e fluire in modo naturale mentre lo strumento elabora in background.
- L'avviso "Silenzioso": il modello potrebbe comunque tentare occasionalmente di narrare verbalmente l'esecuzione di uno strumento anche se pianificato come
SILENT. Per imporre il silenzio assoluto, aggiungi guardrail espliciti alle istruzioni di sistema (ad esempio, "Quando utilizzi [Nome strumento], esegui un'ESECUZIONE SILENZIOSA e non dire nulla ") o utilizza un pattern di backend"fire-and-forget" in cui non invii affatto unFunctionResponseal modello.
Passaggi successivi
Configura le funzionalità di Gemini
Scopri come configurare le funzionalità di Gemini per l'API Live.