In diesem Leitfaden wird beschrieben, wie Sie Nachrichten in Google Chat mithilfe der Ressource StreamMessage in der Chat API schrittweise streamen. Mit Streaming kann Ihre Google Chat-App Live-Fortschrittsanzeigen, Zwischenschritte beim Schlussfolgern oder bei der Toolausführung und inkrementelle Textantworten anzeigen, bevor eine Nachricht fertiggestellt wird.
Streaming ist für Chat-Apps gedacht, die auf generativer KI oder lang laufenden Backend-Workflows basieren, bei denen das Generieren einer vollständigen Antwort mehrere Sekunden oder Minuten dauert.
Funktionsweise des Nachrichtenstreamings
Eine Streamingnachricht durchläuft einen aktiven Streamingstatus, bevor sie zu einer Standardressource vom Typ Message in einem Gruppenbereich wird:
- Stream starten (
spaces.streamMessages.create): Ihre Chat-App erstellt einenStreamMessagein einem Gruppenbereich mit Threads und verweist auf die Nachricht zur Nutzerinteraktion, auf die sie antwortet. Die API zeigt im Thread eine Live-Fortschrittsanzeige an und gibt einenStreamMessage-Ressourcennamen und eine erstenextChunkTokenzurück. - Stream aktualisieren (
appendStreamMessageContentoderpatch): Während Ihre Chat-App Ausgaben generiert, sendet sie sequenzielle Updates mit dem neuestennextChunkToken:- Rufen Sie
spaces.streamMessages.appendStreamMessageContentauf, um neue Textblöcke zu verketten, Zwischenschritte anzuhängen, Inline-Zitate hinzuzufügen oderprogressTextzu aktualisieren. - Rufen Sie
spaces.streamMessages.patchauf, um die gestreamten Inhaltsblöcke zu ersetzen, oder aktualisieren SieprogressTextdirekt.
- Rufen Sie
- Stream abschließen oder verwerfen (
commitoderdelete):- Rufen Sie
spaces.streamMessages.commitauf, um den Stream abzuschließen und in eine permanenteMessage-Ressource zu konvertieren. Sie können beim Übernehmen auch Elemente anhängen, die nur für die Übernahme bestimmt sind, z. B. Karten, Zubehör-Widgets und Quellen in der Fußzeile. - Rufen Sie
spaces.streamMessages.deleteauf, um einen aktiven Stream zu verwerfen, ohne eine Nachricht im Gruppenbereich zu speichern.
- Rufen Sie
Während ein Stream aktiv ist, kann nur der Absender der referenzierten Nachricht (referencedMessage), auf die gestreamt wird, auf Beenden klicken, um die Generierung abzubrechen. Google Chat sendet ein Systembefehlsereignis zum Abbrechen an Ihre Chat-App, damit Sie die Backend-Arbeit beenden und entweder die Teilausgabe übernehmen oder den Stream löschen können.
Vorbereitung
Wenn Sie Nachrichten mit der Chat API streamen möchten, müssen Sie die folgenden Voraussetzungen erfüllen:
- Ein Google Workspace-Konto für Unternehmen mit Zugriff auf Google Chat.
- Richten Sie Ihre Umgebung ein:
- Google Cloud-Projekt erstellen
- Aktivieren und konfigurieren Sie die Google Chat API mit einem Namen, einem Symbol und einer Beschreibung für Ihre Chat-App.
- Erstellen Sie Anmeldedaten für das Dienstkonto und speichern Sie sie als
credentials.json. Für das Nachrichten-Streaming ist eine App-Authentifizierung mit dem Autorisierungsbereichhttps://www.googleapis.com/auth/chat.boterforderlich. Die Nutzerauthentifizierung wird nicht unterstützt.
- Fügen Sie Ihre Chat-App einem Chatbereich mit Thread (oder einer 1:1-Direktnachricht, die bereits mindestens eine Nachricht enthält) hinzu und rufen Sie den Ressourcennamen einer zugänglichen Nachricht ab, auf die Sie antworten möchten (
spaces/SPACE_ID/messages/MESSAGE_ID). Installieren Sie für Python-Beispiele die Google API-Clientbibliothek für Python und
google-authund initialisieren Sie den Chat API-Dienstclient: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)
Stream starten
Wenn Sie eine Antwort streamen möchten, rufen Sie spaces.streamMessages.create auf und übergeben Sie im Anfragetext ein StreamMessage:
referencedMessage(erforderlich): Ressourcenname der Nachricht, die die Antwort ausgelöst hat, formatiert alsspaces/{space}/messages/{message}. Die referenzierte Nachricht muss sich im selben Gruppenbereich befinden und für Ihre Chat-App zugänglich sein. In Google Chat wird die gestreamte Antwort im selben Thread wiereferencedMessagegepostet.progressText(erforderlich): Nicht leeres Nur-Text-Statuslabel (bis zu 250 Zeichen), das neben der Fortschrittsanzeige angezeigt wird, z. B."Thinking...".markupSyntax(optional): Syntax für die Textformatierung der Nachricht, z. B.MARKUP_SYNTAX_MARKDOWNoderMARKUP_SYNTAX_CHAT(standardmäßig die konfigurierte Syntax der Chat-App, wennMARKUP_SYNTAX_UNSPECIFIED). Legen SieMARKUP_SYNTAX_MARKDOWNfest, wenn Sie Inline-Zitate einfügen möchten.streamContentChunks(optional): Anfänglichetext-,step- odercitation-Blöcke, die sofort angezeigt werden sollen.
Speichern Sie sowohl name (spaces/{space}/streamMessages/{stream_message}) als auch nextChunkToken aus der Antwort für nachfolgende Aufrufe.
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"]
Die Methode gibt eine StreamMessage-Ressource zurück:
{
"name": "spaces/SPACE_ID/streamMessages/STREAM_MESSAGE_ID",
"progressText": "Thinking...",
"markupSyntax": "MARKUP_SYNTAX_MARKDOWN",
"nextChunkToken": "INITIAL_CHUNK_TOKEN"
}
Inhaltsblöcke anhängen
Wenn Ihre Chat-App Zwischenschritte oder Text-Tokens erzeugt, rufen Sie spaces.streamMessages.appendStreamMessageContent auf:
- Übergeben Sie die aktuelle
nextChunkTokeninchunkToken. Bei jedem erfolgreichen Aufruf wird ein neuernextChunkTokenzurückgegeben, den Sie bei der nächsten Aktualisierungs- oder Commit-Anfrage übergeben müssen. text-Chunks werden direkt an zuvor gestreamten Text angehängt. Fügen Sie bei Bedarf Leerzeichen oder Zeilenumbrüche zwischen den Blöcken ein.stepChunks werden an die Liste der Zwischenschritte angehängt, die in der Nachricht angezeigt werden.progressTextist optional. Wenn SieprogressTextweglassen oder auf""setzen, wird in Google Chat weiterhin der zuvor festgelegteprogressTextangezeigt.
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"]
Gestreamte Inhalte oder Fortschrittstext ersetzen
Wenn Sie zuvor gestreamte Inhalte neu schreiben müssen, z. B. nach der Ausführung eines Nachbearbeitungs- oder Sicherheitsfilters, oder wenn Sie nur progressText aktualisieren möchten, ohne Chunks anzuhängen, rufen Sie spaces.streamMessages.patch auf:
- Legen Sie für
updateMaskeine durch Kommas getrennte Liste von Feldern fest, die aktualisiert werden sollen:progressText,streamContentChunksoderprogressText,streamContentChunks. - Fügen Sie das neueste
nextChunkTokenin denStreamMessage-Anfragetext ein und notieren Sie das neuenextChunkToken, das in der Antwort zurückgegeben wird. - Wenn
streamContentChunksden WertupdateMaskhat, ersetzen die bereitgestellten Chunks zuvor gestreamte Inhalte, anstatt sie anzuhängen. Wenn
progressTextinupdateMaskist, mussprogressTextein nicht leerer Nur-Text mit bis zu 250 Zeichen sein.
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"]
Stream abschließen
Wenn die Generierung abgeschlossen ist, rufen Sie spaces.streamMessages.commit mit der neuesten chunkToken auf, um den Stream in eine permanente Message-Ressource umzuwandeln:
- Sie können optional endgültige
streamContentChunksin die Commit-Anfrage aufnehmen, einschließlich Nur-Commit-Chunk-Typen (card,accessoryWidgetundcitedSource). Wenn Sie bereits nicht leere Inhalte in früheren Aufrufen gestreamt haben, können Sie
streamContentChunksbeim Commit weglassen. Die endgültige übernommene Nachricht darf nicht leer sein.
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']}")
Aktiven Stream verwerfen
Wenn ein nicht behebbarer Fehler auftritt oder ein Nutzer die Generierung abbricht und Sie keine unvollständige Antwort im Thread hinterlassen möchten, rufen Sie spaces.streamMessages.delete auf:
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()
Sobald ein Stream in einen Message übertragen wurde, rufen Sie stattdessen spaces.messages.delete auf, wenn Sie die abgeschlossene Nachricht löschen müssen.
Unterstützte Typen von Inhaltsblöcken
Jeder Eintrag in streamContentChunks gibt ein Feld in der StreamContentChunk-Union an. Einige Chunk-Typen können während des gesamten Streams gesendet werden, während andere nur in spaces.streamMessages.commit akzeptiert werden:
| Feld „Chunk“ | Unterstützte Methoden | Feld „Final Message“ |
Hinweise |
|---|---|---|---|
text |
create, appendStreamMessageContent,
patch, commit |
text |
Inkrementeller Text. Verkettet am appendStreamMessageContent; ersetzt am patch.
Der endgültige übernommene Text darf 32.000 Byte nicht überschreiten. |
step |
create, appendStreamMessageContent,
patch, commit |
elements.steps.steps[] |
Zwischenverarbeitungsschritt mit Nur-Text-title (erforderlich) und optionalem description. |
citation |
create, appendStreamMessageContent,
patch, commit |
elements.citations[] |
Inline-Citation mit einem alphanumerischen id (unter 63 Zeichen, Unterstriche zulässig) und citedSources. Erfordert markupSyntax: "MARKUP_SYNTAX_MARKDOWN" und übereinstimmende <chat-citation data-id="ID">...</chat-citation>-Tags in text. Wenn Sie eine citation mit einer vorhandenen id senden, wird die frühere Zitation überschrieben. |
card |
Nur commit |
cardsV2[] |
Interaktive oder informative CardWithId-Karte. |
accessoryWidget |
Nur commit |
accessoryWidgets[] |
AccessoryWidget-Buttons, die unter der Nachricht angezeigt werden, z. B. Feedback-Buttons. |
citedSource |
Nur commit |
elements.citedSources[] |
CitedSource-Fußzeilenlink, der unter der Nachricht ohne Inline-Zitattags angezeigt wird. |
Vom Nutzer initiierte Stream-Abbrüche verarbeiten
Während ein Stream aktiv ist, kann nur der Absender der referenzierten Nachricht (referencedMessage), auf die gestreamt wird, in der Streaming-Nachricht auf Beenden klicken. Wenn der Nutzer einen Stream beendet, sendet Google Chat ein Interaktionsereignis für einen Systembefehl mit cancelStream.streamMessage (dem spaces/{space}/streamMessages/{stream_message}-Ressourcennamen des beendeten Streams) an den Endpunkt Ihrer Chat-App.
Die Struktur der eingehenden JSON-Nutzlast hängt davon ab, ob Sie Ihre Chat-App als Google Workspace-Add-on oder mit Chat API-Interaktionsereignissen erstellen:
Add-ons für 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"
}
}
}
Wenn Ihre Chat-App ein cancelStream-Ereignis empfängt:
- Signalisieren Sie Ihrem Hintergrund-Worker, dass er keine weiteren Tokens generieren oder nachgelagerte Tools für
streamMessageausführen soll. - Lösen Sie den aktiven Stream mit einem der folgenden Ansätze auf:
- Teilausgabe beibehalten: Rufen Sie
spaces.streamMessages.commitmit der neuestenchunkTokenauf und hängen Sie optional einen Hinweis wie"\n\n_Generation stopped._"an. - Antwort verwerfen: Rufen Sie
spaces.streamMessages.deleteauf, damit nichts im Thread gespeichert wird.
- Teilausgabe beibehalten: Rufen Sie
- Geben Sie eine leere HTTP-
200 OK-JSON-Antwort ({}) von Ihrem Interaktionsereignis-Handler zurück.
Beschränkungen
Für das Nachrichten-Streaming gelten die folgenden Einschränkungen:
- Plattformverfügbarkeit: Das Nachrichtenstreaming ist nur in der Webversion von Google Chat sichtbar. Die Unterstützung für Android und iOS folgt demnächst.
- Zeitüberschreitung des Streams: Ein aktiver
StreamMessagewird 10 Minuten nach der Erstellung beendet. Ihre Chat-App muss innerhalb von 10 Minuten nach dem Start des Streamsspaces.streamMessages.commitoderspaces.streamMessages.deleteaufrufen.