Panggilan fungsi asinkron dengan Gemini Live API

Saat membangun agen suara real-time, beberapa panggilan fungsi dapat memblokir eksekusi model, yang menyebabkan streaming audio menjadi sunyi dan pengguna menunggu dalam keheningan. Dengan Gemini Live API, semua panggilan fungsi bersifat non-pemblokiran secara default, sehingga Anda dapat mengeksekusi fungsi secara paralel dengan alur percakapan utama. Proses ini disebut pemanggilan fungsi asinkron. Backend Anda dapat memproses tugas berat seperti menelusuri harga penerbangan live atau membuat kueri API eksternal yang kompleks di latar belakang, sementara model terus mendengarkan, berbicara, dan bercakap-cakap secara alami dengan pengguna. Gemini Live API memungkinkan panggilan fungsi diproses di latar belakang tanpa mengganggu interaksi pengguna dengan model, sehingga memungkinkan interaksi yang lebih lancar dan real-time.

Pemanggilan fungsi asinkron memungkinkan Anda menyelesaikan tugas seperti membuat janji temu, menyetel pengingat, atau mengambil data tanpa menjeda percakapan. Misalnya, pengguna dapat meminta untuk memesan penerbangan dan langsung meminta informasi cuaca saat pemesanan diproses di latar belakang.

Contoh pemanggilan fungsi asinkron

Contoh ini menunjukkan pengguna yang memesan penerbangan dan menanyakan waktu di New York saat fungsi book_ticket berjalan secara asinkron di latar belakang:

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.

Mengimplementasikan pemanggilan fungsi asinkron

Bagian ini memberikan serangkaian contoh penggunaan Agent Platform SDK versi Python untuk membangun arsitektur serentak yang sangat responsif dan menggunakan kemampuan panggilan fungsi asinkron Gemini Live API. Contohnya diuraikan ke dalam tugas-tugas berikut:

Menentukan alat Anda

Anda dapat mengontrol cara setiap alat dijalankan dengan menetapkan kolom behavior dari FunctionDeclaration:

  • NON_BLOCKING (default jika behavior tidak disetel): model akan terus bercakap-cakap saat alat Anda dijalankan. Gunakan setelan ini untuk pencarian hanya baca atau tugas latar belakang yang hasilnya dapat dikirimkan nanti.
  • BLOCKING: model akan dijeda dan menunggu FunctionResponse Anda sebelum menghasilkan output lebih lanjut. Gunakan setelan ini untuk operasi yang mengubah status atau tidak dapat diubah (seperti pembayaran, pemesanan, atau pembaruan akun) yang modelnya tidak boleh mengonfirmasi hasil sebelum mengetahui hasilnya. Jika input pengguna baru tiba saat panggilan pemblokiran sedang berjalan, server akan membatalkan panggilan, sehingga memerlukan idempotensi backend.

Jika Anda menggunakan framework di atas Gemini Live API, pastikan framework tersebut mengirimkan behavior dalam pesan penyiapan sesi; jika dihilangkan, alat akan berjalan sebagai NON_BLOCKING secara default.

Contoh Python berikut menunjukkan cara mendeklarasikan alat non-pemblokiran dan pemblokiran:

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

Menangani panggilan fungsi dari aliran pesan

Jika satu atau beberapa fungsi harus dipanggil oleh model, Gemini Live API akan mengirimkan peristiwa tool_call melalui aliran pesan real-time.

Backend Anda tidak boleh memblokir streaming karena model diharapkan untuk terus berjalan. Saat menerima panggilan untuk fungsi lambat (seperti search_live_flights), Anda harus meneruskannya ke pekerja latar belakang. Jika Anda menggunakan await langsung di loop pesan utama untuk tugas berdurasi 10 detik, Anda akan membekukan koneksi. Tugas cepat (seperti get_current_weather) dapat ditunggu dengan aman.

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)

Mengelola ekspektasi pengguna

Untuk mengelola ekspektasi selama panggilan fungsi asinkron yang berjalan lama, kirim pesan teks dari klien yang meminta sistem untuk memberi tahu pengguna bahwa permintaan sedang diproses dan meminta kesabaran mereka. Misalnya, setelah panggilan fungsi diterima oleh klien, klien dapat mengirim pesan teks ke model seperti: "ulangi kalimat ini: 'Saya sedang memesan tiket Anda, harap tunggu.'".

Contoh dialog berikut menunjukkan pertukaran ini:

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.

Strategi pesan proaktif ini memiliki manfaat berikut:

  • Menginformasikan operasi sistem saat ini kepada pengguna, yang mengelola ekspektasi selama panggilan fungsi yang berjalan lama.
  • Mengurangi frekuensi perintah singkat pengguna yang berlebihan, seperti "halo?" atau "apakah Anda di sana?". Hal ini sering terjadi selama periode panjang saat sistem tidak merespons selagi panggilan fungsi asinkron diproses. Hal ini dapat meminimalkan risiko panggilan fungsi duplikat yang dipicu oleh permintaan pengguna yang berulang ini.
  • Memberikan perintah sistem tambahan dapat menurunkan kemungkinan pembuatan panggilan duplikat dalam interaksi berikutnya.

Menangani panggilan fungsi duplikat

Ada kemungkinan kecil bahwa model akan menghasilkan panggilan fungsi duplikat sebelum menerima respons untuk panggilan pertama. Jika kasus penggunaan Anda mengizinkan, aplikasi Anda dapat mengabaikan panggilan fungsi duplikat jika respons untuk panggilan fungsi yang sama masih tertunda.

