As SDETs, we’re not just testing software, we’re enabling teams to deliver hight quality software faster. What if your team could trigger builds, get CI/CD updates, or file tickets for failures, all without leaving Slack? In this post, we’ll build a lightweight Slack App in under an hour that acts as a proactive helper bot. It’ll automate boring and repetitive tasks, improve developer experience, and let your team focus on what really matters.
Why do we need bots?
SDETs today are expected to do much more than just write automated tests, we’re enablers of quality at speed. Our mission is to identify friction in the software delivery lifecycle and eliminate it with smart, scalable solutions. One of the most overlooked ways to do this is by building internal tools that developers actually use, and in this blog I will be exploring automation tools with Slack.
Slack has become the command center for engineering teams. Builds fail, PRs get merged, incidents are reported — all in real time, right in the chat. Yet, when something breaks or a test pipeline fails, people still context-switch: open tabs, navigate dashboards, run CLI commands, or chase flaky tests manually. This wastes time and disrupts focus.
Now imagine this instead:
- If a test suite fails, your bot suggests opening a Jira ticket, and files it in one click.
- A developer runs /build status to check if their PR is blocked.
- Your bot replies with the CI status, last run details, and a rerun button.
- Test reports, flaky test stats, even triage checklists, all delivered where people already work.
As SDETs, we have the skills to make this possible. By building Slack bots that automate common tasks, we’re not only speeding up delivery, we’re making quality more visible, debugging faster, and developer lives easier. This isn’t about replacing tools, it’s about bridging them. Slack becomes the interface, and your bot becomes the glue.
Prerequisites: What you need before we start
Before we jump into building our Slack bot, let’s make sure your environment is ready. You don’t need much, this setup is lightweight and approachable for any SDET or developer with basic scripting experience.
Here’s what you’ll need:
✅ Local Setup
- Node.js (v18+) – We’ll be using Bolt for JavaScript (TypeScript) Template App, Slack’s official framework.
- A Slack Workspace – You need admin access to create and install a custom app. You can setup your own Slack workspace for free.
- Basic JavaScript/TypeScript Knowledge – No need to be a frontend expert, but familiarity helps.
🛠️ Tooling You Can Integrate
- Jira Cloud for ticket creation
- GitHub and GitHub Actions
The idea here is to keep your first version simple and fast, then expand with integrations your team will value most. Once you’ve got your tools lined up, we’ll move straight into building the bot.
Getting started: Your first Slack App in 15 minutes
If you’ve never built a Slack bot before, don’t worry, the official guide from Slack is excellent. I recommend cloning the repository linked above - Bolt for JavaScript (TypeScript) Template App. Follow the tutorial to setup the Slack App properly.
Here’s what you need:
- Signing Secret – Found under your app’s Basic Information page, used to verify requests from Slack.
- Bot Token (with
channels:history, chat:write, commands
) – Generated when you install your app to your workspace, it allows your bot to interact with Slack APIs. This token starts withxoxb-
- App Token (with
connections:write
scope) – Required if you use the Socket Mode, which is what we will use for local development. This token starts withxapp-
- Under Event Subscriptions, toggle the switch labeled Enable Events (
message.channels
,message.groups
,message.im
,message.mpim
)
These secrets are stored in your .env file:
SLACK_CLIENT_ID=YOUR_SLACK_CLIENT_ID
SLACK_CLIENT_SECRET=YOUR_SLACK_CLIENT_SECRET
SLACK_SIGNING_SECRET=YOUR_SLACK_SIGNING_SECRET
SLACK_APP_TOKEN=YOUR_SLACK_APP_TOKEN
SLACK_BOT_TOKEN=YOUR_SLACK_BOT_TOKEN
Once all of the secrets are setup, run npm install
and then npm start
to start the server. You will see the following message in your terminal: bolt-app ⚡️ Bolt app is running! ⚡️. In order to interact with the bot, you will have to add the App as Integration in some of your channels. And just like that, you’ll have a local bot up and running, ready to respond to commands or events. Send hi
message and you should receive back hi, how are you?
. Isn’t this cool? You just created your first simple Slack bot automation.
It took me about 15 minutes to go from zero to a working Slack bot that replied to
hi
in a dev channel — including setup, running it locally, and seeing my first interaction in Slack.
Create Slack command
With your Slack App up and running, it’s time to make it do something useful, something your team would actually use. Let’s extend the bolt-ts-starter-template with a command that developers and SDETs will appreciate right away:
🚀 /jira
– Instantly create Jira tickets from Slack
How many times have you seen a test failure or CI issue in Slack, and someone has to open Jira manually to report it? Let’s eliminate that.
We’ll build a /jira report
command that will create simple task ticket:
- title: Short summary
- description: Full details
/jira report `Failed checkout flow` `Checkout fails for guest users on Firefox`
Step 1: Create slash command in the Slack App configuration
In order for the Slack to be able to recognize the /jira
command we will have to create a slash command in the App configuration.
- Go to https://api.slack.com/apps:
- Choose your app.
- Navigate to: Features → Slash Commands
- Ensure you’ve added /jira as a command.
- Command: /jira
- Short Description: Interacts with Jira
- Usage Hint:
Title
Description
- Make sure Socket Mode is enabled so you won’t need to specify a Request URL.
Step 2: Jira setup
You can integrate this with your actual Jira instance via REST API. For this example, I created my own Jira instance and I have setup a small team projects with project named DEV.
In order to connect to Jira, we will need to setup an API key and few other env vars. Navigate to https://id.atlassian.com/manage-profile/security/api-tokens
to create API key. Add the following env vars to the .env file:
JIRA_HOST=YOUR_JIRA_HOST
JIRA_USERNAME=YOUR_JIRA_USERNAME
JIRA_API_TOKEN=YOUR_JIRA_TOKEN
JIRA_PROJECT_KEY=QA
JIRA_ISSUE_TYPE=Task
Step 3: Coding and logic
Now that we have the connection details, let’s first install jira-client, date-fns and some types by running:
npm i jira-client
npm i date-fns
npm i --save-dev @types/jira-client
Now comes the fun part — writing the actual logic. We will first create a minimal wrapper around the Jira API. It will provide us with basic code to create ticket, and we can extand it as we want in the future, based on our needs. The generateADFDescription gives us rich-text formatting in Jira (ADF = Atlassian Document Format) which is needed for the request to work.
// commands/jira-helper.ts
import JiraClient from 'jira-client'
import { config } from 'dotenv'
config()
const jiraConfig = {
host: process.env.JIRA_HOST!,
username: process.env.JIRA_USER!,
token: process.env.JIRA_API_TOKEN!,
projectKey: process.env.JIRA_PROJECT_KEY!,
issueType: process.env.JIRA_ISSUE_TYPE!,
labels: ['automated', 'slack-bot']
}
const jira = new JiraClient({
protocol: 'https',
host: jiraConfig.host,
username: jiraConfig.username,
password: jiraConfig.token,
apiVersion: '3',
strictSSL: true
})
export const generateADFDescription = (text: string) => ({
type: 'doc',
version: 1,
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text
}
]
}
]
})
export const addNewIssue = async (issueData: any) => {
try {
return await jira.addNewIssue(issueData)
} catch (error) {
console.error('Error creating Jira issue:', error)
throw error
}
}
export const getJiraConfig = () => jiraConfig
Next let’s wire up the actual slash command using Bolt:
import type { AllMiddlewareArgs, SlackCommandMiddlewareArgs } from '@slack/bolt'
import { format } from 'date-fns'
import { config } from 'dotenv'
import {
addNewIssue,
generateADFDescription,
getJiraConfig
} from './jira-helper'
config()
const jiraCommandCallback = async ({
ack,
command,
respond
}: AllMiddlewareArgs & SlackCommandMiddlewareArgs) => {
try {
await ack()
const rawArgs = command.text.match(/`[^`]*`|\S+/g) || []
const args = rawArgs.map((arg) => arg.replace(/^`(.*)`$/, '$1'))
const actionType = args[0]
switch (actionType) {
case 'report':
await respond(`Creating Jira report`)
const title = args[1]
const description = args[2]
const summary = `${title} - ${format(
new Date(),
'yyyy-MM-dd HH:mm:ss'
)}`
const JiraConfig = getJiraConfig()
const adfDescription = generateADFDescription(description)
const issueData = {
fields: {
project: {
key: JiraConfig.projectKey
},
summary,
description: adfDescription,
issuetype: {
name: JiraConfig.issueType
},
labels: JiraConfig.labels
}
}
const issue = await addNewIssue(issueData)
await respond(
`Jira ticket created: <https://${JiraConfig.host}/browse/${issue.key}|${issue.key}>`
)
break
default:
await respond('❌ Invalid action. Use `/jira report`.')
break
}
} catch (error) {
await respond('❌ Failed to create the JIRA ticket. Check logs or config.')
}
}
export default jiraCommandCallback
Finally, in your /commands/index.ts
folder add the callback:
// commands/index.ts
import type { App } from '@slack/bolt'
import sampleCommandCallback from './sample-command'
import JiraCommandCallback from './jira-command'
const register = (app: App) => {
app.command('/sample-command', sampleCommandCallback)
app.command('/jira', JiraCommandCallback)
}
export default { register }
Step 4: Test the integration
Now that you’ve wired up the command and connected Jira, it’s time to test it live. Run npm start
to start the Slack bot, head over to any Slack channel where your bot is added and try the command:
/jira report `Failed checkout flow` `Checkout fails for guest users on Firefox`
You should see a response like: Jira ticket created: DEV-123
. Open the Jira link and navigate to the ticket to verify the ticket details.
🎉 Boom - you just created a Jira ticket from Slack!
Step 5: Deployment
We implemented and tested the Slack bot locally, and in order for this to work beyond your local machine, you’ll need to host it somewhere public (so Slack can reach it) and configure it properly for production. I am not going to go into the details as part of this blog, but there are two options that you can use: deploy via socket mode or deploy via HTTP endpoint. You can use Render, AWS Lambda or AWS App Runner to do this. Read more about this in the official Slack documentation.
Summary
In just under an hour, we built a fully functional Slack automation bot, one that can respond to messages, accept slash commands, and even create Jira tickets from inside Slack. This isn’t just a cool side project, it’s a practical tool that streamlines developer workflows, reduces context-switching, and brings test reporting, CI status, and issue tracking closer to where your team already collaborates.
By leveraging tools like Slack’s Bolt, APIs and a bit of TypeScript, you’ve seen how fast it is to go from idea to real automation. The best part? You now have a foundation that can be extended with GitHub integrations, flaky test tracking, release status reports, or whatever your team needs most. SDETs today are enablers — and with automation like this, we can remove friction and let engineers focus on building great software. 🚀