Respond to incidents with Google Chat, Vertex AI, and Apps Script

This tutorial shows how to make a Google Chat app that responds to incidents in real time. When responding to an incident, the app creates and populates a Chat space, facilitates incident resolution with messages, slash commands, and dialogs, and uses AI to summarize the incident response in a Google Docs document.

An incident is an event that requires the immediate attention of a team of people to resolve. Examples of incidents include:

  • A time-sensitive case is created in a Customer Relationship Management (CRM) platform, requiring a service team to collaborate on a resolution.
  • A system goes offline, alerting a group of site reliability engineers (SREs) so that they can work together to bring it back online.
  • A high magnitude earthquake occurs, and emergency workers need to coordinate their response.

For the purposes of this tutorial, the incident alert starts when someone reports the incident with a button click from a web page. The web page simulates an incident by asking users to enter basic incident information: title, description, and email addresses of the responders.

See the incident management Chat app in action:

  • The website that starts an incident.
    Figure 1. The website where someone can report an incident.
  • Notification that the incident Chat space is created.
    Figure 2. Notification that the incident Chat space is created.
  • The incident response Chat space.
    Figure 3. The incident response Chat space.
  • Resolving the incident with a slash command.
    Figure 4. Resolving the incident with a slash command.
  • Incident resolution dialog.
    Figure 5. Incident resolution dialog.
  • Incident resolution Google Docs document shared in space.
    Figure 6. Incident resolution Google Docs document shared in space.
  • The AI summary incident resolution Google Doc.
    Figure 7. The AI summary incident resolution Google Docs document.

Prerequisites

If you need any of these prerequisites turned on for your organization, ask your Google Workspace administrator to turn them on:

  • A Business or Enterprise Google Workspace account with access to Google Chat .
  • To have Directory (contact sharing) turned on for Google Workspace. The incident app uses the directory to look up the incident responders' contact info, like name and email address. Incident responders must be users with a Google Chat account in your Google Workspace organization.

Objectives

  • Build a Chat app that responds to incidents.
  • Help users respond to incidents by doing the following:
    • Creating incident response spaces.
    • Posting messages summarizing incidents and responses.
    • Supporting collaboration with interactive Chat app features.
  • Summarize conversations and resolutions with Vertex AI.

Architecture

The following diagram shows the architecture of the Google Workspace and Google Cloud resources used by the incident response Google Chat app.

Architecture of the incident response Google Chat app

The architecture shows how the incident response Google Chat app processes an incident and resolution.

  1. A user starts an incident from an external website hosted on Apps Script.

  2. The website sends an asynchronous HTTP request to the Google Chat app, also hosted on Apps Script.

  3. The incident response Google Chat app processes the request:

    1. The Apps Script Admin SDK service gets team member information, like user ID and email address.

    2. With a set of HTTP requests to Chat API using the Apps Script Advanced Chat service, the incident response Google Chat app creates an incident Chat space, populates it with team members, and sends a message to the space.

  4. Team members discuss the incident in the Chat space.

  5. A team member invokes a slash command to signal a resolution to the incident.

    1. An HTTP call to Chat API using the Apps Script Advanced Chat service lists all the Chat space's messages.

    2. Vertex AI receives the listed messages and generates a summary.

    3. The Apps Script DocumentApp service creates a Docs document and adds Vertex AI's summary to the document.

    4. The incident response Google Chat app calls Chat API to send a message sharing a link to the summary Docs document.

Prepare the environment

This section shows how to create and configure a Google Cloud project for the Chat app.

Create a Google Cloud project

Google Cloud console

  1. In the Google Cloud console, go to Menu > IAM & Admin > Create a Project .

    Go to Create a Project

  2. In the Project Name field, enter a descriptive name for your project.

    Optional: To edit the Project ID , click Edit . The project ID can't be changed after the project is created, so choose an ID that meets your needs for the lifetime of the project.

  3. In the Location field, click Browse to display potential locations for your project. Then, click Select .
  4. Click Create . The Google Cloud console navigates to the Dashboard page and your project is created within a few minutes.

gcloud CLI

In one of the following development environments, access the Google Cloud CLI ( gcloud ):

  • Cloud Shell : To use an online terminal with the gcloud CLI already set up, activate Cloud Shell.
    Activate Cloud Shell
  • Local Shell : To use a local development environment, install and initialize the gcloud CLI.
    To create a Cloud project, use the gcloud projects create command:
      gcloud projects create PROJECT_ID 
     
     
    
    Replace PROJECT_ID by setting the ID for the project you want to create.

