מענה לתקריות שימוש ב-Google Chat, ב-Vertex AI וב-Apps Script

במדריך הזה מוסבר איך ליצור אפליקציה ל-Google Chat שמגיבה לאירועים בזמן אמת. כשמגיבים לאירוע, האפליקציה יוצרת מרחב ב-Chat וממלאת אותו בפרטים, עוזרת לפתור את האירוע באמצעות הודעות, פקודות לוכסן ודיאלוגים, ומשתמשת ב-AI כדי לסכם את התגובה לאירוע במסמך Google Docs.

במדריך הזה נעשה שימוש בהיקפי הרשאות שמתחילים ב-https://www.googleapis.com/auth/chat.app.*. כדי שאפליקציית Chat תוכל להשתמש בהיקפי הגישה האלה, צריך לקבל אישור אדמין חד-פעמי.

אירוע הוא אירוע שדורש טיפול מיידי של צוות אנשים כדי לפתור אותו. דוגמאות לאירועים:

  • בקשת תמיכה דחופה נוצרת בפלטפורמה לניהול קשרי לקוחות (CRM), וצוות שירות צריך לשתף פעולה כדי לפתור אותה.
  • מערכת עוברת למצב אופליין, וקבוצה של מהנדסי Site Reliability (SRE) מקבלת התראה כדי שיוכלו לעבוד יחד ולהחזיר אותה למצב אונליין.
  • מתרחשת רעידת אדמה בעוצמה גבוהה, ועובדי החירום צריכים לתאם את התגובה שלהם.

לצורך המדריך הזה, ההתראה על האירוע מתחילה כשמישהו מדווח על האירוע בלחיצה על לחצן בדף אינטרנט. דף האינטרנט מדמה אירוע על ידי בקשה מהמשתמשים להזין מידע בסיסי על האירוע: שם, תיאור וכתובות אימייל של המשיבים.

כך נראית אפליקציית Chat לניהול אירועים בפעולה:

  • האתר שמתחיל אירוע.
    איור 1. האתר שבו אפשר לדווח על תקרית.
  • התראה על יצירת המרחב ב-Chat לדיווח על האירוע.
    איור 2. התראה על יצירת המרחב ב-Chat לדיווח על האירוע.
  • המרחב ב-Chat שבו מתנהל הטיפול בתקרית.
    איור 3. מרחב ב-Chat לטיפול בתקרית.
  • לפתור את האירוע באמצעות פקודה של שורת הפקודות.
    איור 4. לפתור את האירוע באמצעות פקודה של שורת הפקודות.
  • תיבת הדו-שיח לפתרון אירועים.
    איור 5. תיבת הדו-שיח של פתרון האירוע.
  • מסמך Google Docs עם פתרון האירוע שותף במרחב.
    איור 6. מסמך Google Docs לפתרון אירועים ששותף במרחב.
  • מסמך Google Docs עם סיכום ה-AI של האירוע.
    איור 7. מסמך Google Docs עם סיכום האירוע שנוצר על ידי AI.

דרישות מוקדמות

אם אתם צריכים להפעיל בארגון שלכם את אחת מהדרישות המוקדמות האלה, אתם צריכים לבקש מהאדמין שלכם ב-Google Workspace להפעיל אותן:

  • חשבון Google Workspace במהדורת Business או Enterprise עם גישה ל-Google Chat.
  • להפעיל את המאגר הארגוני (שיתוף אנשי קשר) ב-Google Workspace. אפליקציית האירוע משתמשת בספרייה כדי לחפש את פרטי הקשר של המשיבים לאירוע, כמו שם וכתובת אימייל. אנשים שמגיבים לאירועים צריכים להיות משתמשים עם חשבון Google Chat בארגון Google Workspace שלכם.

מטרות

  • פיתוח אפליקציה ל-Chat שמגיבה לתקריות.
  • כדי לעזור למשתמשים להגיב לאירועים, אפשר לבצע את הפעולות הבאות:
    • יצירת מרחבים לתגובה לאירועים.
    • פרסום הודעות עם סיכום של תקריות ותגובות.
    • תמיכה בשיתוף פעולה באמצעות תכונות אינטראקטיביות של אפליקציית Chat.
  • סיכום שיחות ופתרונות בעזרת Vertex AI.

ארכיטקטורה

בתרשים הבא מוצגת הארכיטקטורה של משאבי Google Workspace ו-Google Cloud שבהם נעשה שימוש באפליקציית Google Chat לתגובה לאירועים.

ארכיטקטורה של אפליקציית Google Chat לתגובה לאירועים

הארכיטקטורה מראה איך אפליקציית Google Chat לתגובה לאירועים מעבדת אירוע ופתרון.

  1. משתמש מתחיל אירוע מאתר חיצוני שמארח ב-Apps Script.

  2. האתר שולח בקשת HTTP אסינכרונית לאפליקציית Google Chat, שגם היא מתארחת ב-Apps Script.

  3. אפליקציית Google Chat לתגובה לאירועים מעבדת את הבקשה:

    1. שירות Apps Script Admin SDK מקבל מידע על חברי הצוות, כמו מזהה משתמש וכתובת אימייל.

    2. באמצעות סדרה של בקשות HTTP ל-Chat API באמצעות שירות Chat המתקדם של Apps Script, אפליקציית Google Chat לטיפול באירועים יוצרת מרחב ב-Chat לטיפול באירוע, מוסיפה לו את חברי הצוות ושולחת הודעה למרחב.

  4. חברי הצוות דנים באירוע במרחב ב-Chat.

  5. חבר צוות מפעיל פקודה של שורת הפקודות כדי לסמן שהתקרית נפתרה.

    1. קריאת HTTP ל-Chat API באמצעות שירות Chat המתקדם של Apps Script מציגה את כל ההודעות במרחב ב-Chat.

    2. ‫Vertex AI מקבל את ההודעות שצוינו ויוצר סיכום.

    3. שירות DocumentApp של Apps Script יוצר מסמך Docs ומוסיף למסמך את הסיכום של Vertex AI.

    4. אפליקציית Google Chat לתגובה לאירועים קוראת ל-Chat API כדי לשלוח הודעה עם קישור למסמך הסיכום ב-Docs.

הכנת הסביבה

בקטע הזה מוסבר איך ליצור ולהגדיר פרויקט ב-Google Cloud לאפליקציית Chat.

יצירת פרויקט של Google Cloud

