Asynchrone Funktionsaufrufe mit der Gemini Live API

Beim Erstellen von Echtzeit-Sprach-Agents können einige Funktionsaufrufe die Ausführung des Modells blockieren. Dadurch wird der Audiostream stummgeschaltet und der Nutzer muss warten. Bei der Gemini Live API sind alle Funktionsaufrufe standardmäßig nicht blockierend. So können Sie Funktionen parallel zum Hauptunterhaltungsablauf ausführen. Dieser Vorgang wird als asynchroner Funktionsaufruf bezeichnet. Ihr Backend kann rechenintensive Aufgaben wie die Suche nach aktuellen Flugpreisen oder die Abfrage komplexer externer APIs im Hintergrund verarbeiten, während das Modell weiterhin zuhört, spricht und sich natürlich mit dem Nutzer unterhält. Mit der Gemini Live API können Funktionsaufrufe im Hintergrund verarbeitet werden, ohne die Interaktion des Nutzers mit dem Modell zu unterbrechen. Das ermöglicht flüssigere Interaktionen in Echtzeit.

Mit asynchronen Funktionsaufrufen können Sie Aufgaben wie das Buchen von Terminen, das Festlegen von Erinnerungen oder das Abrufen von Daten erledigen, ohne die Unterhaltung zu unterbrechen. Ein Nutzer kann beispielsweise einen Flug buchen und sofort nach Wetterinformationen fragen, während die Buchung im Hintergrund verarbeitet wird.

Beispiel für einen asynchronen Funktionsaufruf

In diesem Beispiel bucht ein Nutzer einen Flug und fragt nach der Uhrzeit in New York, während die Funktion book_ticket asynchron im Hintergrund ausgeführt wird:

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.

Asynchrone Funktionsaufrufe implementieren

In diesem Abschnitt finden Sie eine Reihe von Beispielen, in denen die Python-Version des Agent Platform SDK verwendet wird, um eine hochgradig reaktionsschnelle, gleichzeitige Architektur zu erstellen, die die asynchrone Funktionsaufruffunktion der Gemini Live API nutzt. Die Beispiele sind in die folgenden Aufgaben unterteilt:

Tools definieren

Sie können die Ausführung der einzelnen Tools steuern, indem Sie das Feld behavior der zugehörigen FunctionDeclaration festlegen:

  • NON_BLOCKING (Standard, wenn behavior nicht festgelegt ist): Das Modell setzt die Unterhaltung fort, während Ihr Tool ausgeführt wird. Verwenden Sie diese Einstellung für schreibgeschützte Suchvorgänge oder Hintergrundaufgaben, deren Ergebnisse später geliefert werden können.
  • BLOCKING: Das Modell pausiert und wartet auf Ihre FunctionResponse, bevor es weitere Ausgaben generiert. Verwenden Sie diese Einstellung für zustandsändernde oder unumkehrbare Vorgänge (z. B. Zahlungen, Buchungen oder Kontoaktualisierungen), bei denen das Modell ein Ergebnis erst bestätigen darf, wenn es das Ergebnis kennt. Wenn neue Nutzereingaben eingehen, während ein blockierender Aufruf ausgeführt wird, bricht der Server den Aufruf ab. Dies erfordert Idempotenz im Backend.

Wenn Sie ein Framework zusätzlich zur Gemini Live API verwenden, prüfen Sie, ob das Framework behavior in der Nachricht zur Einrichtung der Sitzung überträgt. Wenn dies nicht der Fall ist, werden Tools standardmäßig als NON_BLOCKING ausgeführt.

Im folgenden Python-Beispiel wird gezeigt, wie sowohl nicht blockierende als auch blockierende Tools deklariert werden:

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])]

Funktionsaufrufe aus dem Nachrichtenstream verarbeiten

Wenn eine oder mehrere Funktionen vom Modell aufgerufen werden sollen, sendet die Gemini Live API ein tool_call-Ereignis über den Echtzeit-Nachrichtenstream.

Ihr Backend darf den Stream nicht blockieren, da das Modell erwartet, dass er weiterläuft. Wenn Sie einen Aufruf für eine langsame Funktion (z. B. search_live_flights) erhalten, müssen Sie ihn an einen Hintergrund-Worker übergeben. Wenn Sie einen await direkt in Ihrer Hauptnachrichtenschleife für eine 10-Sekunden-Aufgabe verwenden, wird die Verbindung eingefroren. Auf schnelle Aufgaben (wie get_current_weather) kann sicher gewartet werden.

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)