Enable billing for the Cloud project

Google Cloud console

  1. In the Google Cloud console, go to Billing . Click Menu > Billing > My Projects .

    Go to Billing for My Projects

  2. In Select an organization , choose the organization associated with your Google Cloud project.
  3. In the project row, open the Actions menu ( ), click Change billing , and choose the Cloud Billing account.
  4. Click Set account .

gcloud CLI

  1. To list available billing accounts, run:
      gcloud billing accounts list 
     
    
  2. Link a billing account with a Google Cloud project:
      gcloud billing projects link PROJECT_ID 
    --billing-account= BILLING_ACCOUNT_ID 
     
     
    

    Replace the following:

    • PROJECT_ID is the Project ID for the Cloud project for which you want to enable billing.
    • BILLING_ACCOUNT_ID is the billing account ID to link with the Google Cloud project.

Enable the APIs

Google Cloud console

  1. In the Google Cloud console, enable the Google Chat API, the Google Docs API, the Admin SDK API, and the Vertex AI API.

    Enable the APIs

  2. Confirm that you're enabling the APIs in the correct Cloud project, then click Next.

  3. Confirm that you're enabling the correct APIs, then click Enable.

gcloud CLI

  1. If necessary, set the current Cloud project to the one you created with the gcloud config set project command:

     gcloud  
    config  
     set 
      
    project  
     PROJECT_ID 
     
    

    Replace PROJECT_ID with the Project IDof the Cloud project you created.

  2. Enable the Google Chat API, Google Docs API, Admin SDK API, and Vertex AI API with the gcloud services enable command:

     gcloud  
    services  
     enable 
      
    chat.googleapis.com  
    docs.googleapis.com  
    admin.googleapis.com  
    aiplatform.googleapis.com 
    

Set up authentication and authorization

Authentication and authorization lets the Chat app access resources in Google Workspace and Google Cloud to process an incident response.

In this tutorial, you publish the app internally so it's OK to use placeholder information. Before publishing the app externally, replace placeholder information with real information for the consent screen.

  1. In the Google Cloud console, go to Menu > APIs & Services > OAuth consent screen.

    Go to OAuth consent screen

  2. Under User type, select Internal, then click Create.

  3. In App name, type Incident Management .

  4. In User support email, select your email address or an appropriate Google group.

  5. Under Developer contact information, enter your email address.

  6. Click Save and Continue.

  7. Click Add or Remove Scopes. A panel appears with a list of scopes for each API that you've enabled in your Cloud project.

  8. Under Manually add scopes, paste the following scopes:

    • https://www.googleapis.com/auth/chat.spaces.create
    • https://www.googleapis.com/auth/chat.memberships
    • https://www.googleapis.com/auth/chat.memberships.app
    • https://www.googleapis.com/auth/chat.messages
    • 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
  9. Click Add to Table.

  10. Click Update.

  11. Click Save and Continue.

  12. Review the app registration summary, then click Back to Dashboard.

Create and deploy the Chat app

In the following section, you copy and update an entire Apps Script project that contains all the required application code for your Chat app, so there's no need to copy and paste each file.

Some functions include underscores at the end of their names, like processSlashCommand_() from ChatApp.gs . The underscore hides the function from the incident initialization web page when it's open in a browser. For more information, see Private functions .

Apps Script supports two file types, .gs scripts and .html files. To abide by this support, the app's client-side JavaScript is included inside <script /> tags and its CSS is included inside <style /> tags inside an HTML file.

Optionally, you can view the entire project on GitHub.

View on GitHub

Here's an overview of each file:

Consts.gs

Defines constants referenced by other code files, including your Cloud project ID, Vertex AI location ID, and the slash command ID for closing an incident.

View Consts.gs code

apps-script/incident-response/Consts.gs
 const 
  
 PROJECT_ID 
  
 = 
  
 ' 
 replace 
 - 
 with 
 - 
 your 
 - 
 project 
 - 
 id 
 ' 
 ; 
 const 
  
 VERTEX_AI_LOCATION_ID 
  
 = 
  
 ' 
 us 
 - 
 central1 
 ' 
 ; 
 const 
  
 CLOSE_INCIDENT_COMMAND_ID 
  
 = 
  
 1 
 ; 