מסוף Google Cloud

  1. במסוף Google Cloud, עוברים אל תפריט > IAM & Admin > Create a Project (יצירת פרויקט).

    כניסה לדף Create a Project

  2. בשדה Project Name (שם הפרויקט), מזינים שם תיאורי לפרויקט.

    אופציונלי: כדי לערוך את מזהה הפרויקט, לוחצים על עריכה. אי אפשר לשנות את מזהה הפרויקט אחרי שהוא נוצר, לכן חשוב לבחור מזהה שיענה על הצרכים שלכם למשך חיי הפרויקט.

  3. בשדה Location, לוחצים על Browse כדי להציג מיקומים אפשריים לפרויקט. אחר כך לוחצים על בחירה.
  4. לוחצים על יצירה. מערכת Google Cloud מעבירה אתכם לדף Dashboard והפרויקט נוצר תוך כמה דקות.

CLI של gcloud

באחת מסביבות הפיתוח הבאות, ניגשים אל Google Cloud CLI‏ (gcloud):

  • Cloud Shell: כדי להשתמש בטרמינל אונליין שבו כבר מוגדר ה-CLI של gcloud, צריך להפעיל את Cloud Shell.
    הפעלת Cloud Shell
  • מעטפת מקומית: כדי להשתמש בסביבת פיתוח מקומית צריך להתקין ולהפעיל את ה-CLI של gcloud.
    כדי ליצור פרויקט ב-Cloud, משתמשים בפקודה gcloud projects create:
    gcloud projects create PROJECT_ID
    מחליפים את PROJECT_ID במזהה של הפרויקט שרוצים ליצור.

הפעלת החיוב בפרויקט ב-Cloud

מסוף Google Cloud

  1. במסוף Google Cloud, עוברים אל Billing. לוחצים על תפריט > חיוב > הפרויקטים שלי.

    כניסה לדף Billing for My Projects

  2. בקטע Select an organization (בחירת ארגון), בוחרים את הארגון שמשויך לפרויקט Google Cloud.
  3. בשורת הפרויקט, פותחים את התפריט Actions (), לוחצים על Change billing ובוחרים את החשבון לחיוב ב-Cloud.
  4. לוחצים על Set account.

CLI של gcloud

  1. כדי להציג רשימה של החשבונות לחיוב שזמינים לכם, מריצים את הפקודה:
    gcloud billing accounts list
  2. קישור חשבון לחיוב לפרויקט ב-Google Cloud:
    gcloud billing projects link PROJECT_ID --billing-account=BILLING_ACCOUNT_ID

    מחליפים את מה שכתוב בשדות הבאים:

    • PROJECT_ID הוא מזהה הפרויקט של פרויקט Cloud שרוצים להפעיל בו חיוב.
    • BILLING_ACCOUNT_ID הוא מזהה החשבון לחיוב שאליו רוצים לקשר את הפרויקט ב-Google Cloud.

הפעלת ממשקי ה-API

מסוף Google Cloud

  1. במסוף Google Cloud, מפעילים את Google Chat API,‏ Google Docs API,‏ Admin SDK API,‏ Google Workspace Marketplace SDK ו-Vertex AI API.

    הפעלת ממשקי ה-API

  2. מוודאים שמפעילים את ממשקי ה-API בפרויקט הנכון ב-Cloud ולוחצים על הבא.

  3. מוודאים שמפעילים את ממשקי ה-API הנכונים ולוחצים על הפעלה.

CLI של gcloud

  1. אם צריך, מגדירים את פרויקט Cloud הנוכחי לפרויקט שיצרתם באמצעות הפקודה gcloud config set project:

    gcloud config set project PROJECT_ID

    מחליפים את PROJECT_ID במזהה הפרויקט של פרויקט Cloud שיצרתם.

  2. מפעילים את Google Chat API,‏ Google Docs API,‏ Admin SDK API,‏ Google Workspace Marketplace SDK ו-Vertex AI API באמצעות הפקודה gcloud services enable:

    gcloud services enable chat.googleapis.com docs.googleapis.com admin.googleapis.com aiplatform.googleapis.com appsmarket-component.googleapis.com

הגדרת אימות והרשאה

אפליקציית Chat ניגשת ל-Chat API באמצעות פרטי הכניסה של אפליקציית Chat. האפליקציה ניגשת אל Admin SDK API ו-Google Docs API באמצעות פרטי הכניסה של המשתמש.

הגדרת אימות והרשאה של משתמשים

אימות והרשאה מאפשרים לאפליקציית Chat לגשת למשאבים ב-Google Workspace וב-Google Cloud כדי לעבד תגובה לאירוע. באופן ספציפי, אימות משתמשים משמש לקריאה ל-Google Docs API ול-Admin SDK API.

במדריך הזה, אתם מפרסמים את האפליקציה באופן פנימי בדומיין שלכם ב-Workspace, ולכן אפשר להשתמש במידע של placeholder. לפני שמפרסמים את האפליקציה באופן חיצוני, צריך להחליף את המידע של placeholder במידע אמיתי במסך ההסכמה.

  1. במסוף Google Cloud, נכנסים לתפריט > > Branding.

    מעבר לדף Branding

  2. אם כבר הגדרתם את, אתם יכולים לקבוע את ההגדרות הבאות של מסך ההסכמה ל-OAuth בקטעים Branding,‏ Audience וData Access. אם מופיעה ההודעה not configured yet, לוחצים על Get Started:

    1. בקטע App Information בשדה App name, מקלידים Incident Management.
    2. בקטע User support email, בוחרים את כתובת האימייל שלכם או קבוצת Google מתאימה.
    3. לוחצים על הבא.
    4. בקטע Audience, לוחצים על Internal. אם אי אפשר לבחור באפשרות פנימי, בוחרים באפשרות חיצוני.
    5. לוחצים על הבא.
    6. בקטע Contact Information, מזינים כתובת אימייל שאליה אפשר לשלוח התראות על שינויים בפרויקט.
    7. לוחצים על הבא.
    8. בקטע Finish, קוראים את המדיניות של Google בנושא נתוני משתמשים בשירותי API. אם אתם מסכימים, מסמנים את התיבה I agree to the Google API Services: User Data Policy.
    9. לוחצים על המשך.
    10. לוחצים על יצירה.
    11. אם בחרתם באפשרות חיצוני לסוג המשתמש, מוסיפים משתמשי בדיקה:
      1. לוחצים על קהל.
      2. בקטע משתמשי בדיקה, לוחצים על הוספת משתמשים.
      3. מזינים את כתובת האימייל שלכם ושל משתמשים מורשים אחרים לבדיקה, ואז לוחצים על שמירה.
  3. לוחצים על גישה לנתונים > הוספה או הסרה של היקפי הרשאה. מופיעה חלונית עם רשימה של היקפי גישה לכל API שהפעלתם בפרויקט ב-Google Cloud.

    1. בקטע Manually add scopes (הוספת היקפי הרשאה באופן ידני), מדביקים את היקפי ההרשאה הבאים:

      • https://www.googleapis.com/auth/documents
      • https://www.googleapis.com/auth/admin.directory.user.readonly
      • https://www.googleapis.com/auth/script.external_request
      • https://www.googleapis.com/auth/userinfo.email
      • https://www.googleapis.com/auth/cloud-platform
    2. לוחצים על הוספה לטבלה.

    3. לוחצים על עדכון.

    4. אחרי שבוחרים את ההיקפים שנדרשים לאפליקציה, לוחצים על שמירה בדף גישה לנתונים.

