Prozessautomatisierung mit Chatbots in Google Workspace
Inside Develpmnt

Prozessautomatisierung mit Chatbots in Google Workspace

  • 15. April 2025

Unsere Motivation: Bye Bye, Zettelwirtschaft!

Wir waren auf der Suche nach einer unkomplizierten Lösung, mit der unsere Mitarbeiter Urlaubsanträge digital einreichen können – idealerweise inklusive automatischer Genehmigung, Ablehnung und Kalenderpflege direkt in unserem Google Workspace-Intranet.

Statt gleich in ein teures Tool zu investieren, haben wir überlegt: Geht das nicht auch smarter – und günstiger? Also haben wir selbst einen Chatbot gebaut.

Jetzt können Urlaubsanträge direkt im Google Chat gestellt werden. Vorgesetzte bekommen automatisch eine Benachrichtigung und können mit einem Klick zustimmen oder ablehnen. Wird der Urlaub genehmigt, landet er direkt im Teamkalender – und alle Einträge werden sauber in einem Google Sheet dokumentiert.

Wie einfach das geht? Zeigen wir dir im nächsten Abschnitt.

Vorteile von Chat-Bots & Google App Script

Klären wir zuerst einmal die Vorteile eines solchen Ansatzes:

Intelligente Interaktion: Mehr als nur Text:

Über einfache Slash-Befehle können Nutzer spezifische Aktionen auslösen.
Statt E-Mail-Ketten kann der Bot gezielte Informationen über interaktive Dialogfenster abfragen.

Nahtlose Integration - Dein Bot als Brücke zu Google Workspace:

Unsere Mitarbeiter haben unseren Unternehmenschat (Google Chat) eh meisten geöffnet.
Sie müssen keine Tools wechseln. Alle Benachrichtigungen, Auswertungen und auch die Kalendereinträge im gewohnten Umfeld.

Automatisierte Workflows - Der Bot als Prozess-Manager:

Auslöser und Aktionen können leicht verkettet werden. In unserem Urlaubs-Beispiel löst die Einreichung im Chat eine Kette aus: Speichern im Sheet, E-Mail an Manager, Klick auf Genehmigungslink, Status-Update im Sheet, Kalendereintrag, Benachrichtigung an Mitarbeiter. All das ohne manuelles Kopieren, Einfügen oder Nachhaken.

Wie geht das?

Projekt anlegen & Bot einrichten

Bevor’s richtig losgeht, brauchst du ein neues Projekt in der Google Cloud Console. Dort aktivierst du die Google Chat API und richtest deinen Bot ein.

Du vergibst einen Namen, lädst ein passendes Profilbild hoch, schreibst eine kurze Beschreibung – und legst fest, auf welche Befehle dein Bot reagieren soll. In unserem Fall sind das:

  • /help – für die Übersicht der Funktionen
  • /einreichen – zum Stellen eines Urlaubsantrags
  • /uebersicht – um alle bisherigen Anträge einzusehen
chatbot1
chatbot2
Bot-Logik mit Google Apps Script bauen

Als Nächstes erstellen wir ein Google Apps Script. Das bildet das Herzstück unseres Chatbots.

Besonders wichtig ist dabei die Funktion onMessage(). Sie reagiert auf die Befehle, die wir zuvor im Bot hinterlegt haben (siehe Screenshot).

Damit der Bot auch wirklich hilfreich ist, geben wir am Ende ein JSON-Objekt zurück. Darüber lässt sich z. B. eine übersichtliche Hilfe-Karte im Chat rendern – ideal, um dem Nutzer direkt die nächsten Schritte zu zeigen.