ChatApp.gs

Handles Chat interaction events, including messages, card clicks, slash commands, and dialogs. Responds to the /closeIncident slash command by opening a dialog to gather incident resolution details. Reads messages in the space by calling the spaces.messages.list method in the Chat API. Gets user IDs using the Admin SDK Directory service in Apps Script.

View ChatApp.gs code

apps-script/incident-response/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

Receives form data users enter on the incident initialization web page, and uses it to set up a Chat space by creating and populating it, and then posts a message about the incident.

View ChatSpaceCreator.gs code

apps-script/incident-response/ChatSpaceCreator.gs
 /** 
 * Creates a space in Google Chat with the provided title and members, and posts an 
 * initial message to it. 
 * 
 * @param {Object} formData the data submitted by the user. It should contain the fields 
 *                          title, description, and users. 
 * @return {string} the resource name of the new space. 
 */ 
 function 
  
 createChatSpace 
 ( 
 formData 
 ) 
  
 { 
  
 const 
  
 users 
  
 = 
  
 formData 
 . 
 users 
 . 
 trim 
 (). 
 length 
 > 
 0 
  
 ? 
  
 formData 
 . 
 users 
 . 
 split 
 ( 
 ' 
 , 
 ' 
 ) 
  
 : 
  
 []; 
  
 const 
  
 spaceName 
  
 = 
  
 setUpSpace_ 
 ( 
 formData 
 . 
 title 
 , 
  
 users 
 ); 
  
 addAppToSpace_ 
 ( 
 spaceName 
 ); 
  
 createMessage_ 
 ( 
 spaceName 
 , 
  
 formData 
 . 
 description 
 ); 
  
 return 
  
 spaceName 
 ; 
 } 
 /** 
 * Creates a space in Google Chat with the provided display name and members. 
 * 
 * @return {string} the resource name of the new space. 
 */ 
 function 
  
 setUpSpace_ 
 ( 
 displayName 
 , 
  
 users 
 ) 
  
 { 
  
 const 
  
 memberships 
  
 = 
  
 users 
 . 
 map 
 ( 
 email 
  
 = 
>  
 ({ 
  
 member 
 : 
  
 { 
  
 name 
 : 
  
 ` 
 users 
 / 
 $ 
 { 
 email 
 } 
 ` 
 , 
  
 type 
 : 
  
 "HUMAN" 
  
 } 
  
 })); 
  
 const 
  
 request 
  
 = 
  
 { 
  
 space 
 : 
  
 { 
  
 displayName 
 : 
  
 displayName 
 , 
  
 spaceType 
 : 
  
 "SPACE" 
 , 
  
 externalUserAllowed 
 : 
  
 true 
  
 }, 
  
 memberships 
 : 
  
 memberships 
  
 }; 
  
 // Call Chat API method spaces.setup 
  
 const 
  
 space 
  
 = 
  
 Chat 
 . 
 Spaces 
 . 
 setup 
 ( 
 request 
 ); 
  
 return 
  
 space 
 . 
 name 
 ; 
 } 
 /** 
 * Adds this Chat app to the space. 
 * 
 * @return {string} the resource name of the new membership. 
 */ 
 function 
  
 addAppToSpace_ 
 ( 
 spaceName 
 ) 
  
 { 
  
 const 
  
 request 
  
 = 
  
 { 
  
 member 
 : 
  
 { 
  
 name 
 : 
  
 "users/app" 
 , 
  
 type 
 : 
  
 "BOT" 
  
 } 
  
 }; 
  
 // Call Chat API method spaces.members.create 
  
 const 
  
 membership 
  
 = 
  
 Chat 
 . 
 Spaces 
 . 
 Members 
 . 
 create 
 ( 
 request 
 , 
  
 spaceName 
 ); 
  
 return 
  
 membership 
 . 
 name 
 ; 
 } 
 /** 
 * Posts a text message to the space on behalf of the user. 
 * 
 * @return {string} the resource name of the new message. 
 */ 
 function 
  
 createMessage_ 
 ( 
 spaceName 
 , 
  
 text 
 ) 
  
 { 
  
 const 
  
 request 
  
 = 
  
 { 
  
 text 
 : 
  
 text 
  
 }; 
  
 // Call Chat API method spaces.messages.create 
  
 const 
  
 message 
  
 = 
  
 Chat 
 . 
 Spaces 
 . 
 Messages 
 . 
 create 
 ( 
 request 
 , 
  
 spaceName 
 ); 
  
 return 
  
 message 
 . 
 name 
 ; 
 } 