הגדרת אימות והרשאה לאפליקציה

אימות האפליקציה משמש לקריאה ל-Google Chat API.

איך יוצרים חשבון שירות במסוף Google Cloud

כדי ליצור חשבון שירות:

מסוף Google Cloud

  1. במסוף Google Cloud, לוחצים על סמל התפריט > IAM & Admin > Service Accounts (חשבונות שירות).

    לדף Service accounts

  2. לוחצים על יצירת חשבון שירות.
  3. ממלאים את פרטי חשבון השירות ולוחצים על יצירה והמשך.
  4. אופציונלי: מקצים תפקידים לחשבון השירות כדי לתת גישה למשאבים בפרויקט Google Cloud. פרטים נוספים זמינים במאמר הענקה, שינוי וביטול גישה למשאבים.
  5. לוחצים על המשך.
  6. אופציונלי: מזינים משתמשים או קבוצות שיכולים לנהל את חשבון השירות הזה ולבצע בו פעולות. פרטים נוספים זמינים במאמר ניהול התחזות לחשבון שירות.
  7. לוחצים על סיום. רושמים את כתובת האימייל של חשבון השירות.

CLI של gcloud

  1. יוצרים את חשבון השירות:
    gcloud iam service-accounts create SERVICE_ACCOUNT_NAME \
      --display-name="SERVICE_ACCOUNT_NAME"
  2. אופציונלי: מקצים תפקידים לחשבון השירות כדי לתת גישה למשאבים בפרויקט Google Cloud. פרטים נוספים זמינים במאמר הענקה, שינוי וביטול גישה למשאבים.

חשבון השירות מופיע בדף חשבון השירות. בשלב הבא, יוצרים מפתח פרטי לחשבון השירות.

יצירת מפתח פרטי

כדי ליצור ולהוריד מפתח פרטי לחשבון השירות, פועלים לפי השלבים הבאים:

  1. במסוף Google Cloud, לוחצים על סמל התפריט > IAM & Admin > Service Accounts (חשבונות שירות).

    לדף Service accounts

  2. בוחרים את חשבון השירות.
  3. לוחצים על מפתחות > הוספת מפתח > יצירת מפתח חדש.
  4. בוחרים באפשרות JSON ולוחצים על Create.

    זוג המפתחות הציבורי/הפרטי החדש נוצר ומורד למחשב שלכם כקובץ חדש. שומרים את קובץ ה-JSON שהורדתם בשם credentials.json בספריית העבודה. הקובץ הזה הוא העותק היחיד של המפתח. מידע על אחסון מאובטח של המפתח זמין במאמר ניהול מפתחות לחשבונות שירות.

  5. לוחצים על סגירה.

מידע נוסף על חשבונות שירות זמין במאמר בנושא חשבונות שירות במרכז העזרה של IAM ב-Google Cloud.

יצירת לקוח OAuth שתואם ל-Google Workspace Marketplace

כדי ליצור לקוח OAuth שתואם ל-Google Workspace Marketplace:

  1. במסוף Google Cloud, לוחצים על סמל התפריט > IAM & Admin > Service Accounts.

    לדף Service accounts

  2. לוחצים על חשבון השירות שיצרתם לאפליקציית Chat.

  3. לוחצים על הגדרות מתקדמות.

  4. לוחצים על יצירת לקוח OAuth שתואם ל-Google Workspace Marketplace.

  5. לוחצים על המשך.

תוצג הודעת אישור שנוצר לקוח OAuth שתואם ל-Google Workspace Marketplace.

יצירה ופריסה של אפליקציה ל-Chat

בקטע הבא, מעתיקים ומעדכנים פרויקט שלם בסקריפט של Google Apps שמכיל את כל קוד האפליקציה הנדרש לאפליקציית Chat, כך שאין צורך להעתיק ולהדביק כל קובץ בנפרד.

חלק מהפונקציות כוללות קו תחתון בסוף השם שלהן, כמו processSlashCommand_() מתוך ChatApp.gs. הקו התחתון מסתיר את הפונקציה מדף האינטרנט של אתחול האירוע כשהוא פתוח בדפדפן. מידע נוסף זמין במאמר בנושא פונקציות פרטיות.

‫Apps Script תומך בשני סוגי קבצים: .gs סקריפטים ו.html קבצים. כדי לעמוד בדרישות התמיכה האלה, קוד ה-JavaScript בצד הלקוח של האפליקציה נכלל בתוך תגי <script />, וקוד ה-CSS שלה נכלל בתוך תגי <style /> בתוך קובץ HTML.

אם רוצים, אפשר לראות את הפרויקט כולו ב-GitHub.

הצגת הקוד ב-GitHub

סקירה כללית של כל קובץ:

Consts.gs

הקובץ מגדיר קבועים שמופיעים בקובצי קוד אחרים, כולל מזהה פרויקט Cloud, מזהה מיקום Vertex AI, פרטי כניסה לאפליקציה של חשבון השירות ומזהה פקודת הלוכסן לסגירת אירוע.

הצגת הקוד Consts.gs

