Build an HTTP Google Chat app

This page explains how to create an HTTP Chat app. There are different ways to implement this architecture. On Google Cloud, you can use Cloud Functions, Cloud Run, and App Engine. In this quickstart, you write and deploy a Cloud Function that the Chat app uses to respond to a user's message.

With this architecture, you configure Chat to integrate with Google Cloud or an on-premises server by using HTTP, as shown in the following diagram:

Architecture of a Chat app using a web service in an on-premises server.

In the preceding diagram, a user interacting with an HTTP Chat app has the following flow of information:

  1. A user sends a message in Chat to a Chat app, either in a direct message or in a Chat space.
  2. An HTTP request is sent to a web server that is either a cloud or on-premises system that contains the Chat app logic.
  3. Optionally, the Chat app logic can integrate with Google Workspace services (like Calendar and Sheets), other Google services (like Maps, YouTube, and Vertex AI), or other web services (like a project management system or ticketing tool).
  4. The web server sends an HTTP response back to the Chat app service in Chat.
  5. The response is delivered to the user.
  6. Optionally, the Chat app can call the Chat API to asynchronously post messages or perform other operations.

This architecture provides you the flexibility to use existing libraries and components that already exist in your system because these Chat apps can be designed using different programming languages.

Objectives

  • Set up your environment.
  • Create and deploy a Cloud Function.
  • Publish the app to Chat.
  • Test the app.

Prerequisites

Set up the environment

Before using Google APIs, you need to turn them on in a Google Cloud project. You can turn on one or more APIs in a single Google Cloud project.
  • In the Google Cloud console, enable the Google Chat API, Cloud Build API, Cloud Functions API, Cloud Pub/Sub API, Cloud Logging API, Artifact Registry API, and Cloud Run API.

    Enable the APIs

Create and deploy a Cloud Function

Create and deploy a Cloud Function that generates a Chat card with the sender's display name and avatar image. When the Chat app receives a message, it runs the function and responds with the card.

To create and deploy the function for your Chat app, complete the following steps:

Node.js

  1. In the Google Cloud console, go to the Cloud Functions page:

    Go to Cloud Functions

    Make sure that the project for your Chat app is selected.

  2. Click Create Function.

  3. On the Create function page, set up your function:

    1. In Environment, select 2nd gen.
    2. In Function name, enter QuickStartChatApp.
    3. In Region, select a region.
    4. Under Authentication, select Require authentication.
    5. Click Next.
  4. In Runtime, select the most recent version of Node.js.

  5. In Source code, select Inline Editor.

  6. In Entry point, delete the default text and enter avatarApp.

  7. Replace the contents of index.js with the following code:

    node/avatar-app/index.js
    // The ID of the slash command "/about".
    // It's not enabled by default, set to the actual ID to enable it. You need to
    // use the same ID as set in the Google Chat API configuration.
    const ABOUT_COMMAND_ID = "";
    
    /**
     * Google Cloud Function that responds to messages sent from a
     * Google Chat space.
     *
     * @param {Object} req Request sent from Google Chat space
     * @param {Object} res Response to send back
     */
    exports.avatarApp = function avatarApp(req, res) {
      if (req.method === 'GET' || !req.body.message) {
        return res.send('Hello! This function is meant to be used ' +
          'in a Google Chat Space.');
      }
    
      // Stores the Google Chat event as a variable.
      const event = req.body;
    
      // Checks for the presence of a slash command in the message.
      if (event.message.slashCommand) {
        // Executes the slash command logic based on its ID.
        // Slash command IDs are set in the Google Chat API configuration.
        switch (event.message.slashCommand.commandId) {
          case ABOUT_COMMAND_ID:
            return res.send({
              privateMessageViewer: event.user,
              text: 'The Avatar app replies to Google Chat messages.'
            });
        }
      }
    
      const sender = req.body.message.sender.displayName;
      const image = req.body.message.sender.avatarUrl;
      const data = createMessage(sender, image);
      res.send(data);
    };
    
    /**
     * Creates a card with two widgets.
     * 
     * @param {string} displayName the sender's display name
     * @param {string} avatarUrl the URL for the sender's avatar
     * @return {Object} a card with the user's avatar.
     */
    function createMessage(displayName, avatarUrl) {
      return {
        text: 'Here\'s your avatar',
        cardsV2: [{
          cardId: 'avatarCard',
          card: {
            name: 'Avatar Card',
            header: {
              title: `Hello ${displayName}!`,
            },
            sections: [{ widgets: [{
              textParagraph: { text: 'Your avatar picture: ' }
            }, {
              image: { imageUrl: avatarUrl }
            }]}]
          }
        }]
      };
    }

  8. Click Deploy.