DocsApi.gs

Calls the Google Docs API to create a Google Docs document in a user's Google Drive and writes a summary of the incident information, created in VertexAiApi.gs , to the document.

View DocsApi.gs code

apps-script/incident-response/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

Summarizes the conversation in the Chat space using Vertex AI. This summary is posted in a specially-created document in DocsAPI.gs .

View VertexAiApi.gs code

apps-script/incident-response/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 
  
 prompt 
  
 = 
  
 "Summarize the following conversation between Engineers resolving an incident" 
  
 + 
  
 " in a few sentences. Use only the information from the conversation.\n\n" 
  
 + 
  
 chatHistory 
 ; 
  
 const 
  
 request 
  
 = 
  
 { 
  
 instances 
 : 
  
 [ 
  
 { 
  
 prompt 
 : 
  
 prompt 
  
 } 
  
 ], 
  
 parameters 
 : 
  
 { 
  
 temperature 
 : 
  
 0.2 
 , 
  
 maxOutputTokens 
 : 
  
 256 
 , 
  
 topK 
 : 
  
 40 
 , 
  
 topP 
 : 
  
 0.95 
  
 } 
  
 } 
  
 const 
  
 fetchOptions 
  
 = 
  
 { 
  
 method 
 : 
  
 ' 
 POST 
 ' 
 , 
  
 headers 
 : 
  
 { 
  
 Authorization 
 : 
  
 ' 
 Bearer 
  
 ' 
  
 + 
  
 ScriptApp 
 . 
 getOAuthToken 
 () 
  
 }, 
  
 contentType 
 : 
  
 ' 
 application 
 / 
 json 
 ' 
 , 
  
 payload 
 : 
  
 JSON 
 . 
 stringify 
 ( 
 request 
 ) 
  
 } 
  
 const 
  
 response 
  
 = 
  
 UrlFetchApp 
 . 
 fetch 
 ( 
  
 ` 
 https 
 : 
 //${VERTEX_AI_LOCATION_ID}-aiplatform.googleapis.com/v1` 
  
 + 
  
 ` 
 / 
 projects 
 / 
 $ 
 { 
 PROJECT_ID 
 }/ 
 locations 
 / 
 $ 
 { 
 VERTEX_AI_LOCATION_ID 
 } 
 ` 
  
 + 
  
 "/publishers/google/models/text-bison:predict" 
 , 
  
 fetchOptions 
 ); 
  
 const 
  
 payload 
  
 = 
  
 JSON 
 . 
 parse 
 ( 
 response 
 . 
 getContentText 
 ()); 
  
 return 
  
 payload 
 . 
 predictions 
 [ 
 0 
 ]. 
 content 
 ; 
 } 
WebController.gs

Serves the incident initialization website.

View WebController.gs code

apps-script/incident-response/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

The HTML comprising the incident initialization website.

View Index.html code

apps-script/incident-response/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

Handles form behavior including submits, errors, and clears, for the incident initialization website. It's included into Index.html by the custom include function in WebController.gs .

View JavaScript.html code