Erwartungen der Nutzer verwalten

Um die Erwartungen bei lang andauernden asynchronen Funktionsaufrufen zu steuern, senden Sie eine Nachricht vom Client, die das System auffordert, den Nutzer darüber zu informieren, dass die Anfrage verarbeitet wird, und ihn um Geduld zu bitten. Nachdem der Client beispielsweise einen Funktionsaufruf erhalten hat, kann er eine Textnachricht an das Modell senden, z. B.: „Wiederhole diesen Satz: ‚Ich buche jetzt dein Ticket, bitte warte.‘“.

Das folgende Beispiel zeigt diesen Austausch:

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.

Diese proaktive Messaging-Strategie bietet folgende Vorteile:

  • Informiert den Nutzer über aktuelle Systemvorgänge, um die Erwartungen bei lang andauernden Funktionsaufrufen zu steuern.
  • Reduziert die Häufigkeit redundanter kurzer Nutzeraufforderungen wie „Hallo?“ oder „Bist du da?“. Diese treten häufig während langer Zeiträume auf, in denen das System inaktiv ist, während asynchrone Funktionsaufrufe verarbeitet werden. So lässt sich das Risiko doppelter Funktionsaufrufe minimieren, die durch diese wiederholten Nutzeranfragen ausgelöst werden.
  • Wenn Sie einen zusätzlichen System-Prompt bereitstellen, kann dies die Wahrscheinlichkeit verringern, dass in nachfolgenden Interaktionen doppelte Aufrufe erstellt werden.

Doppelte Funktionsaufrufe verarbeiten

Es besteht eine geringe Wahrscheinlichkeit, dass das Modell doppelte Funktionsaufrufe generiert, bevor es eine Antwort auf den ersten Aufruf erhält. Wenn Ihr Anwendungsfall es zulässt, kann Ihre Anwendung doppelte Funktionsaufrufe ignorieren, wenn eine Antwort für denselben Funktionsaufruf noch aussteht.

Das folgende Beispiel zeigt, wie ein Client einen doppelten Funktionsaufruf ignorieren kann:

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.

Asynchrone Funktionsantworten verarbeiten

Wenn ein asynchroner Funktionsaufruf abgeschlossen ist, sendet Ihre Anwendung das Ergebnis in einer function_response an das Modell. Während Ihr Backend einen Funktionsaufruf verarbeitet, z. B. die Suche nach Flügen, stellt der Nutzer dem Modell möglicherweise eine völlig andere Frage, z. B. „Wie ist das Wetter in London?“. Das Modell antwortet in Echtzeit auf die Anfrage, parallel zur Ausführung des Funktionsaufrufs. Da sich der Nutzer möglicherweise in einer laufenden Interaktion mit dem Modell befindet, wenn die Funktionsausführung abgeschlossen ist, können Sie eine Richtlinie angeben, die definiert, wie das Modell mit dieser eingehenden Antwort umgehen soll. Sie können eine der folgenden Richtlinien angeben:

Wenn Sie eine Richtlinie angeben möchten, fügen Sie das Feld scheduling in die function_response-Nutzlast ein:

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

Die Modellunterstützung für FunctionResponse.scheduling variiert je nach Modell:

  • Gemini 3.8 Live: unterstützt scheduling (SILENT, WHEN_IDLE und INTERRUPT).
  • gemini-3.8-live-extended-thinking-preview: Unterstützt keine expliziten Planungskonfigurationen. Wenn Sie scheduling senden, wird die Sitzung mit dem WebSocket-Fehler 1007 geschlossen. Lassen Sie bei diesem Modell das Feld scheduling weg.

Wenn scheduling bei unterstützten Modellen weggelassen wird, verwendet die Gemini Live API standardmäßig WHEN_IDLE. Jede eingehende Funktionsantwort löst einen neuen Modellwechsel aus, nachdem der Nutzer aufgehört hat zu sprechen.

Im folgenden Python-Beispiel wird gezeigt, wie Sie eine function_response mit scheduling="WHEN_IDLE" formatieren und senden, um auf eine natürliche Pause im Gespräch zu warten, bevor die Ergebnisse angesagt werden:

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])