Python

  1. In the Google Cloud console, go to the Cloud Functions page:

    Go to Cloud Functions

    Make sure that the project for your Chat app is selected.

  2. Click Create Function.

  3. On the Create function page, set up your function:

    1. In Environment, select 2nd gen.
    2. In Function name, enter QuickStartChatApp.
    3. In Region, select a region.
    4. Under Authentication, select Require authentication.
    5. Click Next.
  4. In Runtime, select the most recent version of Python.

  5. In Source code, select Inline Editor.

  6. In Entry point, delete the default text and enter avatar_app.

  7. Replace the contents of main.py with the following code:

    python/avatar-app/main.py
    from typing import Any, Mapping
    
    import flask
    import functions_framework
    
    # The ID of the slash command "/about".
    # It's not enabled by default, set to the actual ID to enable it. You need to
    # use the same ID as set in the Google Chat API configuration.
    ABOUT_COMMAND_ID = ""
    
    @functions_framework.http
    def avatar_app(req: flask.Request) -> Mapping[str, Any]:
      """Google Cloud Function that handles requests from Google Chat
    
      Args:
          flask.Request: the request
    
      Returns:
          Mapping[str, Any]: the response
      """
      if req.method == "GET":
        return "Hello! This function must be called from Google Chat."
    
      request_json = req.get_json(silent=True)
    
      # Checks for the presence of a slash command in the message.
      if "slashCommand" in request_json["message"]:
        # Executes the slash command logic based on its ID.
        # Slash command IDs are set in the Google Chat API configuration.
        if request_json["message"]["slashCommand"]["commandId"] == ABOUT_COMMAND_ID:
          return {
            "privateMessageViewer": request_json["user"],
            "text": 'The Avatar app replies to Google Chat messages.'
          }
    
      display_name = request_json["message"]["sender"]["displayName"]
      avatar = request_json["message"]["sender"]["avatarUrl"]
      response = create_message(name=display_name, image_url=avatar)
      return response
    
    
    def create_message(name: str, image_url: str) -> Mapping[str, Any]:
      """Google Cloud Function that handles requests from Google Chat
    
      Args:
          str name: the sender's display name.
          str image_url: the URL for the sender's avatar.
    
      Returns:
          Mapping[str, Any]: a card with the user's avatar.
      """
      return {
        "text": "Here's your avatar",
        "cardsV2": [{
          "cardId": "avatarCard",
          "card": {
              "name": "Avatar Card",
              "header": { "title": f"Hello {name}!" },
              "sections": [{
                "widgets": [{
                  "textParagraph": { "text": "Your avatar picture:" }
                }, {
                  "image": { "imageUrl": image_url }
                }]
              }]
          }
        }]
      }

  8. Click Deploy.