apps-script/incident-response-app-auth/Consts.gs
const PROJECT_ID = 'replace-with-your-project-id';
const CLOSE_INCIDENT_COMMAND_ID = 1;
const APP_CREDENTIALS = 'replace-with-your-app-credentials';
const APP_CREDENTIALS_SCOPES = 'https://www.googleapis.com/auth/chat.bot https://www.googleapis.com/auth/chat.app.memberships https://www.googleapis.com/auth/chat.app.spaces.create';
const VERTEX_AI_LOCATION_ID = 'us-central1';
const MODEL_ID = 'gemini-1.5-flash-002';
ChatApp.gs

מטפל באירועי אינטראקציה ב-Chat, כולל הודעות, קליקים על כרטיסים, פקודות עם לוכסנים ודיאלוגים. מגיב לפקודת הלוכס /closeIncident על ידי פתיחת תיבת דו-שיח לאיסוף פרטים על פתרון האירוע. קורא הודעות במרחב על ידי קריאה לשיטה spaces.messages.list ב-Chat API. קבלת מזהי משתמשים באמצעות שירות Admin SDK Directory ב-Apps Script.

הצגת הקוד ChatApp.gs

apps-script/incident-response-app-auth/ChatApp.gs
/**
 * Responds to a MESSAGE event in Google Chat.
 *
 * This app only responds to a slash command with the ID 1 ("/closeIncident").
 * It will respond to any other message with a simple "Hello" text message.
 *
 * @param {Object} event the event object from Google Chat
 */
function onMessage(event) {
  if (event.message.slashCommand) {
    return processSlashCommand_(event);
  }
  return { "text": "Hello from Incident Response app!" };
}

/**
 * Responds to a CARD_CLICKED event in Google Chat.
 *
 * This app only responds to one kind of dialog (Close Incident).
 *
 * @param {Object} event the event object from Google Chat
 */
function onCardClick(event) {
  if (event.isDialogEvent) {
    if (event.dialogEventType == 'SUBMIT_DIALOG') {
      return processSubmitDialog_(event);
    }
    return {
      actionResponse: {
        type: "DIALOG",
        dialogAction: {
          actionStatus: "OK"
        }
      }
    };
  }
}

/**
 * Responds to a MESSAGE event with a Slash command in Google Chat.
 *
 * This app only responds to a slash command with the ID 1 ("/closeIncident")
 * by returning a Dialog.
 *
 * @param {Object} event the event object from Google Chat
 */
function processSlashCommand_(event) {
  if (event.message.slashCommand.commandId != CLOSE_INCIDENT_COMMAND_ID) {
    return {
      "text": "Command not recognized. Use the command `/closeIncident` to close the incident managed by this space."
    };
  }
  const sections = [
    {
      header: "Close Incident",
      widgets: [
        {
          textInput: {
            label: "Please describe the incident resolution",
            type: "MULTIPLE_LINE",
            name: "description"
          }
        },
        {
          buttonList: {
            buttons: [
              {
                text: "Close Incident",
                onClick: {
                  action: {
                    function: "closeIncident"
                  }
                }
              }
            ]
          }
        }
      ]
    }
  ];
  return {
    actionResponse: {
      type: "DIALOG",
      dialogAction: {
        dialog: {
          body: {
            sections,
          }
        }
      }
    }
  };
}

/**
 * Responds to a CARD_CLICKED event with a Dialog submission in Google Chat.
 *
 * This app only responds to one kind of dialog (Close Incident).
 * It creates a Doc with a summary of the incident information and posts a message
 * to the space with a link to the Doc.
 *
 * @param {Object} event the event object from Google Chat
 */
function processSubmitDialog_(event) {
  const resolution = event.common.formInputs.description[""].stringInputs.value[0];
  const chatHistory = concatenateAllSpaceMessages_(event.space.name);
  const chatSummary = summarizeChatHistory_(chatHistory);
  const docUrl = createDoc_(event.space.displayName, resolution, chatHistory, chatSummary);
  return {
    actionResponse: {
      type: "NEW_MESSAGE",
    },
    text: `Incident closed with the following resolution: ${resolution}\n\nHere is the automatically generated post-mortem:\n${docUrl}`
  };
}

/**
 * Lists all the messages in the Chat space, then concatenate all of them into
 * a single text containing the full Chat history.
 *
 * For simplicity for this demo, it only fetches the first 100 messages.
 *
 * Messages with slash commands are filtered out, so the returned history will
 * contain only the conversations between users and not app command invocations.
 *
 * @return {string} a text containing all the messages in the space in the format:
 *          Sender's name: Message
 */
function concatenateAllSpaceMessages_(spaceName) {
  // Call Chat API method spaces.messages.list
  const response = Chat.Spaces.Messages.list(spaceName, { 'pageSize': 100 });
  const messages = response.messages;
  // Fetch the display names of the message senders and returns a text
  // concatenating all the messages.
  let userMap = new Map();
  return messages
    .filter(message => message.slashCommand === undefined)
    .map(message => `${getUserDisplayName_(userMap, message.sender.name)}: ${message.text}`)
    .join('\n');
}

/**
 * Obtains the display name of a user by using the Admin Directory API.
 *
 * The fetched display name is cached in the provided map, so we only call the API
 * once per user.
 *
 * If the user does not have a display name, then the full name is used.
 *
 * @param {Map} userMap a map containing the display names previously fetched
 * @param {string} userName the resource name of the user
 * @return {string} the user's display name
 */
function getUserDisplayName_(userMap, userName) {
  if (userMap.has(userName)) {
    return userMap.get(userName);
  }
  let displayName = 'Unknown User';
  try {
    const user = AdminDirectory.Users.get(
      userName.replace("users/", ""),
      { projection: 'BASIC', viewType: 'domain_public' });
    displayName = user.name.displayName ? user.name.displayName : user.name.fullName;
  } catch (e) {
    // Ignore error if the API call fails (for example, because it's an
    // out-of-domain user or Chat app)) and just use 'Unknown User'.
  }
  userMap.set(userName, displayName);
  return displayName;
}
ChatSpaceCreator.gs

מקבל את נתוני הטופס שהמשתמשים מזינים בדף האינטרנט של אתחול האירוע, ומשתמש בהם כדי להגדיר מרחב ב-Chat על ידי יצירה ואכלוס שלו, ואז מפרסם הודעה לגבי האירוע.

הצגת הקוד ChatSpaceCreator.gs