Die folgenden Richtlinien können im Feld scheduling angegeben werden, um Funktionsantworten zu verwalten:

Antwortrichtlinie SILENT

Bei der Richtlinie SILENT wird die Funktionsantwort dem Kontext des Modells hinzugefügt, das Modell generiert jedoch keine Antwort darauf und laufende Nutzerinteraktionen werden nicht unterbrochen.

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.

Antwortrichtlinie WHEN_IDLE

Mit der Richtlinie WHEN_IDLE generiert das Modell nur dann eine Antwort auf die Funktionsantwort, wenn keine aktive Nutzerinteraktion stattfindet. Wenn eine Nutzerinteraktion im Gange ist, wartet das Modell, bis diese abgeschlossen ist, bevor es eine Antwort generiert, um Unterbrechungen zu vermeiden.

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.

INTERRUPT-Antwortrichtlinie

Bei der Richtlinie INTERRUPT generiert das Modell sofort eine Antwort auf die Funktionsantwort und unterbricht alle laufenden Nutzerinteraktionen.

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.

Mehrere nicht blockierende Antworten zusammenfassen

Wenn das Modell mehrere nicht blockierende Tools gleichzeitig aufruft (z. B. parallele Datensuchen), führt das Senden jedes Ergebnisses einzeln mit WHEN_IDLE dazu, dass das Modell mehrere separate gesprochene Turns generiert. Wenden Sie eines der folgenden Muster an, um eine einzelne konsolidierte Antwort zu liefern:

  • SILENT für Zwischenergebnisse verwenden: Senden Sie alle Zwischenantworten des Tools mit scheduling="SILENT". Senden Sie die endgültige Antwort mit scheduling="WHEN_IDLE", damit das Modell alle erfassten Daten in einem Durchgang zusammenfasst.
  • Batchantworten: Warten Sie, bis alle gleichzeitigen Toolaufgaben abgeschlossen sind, und liefern Sie sie zusammen in einem einzigen send_tool_response-Aufruf mit function_responses=[...].

Best Practices

  • Toolverhalten explizit deklarieren: Setzen Sie Tools, die den Zustand ändern oder nicht rückgängig gemacht werden können, auf BLOCKING und Lesezugriff- oder Hintergrundabfragen auf NON_BLOCKING.
  • Für Nebenläufigkeit entwerfen: Lagern Sie langsame Tools (z. B. Abfragen externer APIs oder Ausführen von RAG-Pipelines) immer in Hintergrundaufgaben in Ihrem Backend aus. Das Modell soll den aktiven Audiostream weiterhin verarbeiten.
  • Nicht blockierende Antworten gezielt planen: Verwenden Sie SILENT für Zwischenantworten, WHEN_IDLE für das Endergebnis, das eine Sprachausgabe auslösen soll, und INTERRUPT nur für wichtige Warnungen. Wenn scheduling nicht festgelegt ist, wird standardmäßig WHEN_IDLE verwendet und für jede Antwort ein Modellwechsel initiiert.
  • Unabhängige Chat-Turns: In der Gemini Live API ist die Toolausführung vollständig unabhängig von Chat-Turns. Die Unterhaltung kann sich verzweigen, fortgesetzt werden und natürlich fließen, während Ihr Tool im Hintergrund arbeitet.
  • Einschränkung „Silent“: Das Modell versucht möglicherweise gelegentlich, die Ausführung eines Tools mündlich zu beschreiben, auch wenn es als SILENT geplant ist. Wenn Sie eine echte Stille erzwingen möchten, fügen Sie Ihren Systemanweisungen explizite Guardrails hinzu (z. B. „Führe bei Verwendung von [Toolname] eine STILLE AUSFÜHRUNG durch und sage nichts“) oder verwenden Sie ein „Fire-and-Forget“-Backend-Muster, bei dem Sie überhaupt kein FunctionResponse an das Modell zurücksenden.

Nächste Schritte

Übersicht

Verschaffen Sie sich einen Überblick über die Live API.

Referenz

Referenzhandbuch für die Live API.

Anleitung

Hier erfahren Sie, wie Sie Live-Sitzungen mit der Live API starten und verwalten.

Anleitung

Hier erfahren Sie, wie Sie Gemini-Funktionen für die Live API konfigurieren.