This guide explains how to set up and use the CRISP-T chat bot, which lets researchers interact with CRISP-T from Microsoft Teams and Slack using natural-language commands.
The bot acts as a bridge between Teams/Slack and the CRISP-T web UI server (crisp-ui). It uses the Chat SDK (@chat-adapter/teams + @chat-adapter/slack) to handle messages from both platforms and forwards commands to the crisp-ui REST API.
Teams User ──► Teams Chat ──┐
├──► CRISP-T Bot (Node.js) ──► crisp-ui (Python) ──► CRISP-T Engine
Slack User ──► Slack Channel ─┘
| Requirement | Version |
|---|---|
| Node.js | ≥ 18 |
| npm | ≥ 9 |
| Python | ≥ 3.10 |
crisp-t[copilot] |
latest |
| Microsoft Azure account | (for Teams) |
| Slack workspace with admin access | (for Slack) |
cd integration
npm install
npm run buildcp .env.example .env
# Edit .env and fill in your credentialsKey variables:
| Variable | Description | Default |
|---|---|---|
TEAMS_APP_ID |
Microsoft App ID from Azure Bot registration | (required for Teams) |
TEAMS_APP_PASSWORD |
Client secret from Azure App registration | (required for Teams) |
SLACK_BOT_TOKEN |
Slack Bot User OAuth Token (xoxb-...) |
(required for Slack) |
SLACK_SIGNING_SECRET |
Slack App signing secret | (required for Slack) |
TEAMS_APP_TENANT_ID |
Tenant ID (leave blank for multi-tenant) | (optional) |
CRISP_UI_URL |
URL where crisp-ui is running |
http://127.0.0.1:5000 |
CRISP_DEFAULT_MODEL |
Default AI model for new sessions | gpt-4.1 |
PORT |
Port the bot webhook server listens on | 3978 |
- Sign in to the Azure Portal.
- Search for Azure Bot and click Create.
- Fill in:
- Bot handle: choose a unique name (e.g.,
crisp-t-bot) - Subscription / Resource Group: your existing group
- Microsoft App Type:
Multi-tenant
- Bot handle: choose a unique name (e.g.,
- Under Microsoft App ID, select Create new Microsoft App ID.
- Click Review + Create, then Create.
- Open the new Azure Bot resource.
- Under Configuration, copy the Microsoft App ID → set as
TEAMS_APP_ID. - Click Manage password (links to the App registration).
- Under Certificates & secrets, create a new Client secret → set as
TEAMS_APP_PASSWORD.
- In the Azure Bot resource, select Channels.
- Click Microsoft Teams and follow the prompts to enable it.
- Save the configuration.
Once your bot is reachable from the internet (see Exposing the bot):
- In the Azure Bot resource, select Configuration.
- Set the Messaging endpoint to
https://<your-public-domain>/api/messages. - Save.
- In the Azure Bot resource, select Channels → Microsoft Teams → Open in Teams.
- In Teams, click Add to install the bot.
- You can now @-mention the bot in any channel or chat with it directly.
- Go to api.slack.com/apps and click Create New App.
- Select From scratch, give it a name (e.g.,
crisp-t-bot) and choose your workspace.
- Under OAuth & Permissions, add the following Bot Token Scopes:
app_mentions:readchat:writeim:historyim:readim:write
- Click Install to Workspace and copy the Bot User OAuth Token → set as
SLACK_BOT_TOKEN.
- Under Basic Information, find the Signing Secret → set as
SLACK_SIGNING_SECRET.
Once your bot is reachable from the internet (see Exposing the bot):
- Under Event Subscriptions, toggle Enable Events on.
- Set the Request URL to
https://<your-public-domain>/slack/events. - Under Subscribe to bot events, add:
app_mentionmessage.im
- Save changes and reinstall the app if prompted.
# In one terminal
crisp-uiThe bot will also attempt to auto-start crisp-ui on startup if it is not detected, but it is more reliable to start it manually.
cd integration
npm startYou should see:
[crisp-t-bot] Bot listening on port 3978
[crisp-t-bot] Teams webhook: http://localhost:3978/api/messages
[crisp-t-bot] Slack webhook: http://localhost:3978/slack/events
[crisp-t-bot] CRISP-T session ready (model: gpt-4.1)
During development you can use ngrok to create a public tunnel:
ngrok http 3978Copy the https:// forwarding URL and use it for both platforms:
- Teams: append
/api/messages→ paste as Azure Bot Messaging endpoint - Slack: append
/slack/events→ paste as Slack App Request URL
https://abc123.ngrok.io/api/messages # Teams
https://abc123.ngrok.io/slack/events # Slack
Commands work in Teams channels (via @-mention), Teams DMs, Slack channels (via @-mention), and Slack DMs.
| Command | Description |
|---|---|
@list or /list |
List available AI models |
@switch <model> or /switch <model> |
Switch to a different AI model |
@crisp <message> or /crisp <message> |
Send a message to the CRISP-T AI |
@clear or /clear |
Clear the current CRISP-T session |
@help or /help |
Show all available commands |
Note: In channels the bot must be @-mentioned. In DMs commands work without a mention prefix.
Teams:
@crisp-t-bot @list
Slack:
@crisp-t-bot /list
Response:
**Available models:**
1. gpt-4.1
2. gpt-5
3. claude-sonnet-4.5
_Current model: gpt-4.1_
@crisp-t-bot @switch claude-sonnet-4.5
Response:
Switched to model: **claude-sonnet-4.5**
@crisp-t-bot @crisp Import the CSV file from ./data using the "review" column and analyse topics
Response (streamed):
I'll import the CSV file and perform topic analysis...
[full CRISP-T response]
@crisp-t-bot @clear
Response:
Session cleared. A new session will be created automatically on your next `@crisp` command.
@crisp-t-bot @help
Response:
**CRISP-T Teams Bot — available commands:**
• `@list` or `/list` — List available AI models
• `@switch <model>` or `/switch <model>` — Switch to a different AI model
• `@crisp <message>` or `/crisp <message>` — Send a message to CRISP-T
• `@clear` or `/clear` — Clear the current CRISP-T session
• `@help` or `/help` — Show this help message
...
integration/
├── src/
│ └── index.ts # Main bot logic (Chat SDK + Express)
├── dist/ # Compiled JavaScript (auto-generated)
├── node_modules/ # npm dependencies (auto-generated)
├── package.json # npm project config
├── tsconfig.json # TypeScript config
└── .env.example # Environment variable documentation
| Function | Description |
|---|---|
isCrispUIRunning() |
Health-checks the crisp-ui server |
startCrispUI() |
Spawns crisp-ui as a background process |
ensureCrispUIRunning() |
Combines the two above; logs if it fails |
ensureSession() |
Creates a CRISP-T session if none exists |
destroySession() |
Destroys the active CRISP-T session |
listModels() |
Calls GET /api/models and formats the result |
switchModel(name) |
Destroys session and recreates with new model |
sendCrispMessage(msg) |
Sends a message and polls for the reply |
clearSession() |
Alias for destroySession() with a friendly message |
getHelpText(platform?) |
Returns formatted help (includes platform name if given) |
routeMessage(text, platform?) |
Top-level router; returns null for ignored messages |
main() |
Starts the Express server and initialises the session |
The bot exposes a /health endpoint:
curl http://localhost:3978/health{
"status": "ok",
"model": "gpt-4.1",
"sessionActive": true
}- Verify the Messaging endpoint in the Azure Bot Configuration is correct and publicly accessible.
- Check that
TEAMS_APP_IDandTEAMS_APP_PASSWORDare correct. - Inspect the bot's console output for errors.
- Verify the Request URL in the Slack App Event Subscriptions is correct and publicly accessible.
- Check that
SLACK_BOT_TOKENandSLACK_SIGNING_SECRETare correct. - Ensure the app is reinstalled in the workspace after any permission changes.
- Start
crisp-uimanually in a separate terminal:crisp-ui
- Verify
CRISP_UI_URLpoints to the correct host/port.
- Install the copilot extra:
pip install crisp-t[copilot]
- Run
@clearto reset the session and try again.
- Never commit your
.envfile. - Use short-lived client secrets and rotate them regularly.
- Restrict
TEAMS_APP_TENANT_IDto your organisation's tenant in production. - Store Slack tokens securely and rotate them if compromised.
- For production, use Redis (
@chat-adapter/state-redis) instead of in-memory state.