Building an AI Slack Bot using Vertex Generative AI

Taneli Leppä
Google Cloud - Community
5 min readMay 13, 2023

Last time we built a Google Cloud Deploy bot using Pubsub2Inbox and Cloud Deploy. This time we’ll switch gears a little and build a completely serverless Slack bot that uses Vertex AI Generative Studio models to add a bit of smarts to the bot.

To enable Slack bot building, I’ve built three new components for Pubsub2Inbox:

  • Slack output, for sending messages,
  • Slack processor, for fetching existing messages and conversations,
  • Json2Pubsub, a tool for taking all kinds of webhooks, verifying them and posting the results into a Pub/Sub topic. It can perform Slack validation using the HMAC SHA256 algorithm and it can be automatically deployed alongside Pubsub2Inbox using Terraform.

Adding an app (a bot) to Slack

To set up a Slack app, we’ll start off in api.slack.com and add a new app there. We’ll need to jot down a few details, such as tokens and signing keys, plus set up the event webhook.

First, under basic information, we’ll need to capture the signing secret (this is used to verify that incoming requests to our Json2Pubsub webhook are coming from Slack actually):

Then we will need the bot token (can be found in OAuth & Permissions section):

We’ll also make sure that our bot has the correct OAuth scopes for the token, so it can read messages and reply back:

We’ll configure the Events webhook after we’ve deployed the code.

Deploying via Terraform

First, clone the Pubsub2Inbox repository. You’ll find the example code under examples/vertexgenai-slack-bot/. Change to that directory and create a terraform.tfvars file containing the following:

project_id        = "<your-project-id>"
region = "europe-west1"
slack_token = "xoxb-............................MB"
slack_signing_key = "8e..........................2f"
slack_app_id = "A0.......L"

You also have a few additional settings in variables.tf, such as creation of a custom role with vastly smaller permissions (just one) than the default Vertex AI User IAM role, but that is on by default.

After this, all you need to do is:

terraform init
terraform apply
....
Apply complete! Resources: 3 added, 2 changed, 3 destroyed.

Outputs:

instructions = <<EOT
Please use the following webhook URL for Slack event webhook:
https://vertex-genai-bot-json2pubsub-abcdefghijk-lm.a.run.app

It outputs the Json2Pubsub webhook address, which is already made publicly accessible (it will verify that all requests sent to it are done by Slack and it only has Pub/Sub publisher to the specific topic on Google Cloud).

You can also check that you have two Cloud Functions deployed:

We can now configure the webhook in api.slack.com under Event subscriptions:

That’s it, we can now add the Slack bot to our channel:

If all went well, you can just mention the bot on the channel and ask it a question:

You can check the slack-bot.yaml that is in the same directory as the Terraform code to modify any of the Vertex AI settings or do other things.

If you are not getting a proper reply, look at the Cloud Functions logs for clues.

We’ll discuss a few technical details next.

Receiving Slack events

Whenever the bot is mentioned one a public channel, a message is sent to Json2Pubsub, which validates that it’s coming from Slack and submits it to the Pub/Sub topic, allowing Pubsub2Inbox to pick it up and send a reply. (Please note that the bot also gets its own messages as events, but those have an app_id field in the event structure)

The following is an example of the event:

{
"api_app_id": "A056L1L8RFL",
"authorizations": [
{
"enterprise_id": null,
"is_bot": true,
"is_enterprise_install": false,
"team_id": "T156KL1RBJF",
"user_id": "U056HF3L53P"
}
],
"event": {
"blocks": [
{
"block_id": "cBH",
"elements": [
{
"elements": [
{
"type": "user",
"user_id": "U056HE3L13P"
},
{
"text": " Hello World!",
"type": "text"
}
],
"type": "rich_text_section"
}
],
"type": "rich_text"
}
],
"channel": "C056KQ1TLUA",
"client_msg_id": "2a2f0dd6-94d9-4bd2-a4e1-2642bb928aa7",
"event_ts": "1683890230.468149",
"team": "T056KL1RAJF",
"text": "\u003c@U056HE3L13P\u003e Hello World!",
"ts": "1683890230.468149",
"type": "app_mention",
"user": "U0579EPJN72"
},
"event_context": "4-ey...In0",
"event_id": "Ev057E3B27FF",
"event_time": 1683890230,
"is_ext_shared_channel": false,
"team_id": "T056KL1RAJF",
"token": "7n...........N",
"type": "event_callback"
}

The bot picks up next messages and looks up the threaded conversation history using conversations.replies Slack API, then processes the messages in a suitable format for Vertex AI and then performs the prediction request. The reply is posted back in the thread and you can continue the conversation normally (please note some replies can be cut off with max tokens setting):

How does the bot work?

The bot pipeline in Pubsub2Inbox comprises of several steps:

  • Message parsing: removing nickname and Slack mrkdwn for the message
  • Slack conversation history: fetches the history of a threaded conversation from Slack API and converts it to an array suitable for Vertex AI consumption
  • Calling Vertex AI chat model prediction
  • Posts the reply from Vertex AI back to the conversation via Slack API

The Vertex requests looks like this:

Context contains the “prompt” and messages the chat history. You can customize the prompt by editing the slack-bot.yaml file.

Did it work? Do you have an issue or want to send feedback? Reach out to me on Twitter for example: https://twitter.com/rosmo

--

--