Java

  1. In the Google Cloud console, go to the Cloud Functions page:

    Go to Cloud Functions

    Make sure that the project for your Chat app is selected.

  2. Click Create Function.

  3. On the Create function page, set up your function:

    1. In Environment, select 2nd gen.
    2. In Function name, enter QuickStartChatApp.
    3. In Region, select a region.
    4. Under Authentication, select Require authentication.
    5. Click Next.
  4. In Runtime, select the most recent version of Java.

  5. In Source code, select Inline Editor.

  6. In Entry point, delete the default text and enter App.

  7. Rename src/main/java/com/example/Example.java to src/main/java/App.java.

  8. Replace the contents of App.java with the following code:

    java/avatar-app/src/main/java/App.java
    import java.util.List;
    
    import com.google.api.services.chat.v1.model.CardWithId;
    import com.google.api.services.chat.v1.model.GoogleAppsCardV1Card;
    import com.google.api.services.chat.v1.model.GoogleAppsCardV1CardHeader;
    import com.google.api.services.chat.v1.model.GoogleAppsCardV1Image;
    import com.google.api.services.chat.v1.model.GoogleAppsCardV1Section;
    import com.google.api.services.chat.v1.model.GoogleAppsCardV1TextParagraph;
    import com.google.api.services.chat.v1.model.GoogleAppsCardV1Widget;
    import com.google.api.services.chat.v1.model.Message;
    import com.google.cloud.functions.HttpFunction;
    import com.google.cloud.functions.HttpRequest;
    import com.google.cloud.functions.HttpResponse;
    import com.google.gson.Gson;
    import com.google.gson.JsonObject;
    
    public class App implements HttpFunction {
      private static final Gson gson = new Gson();
    
      // The ID of the slash command "/about".
      // It's not enabled by default, set to the actual ID to enable it. You need to
      // use the same ID as set in the Google Chat API configuration.
      private static final String ABOUT_COMMAND_ID = "";
    
      @Override
      public void service(HttpRequest request, HttpResponse response) throws Exception {
        JsonObject body = gson.fromJson(request.getReader(), JsonObject.class);
    
        if (request.getMethod().equals("GET") || !body.has("message")) {
          response.getWriter().write("Hello! This function must be called from Google Chat.");
          return;
        }
    
        // Checks for the presence of a slash command in the message.
        if (body.getAsJsonObject("message").has("slashCommand")) {
          // Executes the slash command logic based on its ID.
          // Slash command IDs are set in the Google Chat API configuration.
          JsonObject slashCommand = body.getAsJsonObject("message").getAsJsonObject("slashCommand");
          switch (slashCommand.get("commandId").getAsString()) {
            case ABOUT_COMMAND_ID:
            JsonObject aboutMessage = new JsonObject();
            aboutMessage.addProperty("text", "The Avatar app replies to Google Chat messages.");
            aboutMessage.add("privateMessageViewer", body.getAsJsonObject("user"));
              response.getWriter().write(gson.toJson(aboutMessage));
              return;
          }
        }
    
        JsonObject sender = body.getAsJsonObject("message").getAsJsonObject("sender");
        String displayName = sender.has("displayName") ? sender.get("displayName").getAsString() : "";
        String avatarUrl = sender.has("avatarUrl") ? sender.get("avatarUrl").getAsString() : "";
        Message message = createMessage(displayName, avatarUrl);
        response.getWriter().write(gson.toJson(message));
      }
    
      Message createMessage(String displayName, String avatarUrl) {
        GoogleAppsCardV1CardHeader cardHeader = new GoogleAppsCardV1CardHeader();
        cardHeader.setTitle(String.format("Hello %s!", displayName));
    
        GoogleAppsCardV1TextParagraph textParagraph = new GoogleAppsCardV1TextParagraph();
        textParagraph.setText("Your avatar picture: ");
    
        GoogleAppsCardV1Widget avatarWidget = new GoogleAppsCardV1Widget();
        avatarWidget.setTextParagraph(textParagraph);
    
        GoogleAppsCardV1Image image = new GoogleAppsCardV1Image();
        image.setImageUrl(avatarUrl);
    
        GoogleAppsCardV1Widget avatarImageWidget = new GoogleAppsCardV1Widget();
        avatarImageWidget.setImage(image);
    
        GoogleAppsCardV1Section section = new GoogleAppsCardV1Section();
        section.setWidgets(List.of(avatarWidget, avatarImageWidget));
    
        GoogleAppsCardV1Card card = new GoogleAppsCardV1Card();
        card.setName("Avatar Card");
        card.setHeader(cardHeader);
        card.setSections(List.of(section));
    
        CardWithId cardWithId = new CardWithId();
        cardWithId.setCardId("previewLink");
        cardWithId.setCard(card);
    
        Message message = new Message();
        message.setText("Here's your avatar");
        message.setCardsV2(List.of(cardWithId));
    
        return message;
      }
    }

  9. Replace the contents of pom.xml with the following code:

    java/avatar-app/pom.xml
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>com.google.chat</groupId>
      <artifactId>avatar-app</artifactId>
      <version>1.0-SNAPSHOT</version>
    
      <properties>
        <maven.compiler.target>17</maven.compiler.target>
        <maven.compiler.source>17</maven.compiler.source>
      </properties>
    
      <dependencies>
        <dependency>
          <groupId>com.google.cloud.functions</groupId>
          <artifactId>functions-framework-api</artifactId>
          <version>1.0.1</version>
        </dependency>
    
        <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.9.1</version>
        </dependency>
    
        <!-- https://mvnrepository.com/artifact/com.google.apis/google-api-services-chat -->
        <dependency>
          <groupId>com.google.apis</groupId>
          <artifactId>google-api-services-chat</artifactId>
          <version>v1-rev20230115-2.0.0</version>
        </dependency>
      </dependencies>
    
      <!-- Required for Java 11 functions in the inline editor -->
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
              <excludes>
                <exclude>.google/</exclude>
              </excludes>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </project>

  10. Click Deploy.