apps-script/incident-response-app-auth/ChatSpaceCreator.gs
/**
 * Handles an incident by creating a chat space, adding members, and posting a message.
 * All the actions are done using application credentials.
 *
 * @param {Object} formData - The data submitted by the user. It should contain the fields:
 *                           - title: The display name of the chat space.
 *                           - description: The description of the incident.
 *                           - users: A comma-separated string of user emails to be added to the space.
 * @return {string} The resource name of the new space.
 */
function handleIncident(formData) {
  const users = formData.users.trim().length > 0 ? formData.users.split(',') : [];
  const service = getService_();
  if (!service.hasAccess()) {
    console.error(service.getLastError());
    return;
   }
  const spaceName = createChatSpace_(formData.title, service);
  createHumanMembership_(spaceName, getUserEmail(), service);
  for (const user of users ){
    createHumanMembership_(spaceName, user, service);
  }
  createMessage_(spaceName, formData.description, service);
  return spaceName;
}
/**
 * Creates a chat space with application credentials.
 *
 * @param {string} displayName - The name of the chat space.
 * @param {object} service - The credentials of the service account.
 * @returns {string} The resource name of the new space.
*/
function createChatSpace_(displayName, service) {
  try {
    // For private apps, the alias can be used
    const my_customer_alias = "customers/my_customer";
    // Specify the space to create.
    const space = {
        displayName: displayName,
        spaceType: 'SPACE',                
        customer: my_customer_alias
    };
    // Call Chat API with a service account to create a message.
    const createdSpace = Chat.Spaces.create(
        space,
        {},
        // Authenticate with the service account token.
        {'Authorization': 'Bearer ' + service.getAccessToken()});
    return createdSpace.name;
  } catch (err) {
    // TODO (developer) - Handle exception.
    console.log('Failed to create space with error %s', err.message);
  }
}
/*
 * Creates a chat message with application credentials.
 *
 * @param {string} spaceName - The resource name of the space.
 * @param {string} message - The text to be posted.
 * @param {object} service - The credentials of the service account.
 * @return {string} the resource name of the new space.
 */
function createMessage_(spaceName, message, service) {
  try {
    // Call Chat API with a service account to create a message.
    const result = Chat.Spaces.Messages.create(
        {'text': message},
        spaceName,
        {},
        // Authenticate with the service account token.
        {'Authorization': 'Bearer ' + service.getAccessToken()});

  } catch (err) {
    // TODO (developer) - Handle exception.
    console.log('Failed to create message with error %s', err.message);
  }
}
/**
 * Creates a human membership in a chat space with application credentials.
 *
 * @param {string} spaceName - The resource name of the space.
 * @param {string} email - The email of the user to be added.
 * @param {object} service - The credentials of the service account.
 */
function createHumanMembership_(spaceName, email, service){
  try{
    const membership = {
      member: {
        name: 'users/'+email,
        // User type for the membership
        type: 'HUMAN'
      }
    };
    const result = Chat.Spaces.Members.create(
      membership,
      spaceName,
      {},
      {'Authorization': 'Bearer ' + service.getAccessToken()}
    );
  } catch (err){
    console.log('Failed to create membership with error %s', err.message)
  }

}

 /*
 * Creates a service for the service account.
 * @return {object}  - The credentials of the service account.
 */
function getService_() {
  return OAuth2.createService(APP_CREDENTIALS.client_email)
      .setTokenUrl('https://oauth2.googleapis.com/token')
      .setPrivateKey(APP_CREDENTIALS.private_key)
      .setIssuer(APP_CREDENTIALS.client_email)
      .setSubject(APP_CREDENTIALS.client_email)
      .setScope(APP_CREDENTIALS_SCOPES)
      .setPropertyStore(PropertiesService.getScriptProperties());
}
DocsApi.gs

קורא את Google Docs API כדי ליצור מסמך Google Docs ב-Google Drive של המשתמש, וכותב במסמך סיכום של פרטי האירוע שנוצר ב-VertexAiApi.gs.

הצגת הקוד DocsApi.gs

apps-script/incident-response-app-auth/DocsApi.gs
/**
 * Creates a Doc in the user's Google Drive and writes a summary of the incident information to it.
 *
 * @param {string} title The title of the incident
 * @param {string} resolution Incident resolution described by the user
 * @param {string} chatHistory The whole Chat history be included in the document
 * @param {string} chatSummary A summary of the Chat conversation to be included in the document
 * @return {string} the URL of the created Doc
 */
function createDoc_(title, resolution, chatHistory, chatSummary) {
  let doc = DocumentApp.create(title);
  let body = doc.getBody();
  body.appendParagraph(`Post-Mortem: ${title}`).setHeading(DocumentApp.ParagraphHeading.TITLE);
  body.appendParagraph("Resolution").setHeading(DocumentApp.ParagraphHeading.HEADING1);
  body.appendParagraph(resolution);
  body.appendParagraph("Summary of the conversation").setHeading(DocumentApp.ParagraphHeading.HEADING1);
  body.appendParagraph(chatSummary);
  body.appendParagraph("Full Chat history").setHeading(DocumentApp.ParagraphHeading.HEADING1);
  body.appendParagraph(chatHistory);
  return doc.getUrl();
}
VertexAiApi.gs

מסכם את השיחה במרחב ב-Chat באמצעות Vertex AI API. הסיכום הזה מתפרסם במסמך שנוצר במיוחד ב-DocsAPI.gs.

הצגת הקוד VertexAiApi.gs

apps-script/incident-response-app-auth/VertexAiApi.gs
/**
 * Summarizes a Chat conversation using the Vertex AI text prediction API.
 *
 * @param {string} chatHistory The Chat history that will be summarized.
 * @return {string} The content from the text prediction response.
 */