apps-script/incident-response/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)
      .createChatSpace(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

The CSS for the incident initialization website. It's included into Index.html by the custom include function in WebController.gs .

View Stylesheet.html code

apps-script/incident-response/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>

Find your Cloud project number and ID

  1. In the Google Cloud console, go to your Cloud project.

    Go to Google Cloud console

  2. Click Settings and Utilities > Project settings.

  3. Note the values in the Project numberand Project IDfields. You use them in the following sections.

Create the Apps Script project

To create an Apps Script project and connect it with your Cloud project:

  1. Click the following button to open the Respond to incidents with Google ChatApps Script project.
    Open the project
  2. Click Overview.
  3. On the overview page, clickThe icon for making a copy Make a copy.
  4. Name your copy of the Apps Script project:

    1. Click Copy of Respond to incidents with Google Chat.

    2. In Project title, type Incident Management Chat app .

    3. Click Rename.

  5. In your copy of the Apps Script project, go to the Consts.gs file and replace YOUR_PROJECT_ID with the ID of your Cloud project.

Set the Apps Script project's Cloud project

  1. In your Apps Script project, clickThe icon for project settings Project Settings.
  2. Under Google Cloud Platform (GCP) Project, click Change project.
  3. In GCP project number, paste the project number of your Cloud project.
  4. Click Set project. The Cloud project and Apps Script project are now connected.

Create an Apps Script deployment

Now that all the code is in place, deploy the Apps Script project. You use the deployment ID when you configure the Chat app in the Google Cloud.

  1. In Apps Script, open the incident response app's project.

    Go to Apps Script

  2. Click Deploy> New deployment.

  3. If Add-onand Web apparen't already selected, next to Select type, click deployment typesThe icon for project settingsand select Add-onand Web app.

  4. In Description, enter a description for this version, like Complete version of incident management app .

  5. In Execute as, select User accessing the web app

  6. In Who has access, select Anyone within your Workspace organization, where "your Workspace organization" is the name of your Google Workspace organization.

  7. Click Deploy. Apps Script reports successful deployment and provides a deployment ID and a URL for the incident initialization web page.

  8. Make note of the Web appURL to visit later when you start an incident. Copy the Deployment ID. You use this ID while configuring the Chat app in Google Cloud console.

  9. Click Done.

Configure the Chat app in the Google Cloud console

This section shows how to configure the Google Chat API in the Google Cloud console with information about your Chat app, including the ID of the deployment that you just created from your Apps Script project.

  1. In the Google Cloud console, click Menu > More products > Google Workspace > Product Library > Google Chat API > Manage > Configuration .

    Go to Chat API configuration

  2. In App name, type Incident Management .

  3. In Avatar URL, type https://developers.google.com/chat/images/quickstart-app-avatar.png .

  4. In Description, type Responds to incidents. .

  5. Click the Enable Interactive featurestoggle to the on position.

  6. Under Functionality, select Receive 1:1 messages, Join spaces and group conversations.

  7. Under Connection settings, select Apps Script.

  8. In Deployment ID, paste the Apps Script Deployment ID that you copied earlier from the Apps Script project deployment.

  9. Register a slash command that the fully implemented Chat app uses:

    1. Under Slash commands, click Add a slash command.

    2. In Name, type /closeIncident .

    3. In Command ID, type 1 .

    4. In Description, type Closes the incident being discussed in the space.

    5. Select Opens a dialog.

    6. Click Done. The slash command is registered and listed.

  10. Under Visibility, select Make this Chat app available to specific people and groups in Your Workspace Domainand enter your email address.

  11. Under Logs, select Log errors to Logging.

  12. Click Save. A configuration saved message appears, meaning the app is ready to test.

Test the Chat app

To test the incident management Chat app, initiate an incident from the web page and verify that the Chat app works as expected:

  1. Go to the Apps Script deployment web app URL.

  2. When Apps Script asks permission to access your data, click Review permissions, sign in with an appropriate Google Account in your Google Workspace domain, and click Allow.

  3. The incident initialization web page opens. Enter test information:

    1. In Incident title, type The First Incident .
    2. Optionally, in Incident responders, enter the email addresses of your fellow incident responders. They must be users with a Google Chat account in your Google Workspace organization or space creation fails. Don't enter your own email address because it's included automatically.
    3. In Initial message, type Testing the incident management Chat app.
  4. Click Create Chat Space. A creating space message appears.

  5. After the space is created, a Space created! message appears. Click Open space, which opens the space in Chat in a new tab.

  6. Optionally, you and the other incident responders can send messages in the space. The app summarizes these messages using Vertex AI and shares a retrospective document.

  7. To end the incident response and begin the resolution process, in the Chat space, type /closeIncident . An incident management dialog opens.

  8. In Close incident, enter a description for the incident resolution, like Test complete .

  9. Click Close Incident.

The Incident Management app lists the messages in the space, summarizes them with Vertex AI, pastes the summary in a Google Docs document, and shares the document in the space.

Clean up

To avoid incurring charges to your Google Cloud account for the resources used in this tutorial, we recommend that you delete the Cloud project.

  1. In the Google Cloud console, go to the Manage resources page. Click Menu > IAM & Admin > Manage Resources .

    Go to Resource Manager

  2. In the project list, select the project you want to delete and then click Delete .
  3. In the dialog, type the project ID and then click Shut down to delete the project.