Panduan ini menjelaskan cara melakukan streaming pesan secara bertahap di Google Chat menggunakan
resource StreamMessage di Chat API. Streaming memungkinkan aplikasi Google Chat Anda menampilkan indikator progres live, langkah-langkah penalaran atau eksekusi alat perantara, dan respons teks inkremental sebelum menyelesaikan pesan.
Streaming dirancang untuk aplikasi Chat yang didukung oleh AI generatif atau alur kerja backend yang berjalan lama, yang memerlukan waktu beberapa detik atau menit untuk menghasilkan respons lengkap.
Cara kerja streaming pesan
Pesan streaming akan melalui status streaming aktif sebelum menjadi resource Message standar di ruang:
- Memulai rangkaian pesan (
spaces.streamMessages.create): Aplikasi Chat Anda membuatStreamMessagedi ruang berangkai, yang merujuk ke pesan interaksi pengguna yang dibalas. API akan menampilkan indikator progres langsung di rangkaian pesan dan menampilkan nama resourceStreamMessagedannextChunkTokenawal. - Memperbarui streaming (
appendStreamMessageContentataupatch): Saat aplikasi Chat Anda menghasilkan output, aplikasi tersebut akan mengirimkan update berurutan menggunakannextChunkTokenterbaru:- Panggil
spaces.streamMessages.appendStreamMessageContentuntuk menggabungkan bagian teks baru, menambahkan langkah-langkah perantara, menambahkan kutipan inline, atau memperbaruiprogressText. - Panggil
spaces.streamMessages.patchuntuk mengganti potongan konten yang di-streaming atau mengupdateprogressTextdi tempat.
- Panggil
- Finalize or discard the stream (
commitordelete):- Panggil
spaces.streamMessages.commituntuk menyelesaikan streaming dan mengonversinya menjadi resourceMessagepermanen. Anda juga dapat melampirkan elemen khusus commit seperti kartu, widget aksesori, dan sumber footer saat melakukan commit. - Panggil
spaces.streamMessages.deleteuntuk menghapus streaming aktif tanpa menyimpan pesan di ruang.
- Panggil
Saat streaming aktif, hanya pengirim pesan yang direferensikan
(referencedMessage) yang sedang di-streaming yang dapat mengklik Stop untuk membatalkan
pembuatan. Chat mengirimkan peristiwa perintah sistem pembatalan ke
aplikasi Chat Anda sehingga Anda dapat menghentikan pekerjaan backend dan
melakukan commit output parsial atau menghapus streaming.
Prasyarat
Untuk melakukan streaming pesan dengan Chat API, selesaikan prasyarat berikut:
- Akun Google Workspace Business atau Enterprise dengan akses ke Google Chat.
- Siapkan lingkungan Anda:
- Buat project Google Cloud.
- Aktifkan dan konfigurasi Google Chat API dengan nama, ikon, dan deskripsi untuk aplikasi Chat Anda.
- Buat kredensial akun layanan dan simpan sebagai
credentials.json. Streaming pesan memerlukan autentikasi aplikasi dengan cakupan otorisasihttps://www.googleapis.com/auth/chat.bot; autentikasi pengguna tidak didukung.
- Tambahkan aplikasi Chat Anda ke ruang Chat berangkai (atau pesan langsung personal yang sudah berisi setidaknya satu pesan), dan dapatkan nama resource pesan yang dapat diakses untuk dibalas (
spaces/SPACE_ID/messages/MESSAGE_ID). Untuk contoh Python, instal Library Klien Google API untuk Python dan
google-auth, lalu lakukan inisialisasi klien layanan Chat API:pip install google-api-python-client google-authfrom google.oauth2 import service_account from googleapiclient.discovery import build SCOPES = ["https://www.googleapis.com/auth/chat.bot"] creds = service_account.Credentials.from_service_account_file( "credentials.json", scopes=SCOPES ) chat = build("chat", "v1", credentials=creds)
Memulai streaming
Untuk mulai menstreaming balasan, panggil spaces.streamMessages.create dan teruskan
StreamMessage dalam isi permintaan:
referencedMessage(Wajib): Nama resource pesan yang memicu respons, yang diformat sebagaispaces/{space}/messages/{message}. Pesan yang direferensikan harus berada di ruang yang sama dan dapat diakses oleh aplikasi Chat Anda. Chat akan memposting balasan yang di-streaming di rangkaian pesan yang sama denganreferencedMessage.progressText(Wajib): Label status teks biasa yang tidak kosong (hingga 250 karakter) yang ditampilkan di samping indikator progres, seperti"Thinking...".markupSyntax(Opsional): Sintaksis pemformatan teks untuk pesan, sepertiMARKUP_SYNTAX_MARKDOWNatauMARKUP_SYNTAX_CHAT(secara default menggunakan sintaksis yang dikonfigurasi aplikasi Chat jikaMARKUP_SYNTAX_UNSPECIFIED). TetapkanMARKUP_SYNTAX_MARKDOWNjika Anda berencana menyertakan kutipan inline.streamContentChunks(Opsional): Chunktext,step, ataucitationawal yang akan langsung ditampilkan.
Simpan name (spaces/{space}/streamMessages/{stream_message}) dan
nextChunkToken dari respons untuk panggilan berikutnya.
HTTP
POST https://chat.googleapis.com/v1/spaces/SPACE_ID/streamMessages HTTP/1.1
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
{
"referencedMessage": "spaces/SPACE_ID/messages/MESSAGE_ID",
"progressText": "Thinking...",
"markupSyntax": "MARKUP_SYNTAX_MARKDOWN"
}
Python
stream = (
chat.spaces()
.streamMessages()
.create(
parent="spaces/SPACE_ID",
body={
"referencedMessage": "spaces/SPACE_ID/messages/MESSAGE_ID",
"progressText": "Thinking...",
"markupSyntax": "MARKUP_SYNTAX_MARKDOWN",
},
)
.execute()
)
stream_name = stream["name"]
chunk_token = stream["nextChunkToken"]
Metode ini menampilkan resource StreamMessage:
{
"name": "spaces/SPACE_ID/streamMessages/STREAM_MESSAGE_ID",
"progressText": "Thinking...",
"markupSyntax": "MARKUP_SYNTAX_MARKDOWN",
"nextChunkToken": "INITIAL_CHUNK_TOKEN"
}
Menambahkan potongan konten
Saat aplikasi Chat Anda menghasilkan langkah-langkah perantara atau token teks, panggil spaces.streamMessages.appendStreamMessageContent:
- Teruskan
nextChunkTokenterbaru dichunkToken. Setiap panggilan yang berhasil akan menampilkannextChunkTokenbaru yang harus Anda teruskan pada permintaan update atau commit berikutnya. textpotongan digabungkan langsung ke teks yang di-streaming sebelumnya. Sertakan spasi atau baris baru jika diperlukan di antara potongan.steppotongan ditambahkan ke daftar langkah perantara yang ditampilkan pada pesan.progressTextbersifat opsional. Jika Anda menghapusprogressTextatau menyetelnya ke"", Chat akan terus menampilkanprogressTextyang ditetapkan sebelumnya.
HTTP
POST https://chat.googleapis.com/v1/spaces/SPACE_ID/streamMessages/STREAM_MESSAGE_ID:appendStreamMessageContent HTTP/1.1
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
{
"chunkToken": "INITIAL_CHUNK_TOKEN",
"progressText": "Searching documentation...",
"streamContentChunks": [
{
"step": {
"title": "Search knowledge base",
"description": "Found 3 matching articles."
}
},
{
"text": "See <chat-citation data-id=\"c1\">guide</chat-citation>:\n"
},
{
"citation": {
"id": "c1",
"citedSources": [
{
"title": "System Architecture Guide",
"uri": "https://example.com/docs/arch"
}
]
}
}
]
}
Python
stream = (
chat.spaces()
.streamMessages()
.appendStreamMessageContent(
name=stream_name,
body={
"chunkToken": chunk_token,
"progressText": "Searching documentation...",
"streamContentChunks": [
{
"step": {
"title": "Search knowledge base",
"description": "Found 3 matching articles.",
}
},
{
"text": (
'See <chat-citation data-id="c1">'
"guide</chat-citation>:\n"
)
},
{
"citation": {
"id": "c1",
"citedSources": [
{
"title": "System Architecture Guide",
"uri": "https://example.com/docs/arch",
}
],
}
},
],
},
)
.execute()
)
chunk_token = stream["nextChunkToken"]
Mengganti konten yang di-streaming atau teks progres
Jika Anda perlu menulis ulang konten yang di-streaming sebelumnya—misalnya, setelah menjalankan
filter pascapemrosesan atau keamanan—atau hanya memperbarui progressText tanpa
menambahkan potongan, panggil spaces.streamMessages.patch:
- Tetapkan
updateMaskke daftar kolom yang dipisahkan koma untuk diupdate:progressText,streamContentChunks, atauprogressText,streamContentChunks. - Sertakan
nextChunkTokenterbaru di dalam isi permintaanStreamMessage, dan catatnextChunkTokenbaru yang ditampilkan dalam respons. - Jika
streamContentChunksberada dalamupdateMask, potongan yang disediakan akan menggantikan konten yang di-streaming sebelumnya, bukan menambahkannya. Jika
progressTextberada dalamupdateMask,progressTextharus berupa teks biasa yang tidak kosong hingga 250 karakter.
HTTP
PATCH https://chat.googleapis.com/v1/spaces/SPACE_ID/streamMessages/STREAM_MESSAGE_ID?updateMask=progressText,streamContentChunks HTTP/1.1
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
{
"nextChunkToken": "LATEST_CHUNK_TOKEN",
"progressText": "Formatting response...",
"streamContentChunks": [
{
"text": "Updated response text."
}
]
}
Python
stream = (
chat.spaces()
.streamMessages()
.patch(
name=stream_name,
updateMask="progressText,streamContentChunks",
body={
"nextChunkToken": chunk_token,
"progressText": "Formatting response...",
"streamContentChunks": [
{"text": "Updated response text."}
],
},
)
.execute()
)
chunk_token = stream["nextChunkToken"]
Memfinalisasi streaming
Setelah pembuatan selesai, panggil spaces.streamMessages.commit dengan chunkToken terbaru untuk menyelesaikan streaming menjadi resource Message permanen:
- Anda dapat menyertakan
streamContentChunksakhir dalam permintaan commit, termasuk jenis potongan khusus commit (card,accessoryWidget, dancitedSource). Jika Anda telah melakukan streaming konten yang tidak kosong dalam panggilan sebelumnya, Anda dapat menghilangkan
streamContentChunkssaat melakukan commit. Pesan final yang di-commit tidak boleh kosong.
HTTP
POST https://chat.googleapis.com/v1/spaces/SPACE_ID/streamMessages/STREAM_MESSAGE_ID:commit HTTP/1.1
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
{
"chunkToken": "LATEST_CHUNK_TOKEN",
"streamContentChunks": [
{
"text": "All checks passed."
},
{
"citedSource": {
"title": "Deployment Runbook",
"uri": "https://example.com/docs/runbook"
}
},
{
"card": {
"cardId": "details-card",
"card": {
"header": {
"title": "Build Status"
},
"sections": [
{
"widgets": [
{
"textParagraph": {
"text": "All 42 checks succeeded."
}
}
]
}
]
}
}
}
]
}
Python
status_card = {
"cardId": "details-card",
"card": {
"header": {"title": "Build Status"},
"sections": [
{
"widgets": [
{"textParagraph": {"text": "All 42 checks succeeded."}}
]
}
],
},
}
commit_response = (
chat.spaces()
.streamMessages()
.commit(
name=stream_name,
body={
"chunkToken": chunk_token,
"streamContentChunks": [
{"text": "All checks passed."},
{
"citedSource": {
"title": "Deployment Runbook",
"uri": "https://example.com/docs/runbook",
}
},
{"card": status_card},
],
},
)
.execute()
)
final_message = commit_response["message"]
print(f"Committed message: {final_message['name']}")
Menghapus streaming aktif
Jika terjadi error yang tidak dapat dipulihkan atau pengguna membatalkan pembuatan dan Anda tidak
ingin meninggalkan balasan parsial dalam rangkaian pesan, panggil
spaces.streamMessages.delete:
HTTP
DELETE https://chat.googleapis.com/v1/spaces/SPACE_ID/streamMessages/STREAM_MESSAGE_ID HTTP/1.1
Authorization: Bearer ACCESS_TOKEN
Python
chat.spaces().streamMessages().delete(name=stream_name).execute()
Setelah aliran di-commit ke Message, panggil
spaces.messages.delete jika Anda perlu
menghapus pesan yang telah diselesaikan.
Jenis potongan konten yang didukung
Setiap entri di streamContentChunks menentukan satu kolom dalam gabungan StreamContentChunk. Beberapa jenis potongan dapat dikirim di seluruh streaming,
sementara yang lain hanya diterima di spaces.streamMessages.commit:
| Kolom chunk | Metode yang didukung | Kolom Message akhir |
Catatan |
|---|---|---|---|
text |
create, appendStreamMessageContent,
patch, commit |
text |
Teks inkremental. Digabungkan pada
appendStreamMessageContent; diganti pada patch.
Teks akhir yang di-commit tidak boleh melebihi 32.000 byte. |
step |
create, appendStreamMessageContent,
patch, commit |
elements.steps.steps[] |
Langkah pemrosesan sementara dengan title teks biasa
(wajib) dan description opsional. |
citation |
create, appendStreamMessageContent,
patch, commit |
elements.citations[] |
Citation inline dengan id alfanumerik (di bawah 63
karakter, garis bawah diizinkan) dan citedSources. Memerlukan tag markupSyntax: "MARKUP_SYNTAX_MARKDOWN" dan tag <chat-citation data-id="ID">...</chat-citation> yang cocok di text. Mengirim citation dengan
id yang sudah ada akan menimpa kutipan sebelumnya. |
card |
commit saja |
cardsV2[] |
Kartu CardWithId interaktif atau informasional. |
accessoryWidget |
commit saja |
accessoryWidgets[] |
Tombol AccessoryWidget ditampilkan di bawah pesan,
seperti tombol masukan. |
citedSource |
commit saja |
elements.citedSources[] |
Link footer CitedSource ditampilkan di bawah pesan
tanpa tag kutipan inline. |
Menangani pembatalan streaming yang dimulai pengguna
Saat streaming aktif, hanya pengirim pesan yang direferensikan
(referencedMessage) yang sedang di-streaming yang dapat mengklik Berhenti pada pesan
streaming. Saat pengguna menghentikan streaming, Chat akan mengirimkan peristiwa interaksi perintah sistem yang berisi cancelStream.streamMessage (nama resource spaces/{space}/streamMessages/{stream_message} dari streaming yang dihentikan) ke endpoint aplikasi Chat Anda.
Struktur payload JSON yang masuk bergantung pada apakah Anda membangun aplikasi Chat sebagai add-on Google Workspace atau menggunakan peristiwa interaksi Chat API:
Add-on Google Workspace
{
"commonEventObject": {
"hostApp": "CHAT"
},
"chat": {
"user": {
"name": "users/USER_ID"
},
"space": {
"name": "spaces/SPACE_ID"
},
"systemCommandPayload": {
"systemCommandMetadata": {
"cancelStream": {
"streamMessage": "spaces/SPACE_ID/streamMessages/STREAM_ID"
}
}
}
}
}
Google Chat API
{
"type": "SYSTEM_COMMAND",
"space": {
"name": "spaces/SPACE_ID"
},
"user": {
"name": "users/USER_ID"
},
"systemCommandMetadata": {
"cancelStream": {
"streamMessage": "spaces/SPACE_ID/streamMessages/STREAM_ID"
}
}
}
Saat aplikasi Chat Anda menerima peristiwa cancelStream:
- Beri sinyal kepada worker latar belakang Anda untuk berhenti membuat token lebih lanjut atau menjalankan alat downstream untuk
streamMessage. - Selesaikan streaming aktif menggunakan salah satu pendekatan berikut:
- Keep partial output: Panggil
spaces.streamMessages.commitdenganchunkTokenterbaru (opsional menambahkan catatan seperti"\n\n_Generation stopped._"). - Menghapus balasan: Panggil
spaces.streamMessages.deleteagar tidak ada yang disimpan ke rangkaian pesan.
- Keep partial output: Panggil
- Tampilkan respons JSON
200 OKHTTP kosong ({}) dari pengendali peristiwa interaksi Anda.
Batasan
Streaming pesan memiliki batasan berikut:
- Ketersediaan platform: Streaming pesan hanya terlihat di Chat di web. Dukungan untuk Android dan iOS akan segera hadir.
- Waktu tunggu streaming:
StreamMessageyang aktif akan habis waktu tunggunya 10 menit setelah pembuatan. Aplikasi Chat Anda harus memanggilspaces.streamMessages.commitatauspaces.streamMessages.deletedalam waktu 10 menit setelah memulai streaming.