function summarizeChatHistory_(chatHistory) {

  const API_ENDPOINT = `https://${VERTEX_AI_LOCATION_ID}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/${VERTEX_AI_LOCATION_ID}/publishers/google/models/${MODEL_ID}:generateContent`;
  const prompt = "Summarize the following conversation between Engineers resolving an incident"
      + " in a few sentences. Use only the information from the conversation.\n\n" + chatHistory;
  // Get the access token.
  const accessToken = ScriptApp.getOAuthToken();

  const headers = {
    'Authorization': 'Bearer ' + accessToken,
    'Content-Type': 'application/json',
  };
  const payload = {
    'contents': {
      'role': 'user',
      'parts' : [
        {
          'text': prompt
        }
      ]
    }
  }
  const options = {
    'method': 'post',
    'headers': headers,
    'payload': JSON.stringify(payload),
    'muteHttpExceptions': true,
  };
  try {
    const response = UrlFetchApp.fetch(API_ENDPOINT, options);
    const responseCode = response.getResponseCode();
    const responseText = response.getContentText();

    if (responseCode === 200) {
      const jsonResponse = JSON.parse(responseText);
      console.log(jsonResponse)
      if (jsonResponse.candidates && jsonResponse.candidates.length > 0) {
        return jsonResponse.candidates[0].content.parts[0].text; // Access the summarized text
      } else {
        return "No summary found in response.";
      }

    } else {
      console.error("Vertex AI API Error:", responseCode, responseText);
      return `Error: ${responseCode} - ${responseText}`;
    }
  } catch (e) {
    console.error("UrlFetchApp Error:", e);
    return "Error: " + e.toString();
  }
}
WebController.gs

השרת מציג את האתר לאתחול האירוע.

הצגת הקוד WebController.gs

apps-script/incident-response-app-auth/WebController.gs
/**
 * Serves the web page from Index.html.
 */
function doGet() {
  return HtmlService
    .createTemplateFromFile('Index')
    .evaluate();
}

/**
 * Serves the web content from the specified filename.
 */
function include(filename) {
  return HtmlService
    .createHtmlOutputFromFile(filename)
    .getContent();
}

/**
 * Returns the email address of the user running the script.
 */
function getUserEmail() {
  return Session.getActiveUser().getEmail();
}
Index.html

קוד ה-HTML שמרכיב את אתר ההפעלה של האירוע.

הצגת הקוד Index.html

apps-script/incident-response-app-auth/Index.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <link href='https://fonts.googleapis.com/css?family=Roboto' rel='stylesheet'>
    <?!= include('Stylesheet'); ?>
  </head>
  <body>
    <div class="container">
      <div class="content">
        <h1>Incident Manager</h1>
        <form id="incident-form" onsubmit="handleFormSubmit(this)">
          <div id="form">
            <p>
              <label for="title">Incident title</label><br/>
              <input type="text" name="title" id="title" />
            </p>
            <p>
              <label for="users">Incident responders</label><br/>
              <small>
                Please enter a comma-separated list of email addresses of the users
                that should be added to the space.
                Do not include <?= getUserEmail() ?> as it will be added automatically.
              </small><br/>
              <input type="text" name="users" id="users" />
            </p>
            <p>
              <label for="description">Initial message</label></br>
              <small>This message will be posted after the space is created.</small><br/>
              <textarea name="description" id="description"></textarea>
            </p>
            <p class="text-center">
              <input type="submit" value="CREATE CHAT SPACE" />
            </p>
          </div>
          <div id="output" class="hidden"></div>
          <div id="clear" class="hidden">
            <input type="reset" value="CREATE ANOTHER INCIDENT" onclick="onReset()" />
          </div>
        </form>
      </div>
    </div>
    <?!= include('JavaScript'); ?>
  </body>
</html>
JavaScript.html

הפונקציה מטפלת בהתנהגות הטופס, כולל שליחות, שגיאות וניקויים, באתר לאתחול האירוע. היא נכללת ב-Index.html על ידי הפונקציה המותאמת אישית include ב-WebController.gs.

הצגת הקוד JavaScript.html

apps-script/incident-response-app-auth/JavaScript.html
<script>
  var formDiv = document.getElementById('form');
  var outputDiv = document.getElementById('output');
  var clearDiv = document.getElementById('clear');

  function handleFormSubmit(formObject) {
    event.preventDefault();
    outputDiv.innerHTML = 'Please wait while we create the space...';
    hide(formDiv);
    show(outputDiv);
    google.script.run
      .withSuccessHandler(updateOutput)
      .withFailureHandler(onFailure)
      .handleIncident(formObject);
  }

  function updateOutput(response) {
    var spaceId = response.replace('spaces/', '');
    outputDiv.innerHTML =
      '<p>Space created!</p><p><a href="https://mail.google.com/chat/#chat/space/'
        + spaceId
        + '" target="_blank">Open space</a></p>';
    show(outputDiv);
    show(clearDiv);
  }

  function onFailure(error) {
    outputDiv.innerHTML = 'ERROR: ' + error.message;
    outputDiv.classList.add('error');
    show(outputDiv);
    show(clearDiv);
  }

  function onReset() {
    outputDiv.innerHTML = '';
    outputDiv.classList.remove('error');
    show(formDiv);
    hide(outputDiv);
    hide(clearDiv);
  }

  function hide(element) {
    element.classList.add('hidden');
  }

  function show(element) {
    element.classList.remove('hidden');
  }
</script>
Stylesheet.html

ה-CSS של אתר ההפעלה של האירוע. הוא נכלל ב-Index.html על ידי הפונקציה המותאמת אישית include ב-WebController.gs.

הצגת הקוד Stylesheet.html

apps-script/incident-response-app-auth/Stylesheet.html
<style>
  * {
    box-sizing: border-box;
  }
  body {
    font-family: Roboto, Arial, Helvetica, sans-serif;
  }
  div.container {
    display: flex;
    justify-content: center;
    align-items: center;
    position: absolute;
    top: 0; bottom: 0; left: 0; right: 0;
  }
  div.content {
    width: 80%;
    max-width: 1000px;
    padding: 1rem;
    border: 1px solid #999;
    border-radius: 0.25rem;
    box-shadow: 0 2px 2px 0 rgba(66, 66, 66, 0.08), 0 2px 4px 2px rgba(66, 66, 66, 0.16);
  }
  h1 {
    text-align: center;
    padding-bottom: 1rem;
    margin: 0 -1rem 1rem -1rem;
    border-bottom: 1px solid #999;
  }
 #output {
    text-align: center;
    min-height: 250px;
  }
  div#clear {
    text-align: center;
    padding-top: 1rem;
    margin: 1rem -1rem 0 -1rem;
    border-top: 1px solid #999;
  }
  input[type=text], textarea {
    width: 100%;
    padding: 1rem 0.5rem;
    margin: 0.5rem 0;
    border: 0;
    border-bottom: 1px solid #999;
    background-color: #f0f0f0;
  }
  textarea {
    height: 5rem;
  }
  small {
    color: #999;
  }
  input[type=submit], input[type=reset] {
    padding: 1rem;
    border: none;
    background-color: #6200ee;
    color: #fff;
    border-radius: 0.25rem;
    width: 25%;
  }
  .hidden {
    display: none;
  }
  .text-center {
    text-align: center;
  }
  .error {
    color: red;
  }