The Cloud Functions detail page opens, and your function appears with two progress indicators: one for the build and one for the service. When both progress indicators disappear and are replaced with a check mark, your function is deployed and ready.

Authorize Google Chat to invoke your function

To Authorize Google Chat to invoke your function, add the Google Chat service account with the Cloud Run Invoker role.

  1. In the Google Cloud console, go to the Cloud Run page:

    Go to Cloud Run

  2. In the Cloud Run services list, select the checkbox next to the receiving function. (Don't click the function itself.)

  3. Click Permissions. The Permissions panel opens.

  4. Click Add principal.

  5. In New principals, enter chat@system.gserviceaccount.com.

  6. In Select a role, select Cloud Run > Cloud Run Invoker.

  7. Click Save.

Publish the app to Google Chat

After the Cloud Function is deployed, follow these steps to turn it into a Google Chat app:

  1. In the Google Cloud console, click Menu > Cloud Functions.

    Go to Cloud Functions

    Make sure that the project for which you enabled Cloud Functions is selected.

  2. In the list of functions, click QuickStartChatApp.

  3. Click the Triggers tab.

  4. Under HTTPS, copy the URL.

  5. Search for "Google Chat API" and click Google Chat API, then click Manage.

    Go to Chat API

  6. Click Configuration and set up the Google Chat app:

    1. In App name, enter Quickstart App.
    2. In Avatar URL, enter https://developers.google.com/chat/images/quickstart-app-avatar.png.
    3. In Description, enter Quickstart app.
    4. Under Functionality, select Receive 1:1 messages and Join spaces and group conversations.
    5. Under Connection settings, select HTTP endpoint URL and paste the URL for the Cloud Function trigger into the box.
    6. In Authentication Audience, select HTTP endpoint URL.
    7. Under Visibility, select Make this Google Chat app available to specific people and groups in your domain and enter your email address.
    8. Under Logs, select Log errors to Logging.
  7. Click Save.

The Chat app is ready to receive and respond to messages on Chat.

Test your Chat app

To test your Chat app, open a direct message space with the Chat app and send a message:

  1. Open Google Chat using the Google Workspace account that you provided when you added yourself as a trusted tester.

    Go to Google Chat

  2. Click New chat.
  3. In the Add 1 or more people field, type the name of your Chat app.
  4. Select your Chat app from the results. A direct message opens.

  5. In the new direct message with the app, type Hello and press enter.

The Chat app's response contains a card message that displays the sender's name and avatar image, as demonstrated in the following image:

Chat app responding with a card featuring the sender's display name and avatar
image

To add trusted testers and learn more about testing interactive features, see Test interactive features for Google Chat apps.

Troubleshoot

When a Google Chat app or card returns an error, the Chat interface surfaces a message saying "Something went wrong." or "Unable to process your request." Sometimes the Chat UI doesn't display any error message, but the Chat app or card produces an unexpected result; for example, a card message might not appear.

Although an error message might not display in the Chat UI, descriptive error messages and log data are available to help you fix errors when error logging for Chat apps is turned on. For help viewing, debugging, and fixing errors, see Troubleshoot and fix Google Chat errors.

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.