onMessage-Function
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 function onMessage(event) { const message = event.message; if (message.slashCommand) { switch (message.slashCommand.commandId) { case 1: // Hilfe-Befehl return createHelpCard(); case 2: // Einreichen-Befehl return openInitialDialog(); case 3: // Übersicht-Befehl return zeigeUrlaubsUebersicht(event); case 4: // Stornieren-Befehl return { text: "Diese Funktion ist noch in Entwicklung." }; } } // Wenn kein bekannter Befehl, zeige Hilfe-Karte return createHelpCard(); }
createHelpCard-Function
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 function createHelpCard() { return { "cardsV2": [ { "cardId": "help-card", "card": { "sections": [ { "header": "", "widgets": [ { "decoratedText": { "topLabel": "", "text": "Hi! 👋 Ich bin hier, um dir mit deinen Urlaubsanträgen zu helfen.<br><br>Hier ist eine Liste von Befehlen, die ich verstehe:", "wrapText": true } } ] }, { "widgets": [ { "decoratedText": { "topLabel": "", "text": "<b>/einreichen</b>: Ich reiche einen Urlaubsantrag ein.", "wrapText": true } }, { "decoratedText": { "topLabel": "", "text": "<b>/übersicht</b>: Gib mir eine Übersicht über meinen geplanten Urlaub.", "wrapText": true } } ] } ], "header": { "title": "Urlaubsbot", "subtitle": "Ich helfe dir deinen Urlaub zu verwalten", "imageUrl": "https://goo.gle/3SfMkjb", "imageType": "SQUARE" } } } ] }; }
Help-Card im Chat
chatbot5

Interaktive Dialoge & Benachrichtigungen per Mail

Auf ähnliche Weise lassen sich auch interaktive Dialoge im Chat darstellen. In unserem Fall öffnet der Befehl /einreichen ein Dialogfenster, in dem alle relevanten Infos zum Urlaub abgefragt werden – Startdatum, Enddatum, Kommentar etc.

Sobald der Nutzer auf „Einreichen“ klickt, wird automatisch eine E-Mail an die Personalverantwortlichen geschickt – ganz einfach über die Gmail API.

Das Beste: Die Mail muss nicht langweilig sein. Mit etwas HTML lässt sich die Nachricht optisch aufwerten – zum Beispiel mit Buttons zur Genehmigung oder Ablehnung, farblichen Markierungen und einem übersichtlichen Layout.

JSON interaktiver Dialog
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 const DATE_RANGE_FORM_WIDGETS = [ { "dateTimePicker": { "name": "dateFrom", "label": "Von", "type": "DATE_ONLY", "valueMsEpoch": new Date(getISODate(0)).getTime() // Aktuelles Datum als Millisekunden seit Epoch } }, { "dateTimePicker": { "name": "dateTo", "label": "Bis", "type": "DATE_ONLY", "valueMsEpoch": new Date(getISODate(7)).getTime() // 7 Tage später } }, { "textInput": { "name": "days", "label": "Anzahl Urlaubstage", "hintText": "Bitte geben Sie die genaue Anzahl der Urlaubstage an", "value": "" } }, { "textInput": { "name": "reason", "label": "Grund", "hintText": "Optional: Grund für den Urlaub angeben", "value": "" } } ];
Einreichen Dialog
chatbot7
Gmail Aufruf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 const subject = `Urlaubsantrag: ${mitarbeiterName} (${vonDatum} bis ${bisDatum})`; // E-Mail mit Genehmigungslinks senden GmailApp.sendEmail( authorizerEmail, subject, `Neuer Urlaubsantrag von ${mitarbeiterName}. Bitte öffne die HTML-Version dieser E-Mail.`, { htmlBody: ` <h2>Neuer Urlaubsantrag</h2> <p><strong>Mitarbeiter:</strong> ${mitarbeiterName} (${aktuellerBenutzer})</p> <p><strong>Zeitraum:</strong> ${vonDatum} bis ${bisDatum} (${anzahlTage} Tage)</p> <p><strong>Grund:</strong> ${grund}</p> <p> <a href="${ScriptApp.getService().getUrl()}?action=approve&id=${urlaubsId}&name=${encodeURIComponent(mitarbeiterName)}&email=${encodeURIComponent(aktuellerBenutzer)}&startDate=${encodeURIComponent(vonDatum)}&endDate=${encodeURIComponent(bisDatum)}&days=${encodeURIComponent(anzahlTage)}" style="display:inline-block; background-color:#4CAF50; color:white; padding:10px 20px; text-decoration:none; margin-right:10px;">Genehmigen</a> <a href="${ScriptApp.getService().getUrl()}?action=reject&id=${urlaubsId}" style="display:inline-block; background-color:#f44336; color:white; padding:10px 20px; text-decoration:none;">Ablehnen</a> </p>
Antrags-Mail
chatbot9

Genehmigung per Klick – so funktioniert’s im Hintergrund

Damit die Buttons in der E-Mail auch wirklich etwas bewirken, muss im Apps Script die Funktion doGet() implementiert werden. Darüber lassen sich Interaktionen abbilden, z. B. wenn ein Vorgesetzter auf „Genehmigen“ klickt.

Mit dem HtmlService können wir dabei sogar eine kleine Bestätigungsseite gestalten.

Im Hintergrund läuft dann Folgendes ab:

1. Über die Calendar API wird der Urlaub direkt in einen für alle sichtbaren Teamkalender eingetragen.
2. Parallel wird über die Spreadsheet API ein neuer Eintrag in einer Google-Tabelle erzeugt. Dort haben Vorgesetzte eine übersichtliche Liste aller Anträge – inklusive Filter- und Suchfunktionen.

doGet Implementierung
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 function doGet(e) { try { // Ausführliche Protokollierung der empfangenen Parameter console.log("GET-Anfrage erhalten - Alle Parameter:", JSON.stringify(e.parameter)); console.log("Action:", e.parameter.action); console.log("ID:", e.parameter.id); const action = e.parameter.action; const urlaubsId = e.parameter.id; // Prüfe auf fehlende Parameter und gib detaillierte Fehlermeldung aus if (!action || !urlaubsId) { console.log("Fehlende Parameter: action=" + action + ", urlaubsId=" + urlaubsId); return HtmlService.createHtmlOutput(` <h2>Fehler: Fehlende Parameter</h2> <p>Die folgenden Parameter fehlen oder sind ungültig:</p> <ul> <li>action: ${action || 'fehlt'}</li> <li>id: ${urlaubsId || 'fehlt'}</li> </ul> <p>Erhaltene Parameter: ${JSON.stringify(e.parameter)}</p> `); } if (action === "approve") { // Parameter für die Genehmigung const mitarbeiterName = e.parameter.name || ""; const mitarbeiterEmail = e.parameter.email || ""; const vonDatum = e.parameter.startDate || ""; const bisDatum = e.parameter.endDate || ""; const anzahlTage = e.parameter.days || ""; // Status aktualisieren aktualisiereUrlaubsantragStatus(urlaubsId, "Genehmigt"); // Kalendereintrag erstellen try { const calendarEvent = createCalendarEvent(vonDatum, bisDatum, mitarbeiterName, anzahlTage); console.log("Kalendereintrag erstellt: " + (calendarEvent ? calendarEvent.getId() : "Fehler")); } catch (calendarError) { console.error("Fehler beim Erstellen des Kalendereintrags:", calendarError); }
Antrags-Mail
chatbot10
Calendar API
1 2 3 4 5 6 7 8 9 10 11 12 13 14 // Kalender-ID aus den Eigenschaften holen const calendarId = PropertiesService.getScriptProperties().getProperty('URLAUB_KALENDER_ID') || 'primary'; // Fallback auf den Hauptkalender // Erstelle Kalendereintrag const calendarEvent = CalendarApp.getCalendarById(calendarId).createAllDayEvent( `${mitarbeiterName} - Urlaub`, startDate, endDate ); // Weitere Details zum Kalendereintrag hinzufügen calendarEvent.setDescription(`Genehmigter Urlaub für ${mitarbeiterName} (${anzahlTage} Tage)`); calendarEvent.setColor(CalendarApp.EventColor.PALE_BLUE); // Farbkodierung für Urlaub
Spreadsheet API
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 const SPREADSHEET_ID = PropertiesService.getScriptProperties().getProperty('URLAUB_SHEET_ID'); if (!SPREADSHEET_ID) { console.log("Kein Spreadsheet konfiguriert, überspringe Speicherung"); return; } const spreadsheet = SpreadsheetApp.openById(SPREADSHEET_ID); const sheet = spreadsheet.getSheetByName('Urlaubsanträge') || spreadsheet.insertSheet('Urlaubsanträge'); // Stelle sicher, dass die Header existieren if (sheet.getLastRow() === 0) { sheet.appendRow([ 'ID', 'Datum eingereicht', 'Mitarbeiter', 'Email', 'Von', 'Bis', 'Tage', 'Grund', 'Status' ]); } // Füge den neuen Antrag hinzu sheet.appendRow([ urlaubsId, new Date().toLocaleDateString('de-DE'), name, email, vonDatum, bisDatum, anzahlTage, grund, 'Ausstehend' ]);
Spreadsheet
chatbot10

Das wars - Bereit zur Nutzung

Damit ist die Implementierung abgeschlossen. Jetzt muss das Ganze nur noch mit einem Klick als Web-App deployed werden – und schon ist der Bot einsatzbereit.

Unsere Mitarbeitenden sind auf jeden Fall begeistert von der Lösung. Und wir sind sicher: Das war nicht das letzte Mal, dass wir unseren Google Workspace programmatisch erweitert haben.