</style>

איך מוצאים את מספר הפרויקט ואת מזהה הפרויקט ב-Cloud

  1. במסוף Google Cloud, נכנסים לפרויקט ב-Cloud.

    כניסה למסוף Google Cloud

  2. לוחצים על סמל ההגדרות והכלים > הגדרות הפרויקט.

  3. שימו לב לערכים בשדות מספר הפרויקט ומזהה הפרויקט. משתמשים בהם בקטעים הבאים.

יצירת פרויקט Apps Script

כדי ליצור פרויקט Apps Script ולקשר אותו לפרויקט Cloud:

  1. לוחצים על הלחצן הבא כדי לפתוח את פרויקט Apps Script של תגובה לאירועים באמצעות Google Chat.
    פתיחת הפרויקט
  2. לוחצים על סקירה כללית.
  3. בדף הסקירה הכללית, לוחצים על הסמל ליצירת עותק יצירת עותק.
  4. נותנים שם לעותק של פרויקט Apps Script:

    1. לוחצים על עותק של Respond to incidents with Google Chat (תגובה לאירועים באמצעות Google Chat).

    2. בשדה שם הפרויקט, כותבים Incident Management Chat app.

    3. לוחצים על Rename.

  5. בעותק של פרויקט Apps Script, עוברים לקובץ Consts.gs ומחליפים את YOUR_PROJECT_ID במזהה של פרויקט Cloud.

הגדרת פרויקט Cloud לפרויקט Apps Script

  1. בפרויקט Apps Script, לוחצים על הסמל של הגדרות הפרויקט הגדרות הפרויקט.
  2. בקטע פרויקט Google Cloud Platform (GCP)‎, לוחצים על שינוי הפרויקט.
  3. בקטע מספר הפרויקט ב-GCP, מדביקים את מספר הפרויקט ב-Cloud.
  4. לוחצים על הגדרת פרויקט. הפרויקט ב-Cloud והפרויקט ב-Apps Script מקושרים עכשיו.

יצירת פריסה של Apps Script

אחרי שכל הקוד מוכן, פורסים את פרויקט Apps Script. משתמשים במזהה הפריסה כשמגדירים את אפליקציית Chat ב-Google Cloud.

  1. ב-Apps Script, פותחים את הפרויקט של אפליקציית התגובה לאירוע.

    מעבר אל Apps Script

  2. לוחצים על פריסה > פריסה חדשה.

  3. אם האפשרויות תוסף ואפליקציית אינטרנט לא מסומנות, לוחצים על סוגי הפריסה הסמל של הגדרות הפרויקט לצד בחירת סוג ובוחרים באפשרויות תוסף ואפליקציית אינטרנט.

  4. בשדה תיאור, מזינים תיאור לגרסה הזו, כמו Complete version of incident management app.

  5. בקטע Execute as (הרצה בתור), בוחרים באפשרות User accessing the web app (משתמש שנכנס לאפליקציית האינטרנט).

  6. בקטע למי יש גישה, בוחרים באפשרות כל מי ששייך לארגון שלכם ב-Workspace, כאשר 'הארגון שלכם ב-Workspace' הוא השם של הארגון שלכם ב-Google Workspace.

  7. לוחצים על פריסה. ‫Apps Script מדווח על פריסה מוצלחת ומספק מזהה פריסה וכתובת URL לדף האינטרנט של אתחול האירוע.

  8. חשוב לרשום את כתובת ה-URL של אפליקציית האינטרנט כדי להיכנס אליה בהמשך כשמתחיל אירוע. מעתיקים את מזהה הפריסה. משתמשים במזהה הזה כשמגדירים את אפליקציית Chat במסוף Google Cloud.

  9. לוחצים על סיום.

הגדרת אפליקציית Chat במסוף Google Cloud