Contoh berikut menunjukkan cara klien dapat mengabaikan panggilan fungsi duplikat:

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.

Menangani respons fungsi asinkron

Setelah panggilan fungsi asinkron selesai, aplikasi Anda akan mengirimkan hasilnya ke model dalam function_response. Saat backend Anda memproses panggilan fungsi, seperti menelusuri penerbangan, pengguna mungkin mengajukan pertanyaan yang sama sekali berbeda kepada model, seperti, "Bagaimana cuaca di London?". Model merespons permintaan secara real-time, bersamaan dengan eksekusi panggilan fungsi. Karena pengguna mungkin sedang berinteraksi dengan model saat eksekusi fungsi selesai, Anda dapat menentukan kebijakan yang menentukan cara model menangani respons yang masuk ini. Anda dapat menentukan salah satu kebijakan berikut:

Untuk menentukan kebijakan, sertakan kolom scheduling dalam payload function_response Anda:

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

Dukungan model untuk FunctionResponse.scheduling bervariasi menurut model:

  • Gemini 3.8 Live: mendukung scheduling (SILENT, WHEN_IDLE, dan INTERRUPT).
  • gemini-3.8-live-extended-thinking-preview: tidak mendukung konfigurasi penjadwalan eksplisit. Mengirim scheduling akan menyebabkan sesi ditutup dengan error WebSocket 1007. Untuk model ini, hapus kolom scheduling.

Jika scheduling dihilangkan pada model yang didukung, Gemini Live API akan ditetapkan secara default ke WHEN_IDLE. Setiap respons fungsi yang masuk akan memicu giliran model baru setelah pengguna selesai berbicara.

Contoh Python berikut menunjukkan cara memformat dan mengirim function_response dengan scheduling="WHEN_IDLE" untuk menunggu jeda alami dalam percakapan sebelum mengumumkan hasil:

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

Kebijakan berikut dapat ditentukan di kolom scheduling untuk mengelola respons fungsi:

Kebijakan respons SILENT

Dengan kebijakan SILENT, respons fungsi ditambahkan ke konteks model, tetapi model tidak menghasilkan respons untuknya, dan interaksi pengguna yang sedang berlangsung tidak akan terganggu.

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.

Kebijakan respons WHEN_IDLE

Dengan kebijakan WHEN_IDLE, model akan menghasilkan respons terhadap respons fungsi hanya jika tidak ada interaksi pengguna yang aktif. Jika interaksi pengguna sedang berlangsung, model akan menunggu hingga interaksi selesai sebelum menghasilkan respons untuk menghindari gangguan.

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.

Kebijakan respons INTERRUPT

Dengan kebijakan INTERRUPT, model akan segera menghasilkan respons terhadap respons fungsi, sehingga mengganggu interaksi pengguna yang sedang berlangsung.

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.

Menggabungkan beberapa respons non-pemblokiran

Saat model memanggil beberapa alat non-pemblokiran secara serentak (seperti pencarian data paralel), mengirimkan setiap hasil satu per satu dengan WHEN_IDLE akan menyebabkan model menghasilkan beberapa giliran bicara yang terpisah. Untuk memberikan satu respons gabungan, terapkan salah satu pola berikut:

  • Gunakan SILENT untuk hasil menengah: Kirim semua respons alat menengah dengan scheduling="SILENT". Kirim respons akhir dengan scheduling="WHEN_IDLE" agar model meringkas semua data yang dikumpulkan dalam satu giliran.
  • Respons batch: Tunggu hingga semua tugas alat serentak selesai dan kirimkan bersama-sama dalam satu panggilan send_tool_response dengan function_responses=[...].

Praktik terbaik

  • Deklarasikan perilaku alat secara eksplisit: Tetapkan alat yang mengubah status atau tidak dapat diubah ke BLOCKING, dan tetapkan pencarian hanya baca atau latar belakang ke NON_BLOCKING.
  • Desain untuk konkurensi: Selalu pindahkan alat yang lambat (seperti membuat kueri API eksternal atau menjalankan pipeline RAG) ke tugas latar belakang di backend Anda. Biarkan model terus menangani streaming audio aktif.
  • Jadwalkan respons non-pemblokiran dengan sengaja: Gunakan SILENT untuk respons perantara, WHEN_IDLE untuk hasil akhir yang akan memicu output lisan, dan INTERRUPT hanya untuk pemberitahuan penting. Jika scheduling tidak ditetapkan, setelan defaultnya adalah WHEN_IDLE dan memulai giliran model untuk setiap respons.
  • Giliran chat independen: Di Gemini Live API, eksekusi alat sepenuhnya independen dari giliran chat. Percakapan dapat bercabang, berlanjut, dan mengalir secara alami saat alat Anda memproses di latar belakang.
  • Peringatan "Senyap": Model mungkin masih sesekali mencoba menceritakan eksekusi alat secara lisan meskipun dijadwalkan sebagai SILENT. Untuk menerapkan keheningan sejati, tambahkan guardrail eksplisit ke System Instructions Anda (misalnya, "Saat menggunakan [Nama Alat], lakukan SILENT EXECUTION dan jangan katakan apa pun"), atau gunakan pola backend "fire-and-forget" di mana Anda tidak mengirim FunctionResponse kembali ke model sama sekali.

Langkah berikutnya

Ringkasan

Dapatkan ringkasan Live API.

Referensi

Panduan referensi untuk Live API.

Panduan

Pelajari cara memulai dan mengelola sesi live dengan Live API.

Panduan

Pelajari cara mengonfigurasi kemampuan Gemini untuk Live API.