בקטע הזה נסביר איך להגדיר את Google Chat API במסוף Google Cloud עם מידע על אפליקציית Chat, כולל מזהה הפריסה שיצרתם זה עתה מפרויקט Apps Script.

  1. במסוף Google Cloud, לוחצים על תפריט > מוצרים נוספים > Google Workspace > ספריית מוצרים > Google Chat API > ניהול > הגדרה.

    כניסה להגדרות של Chat API

  2. מבטלים את הסימון של Build this Chat app as a Google Workspace add-on (פיתוח אפליקציית Chat כתוסף ל-Google Workspace). תיפתח תיבת דו-שיח שבה תתבקשו לאשר את הפעולה. בתיבת הדו-שיח, לוחצים על השבתה.

  3. בשדה App name, כותבים Incident Management.

  4. בקטע כתובת ה-URL של הדמות, מקלידים https://developers.google.com/chat/images/quickstart-app-avatar.png.

  5. בקטע תיאור, מקלידים Responds to incidents..

  6. לוחצים על המתג הפעלת תכונות אינטראקטיביות כדי להפעיל אותו.

  7. בקטע פונקציונליות, בוחרים באפשרות הצטרפות למרחבים ולשיחות קבוצתיות.

  8. בקטע הגדרות חיבור, בוחרים באפשרות Apps Script.

  9. בשדה Deployment ID (מזהה פריסה), מדביקים את מזהה הפריסה של Apps Script שהעתקתם קודם מהפריסה של פרויקט Apps Script.

  10. רושמים פקודה עם לוכסן שהאפליקציה המלאה של Chat משתמשת בה:

    1. בקטע Commands, לוחצים על Add a command.

    2. בשדה Command ID (מזהה הפקודה), מקלידים 1.

    3. בקטע תיאור, מקלידים Closes the incident being discussed in the space.

    4. בקטע סוג הפקודה, בוחרים באפשרות פקודה דרך שורת הפקודות.

    5. בשדה Slash command name, כותבים /closeIncident.

    6. בוחרים באפשרות הקישור פותח תיבת דו-שיח.

    7. לוחצים על סיום. פקודת הסלאש רשומה ומופיעה ברשימה.

  11. בקטע Visibility (חשיפה), בוחרים באפשרות Make this Chat app available to specific people and groups in Your Workspace Domain (הפיכת אפליקציית הצ'אט הזו לזמינה לאנשים ולקבוצות ספציפיים בדומיין שלכם ב-Workspace) ומזינים את כתובת האימייל.

  12. בקטע יומנים, בוחרים באפשרות רישום שגיאות ביומן.

  13. לוחצים על שמירה. מופיעה הודעה שההגדרה נשמרה, כלומר האפליקציה מוכנה לבדיקה.

קבלת אישור אדמין

כדי לקבל אישור מהאדמין, צריך להגדיר את אפליקציית Chat ב-SDK של Google Workspace Marketplace.

הגדרת אפליקציית Chat ב-Google Workspace Marketplace SDK

כדי להגדיר את אפליקציית Chat ב-SDK של Google Workspace Marketplace, פועלים לפי השלבים הבאים:

  1. במסוף Google Cloud, נכנסים אל תפריט > APIs & Services > Enabled APIs & services > Google Workspace Marketplace SDK > App Configuration.

    מעבר להגדרת האפליקציה

  2. ממלאים את הדף 'הגדרת אפליקציה'. האופן שבו מגדירים את אפליקציית Chat תלוי בקהל היעד ובגורמים אחרים. לקבלת עזרה בהשלמת דף הגדרת האפליקציה, אפשר לעיין במאמר בנושא הגדרת האפליקציה ב-Google Workspace Marketplace SDK. לצורך המדריך הזה, מזינים את המידע הבא:

    1. בקטע הרשאות גישה לאפליקציה, בוחרים באפשרות פרטי.
    2. בקטע הגדרות התקנה, בוחרים באפשרות התקנה לאדמין.
    3. בקטע שילובים של אפליקציות, בוחרים באפשרות אפליקציה ל-Chat.
    4. בקטע OAuth scopes (היקפי הרשאות OAuth), מזינים את היקפי ההרשאות הבאים:
      • https://www.googleapis.com/auth/chat.app.spaces
      • https://www.googleapis.com/auth/chat.app.memberships
    5. בקטע פרטי המפתח, מזינים את שם המפתח, כתובת ה-URL של אתר המפתח וכתובת האימייל של המפתח.
    6. לוחצים על שמירת הטיוטה.

אחרי שמגדירים את האפליקציה, מעדכנים את דף האפליקציה בחנות:

  1. במסוף Google Cloud, נכנסים אל תפריט > APIs & Services > Enabled APIs & services > Google Workspace Marketplace SDK > Store Listing.
  2. בקטע פרטי האפליקציה, בוחרים באפשרות 'פיתוח אתרים' כקטגוריה.
  3. בקטע Graphic Assets (נכסים גרפיים), מעלים סמלים של אפליקציות בפורמטים הנדרשים.
  4. בקטע צילומי מסך, מעלים צילום מסך של האפליקציה.
  5. בקטע קישורי תמיכה, ממלאים את כתובת ה-URL של התנאים וההגבלות, כתובת ה-URL של מדיניות הפרטיות וכתובת ה-URL של התמיכה.
  6. בקטע הפצה, בוחרים את האזורים שבהם האפליקציה תהיה זמינה.
  7. לוחצים על פרסום.

קבלת אישור אדמין

אחרי שמגדירים את חשבון השירות לקבלת אישור מהאדמין, צריך לקבל אישור מאדמין ב-Google Workspace. כדי לעשות את זה, האדמין צריך לפעול לפי השלבים שמפורטים במאמר הגדרת הרשאה לאפליקציות ל-Chat.

בדיקת אפליקציית Chat

כדי לבדוק את אפליקציית Chat לניהול אירועים, יוזמים אירוע מדף האינטרנט ומוודאים שאפליקציית Chat פועלת כמצופה:

  1. עוברים אל כתובת ה-URL של אפליקציית האינטרנט של פריסת Apps Script.

  2. כש-Apps Script מבקש הרשאה לגשת לנתונים שלכם, לוחצים על בדיקת ההרשאות, נכנסים לחשבון Google המתאים בדומיין Google Workspace שלכם ולוחצים על אישור.

  3. ייפתח דף האינטרנט של אתחול האירוע. מזינים את פרטי הבדיקה:

    1. בשדה Incident title, כותבים The First Incident.
    2. אופציונלי: בשדה Incident responders (מגיבים לאירועים), מזינים את כתובות האימייל של חברי הצוות שמגיבים לאירועים. הם צריכים להיות משתמשים עם חשבון Google Chat בארגון Google Workspace שלכם, אחרת לא תוכלו ליצור את המרחב. אל תזינו את כתובת האימייל שלכם, כי היא נכללת באופן אוטומטי.
    3. בהודעה ראשונית, מקלידים Testing the incident management Chat app.
  4. לוחצים על יצירת מרחב בצ'אט. תופיע ההודעה creating space.

  5. אחרי שיוצרים את המרחב, מופיעה הודעה Space created!. לוחצים על פתיחת המרחב כדי לפתוח את המרחב ב-Chat בכרטיסייה חדשה.

  6. אם רוצים, אתם וצוות התגובה לאירוע יכולים לשלוח הודעות במרחב. האפליקציה מסכמת את ההודעות האלה באמצעות Vertex AI ומשתפת מסמך רטרוספקטיבי.

  7. כדי לסיים את הטיפול באירוע ולהתחיל בתהליך הפתרון, מקלידים /closeIncident בחדר הצ'אט. תיפתח תיבת דו-שיח של ניהול אירועים.

  8. בקטע סגירת האירוע, מזינים תיאור של פתרון האירוע, כמו Test complete.

  9. לוחצים על סגירת האירוע.

אפליקציית ניהול האירועים מציגה את ההודעות במרחב, מסכמת אותן באמצעות Vertex AI, מדביקה את הסיכום במסמך Google Docs ומשתפת את המסמך במרחב.

הסרת המשאבים

כדי להימנע מחיובים בחשבון Google Cloud בגלל השימוש במשאבים שנעשה במסגרת המדריך הזה, מומלץ למחוק את פרויקט Cloud.

  1. במסוף Google Cloud, עוברים לדף Manage resources. לוחצים על תפריט > IAM & Admin > Manage Resources.

    כניסה ל-Resource Manager

  2. ברשימת הפרויקטים, בוחרים את הפרויקט שרוצים למחוק ולוחצים על Delete .
  3. כדי למחוק את הפרויקט, כותבים את מזהה הפרויקט בתיבת הדו-שיח ולוחצים על Shut down.