Get icon
Script icon
ChatCompletion icon
Set icon
Request icon
Webhook icon

AI Slack Chatbot with Per-User Conversation Memory Using OpenAI and KV Store

Build a stateful Slack AI chatbot with Kestra and OpenAI. Loads per-user conversation history from the KV store and keeps context across messages.

Categories
AIBusiness

Build a Slack AI chatbot that holds a real conversation instead of forgetting every message. This blueprint orchestrates an OpenAI GPT-4o-mini chat assistant with persistent per-user memory backed by the Kestra KV store, so each Slack user keeps their own context across turns. Every inbound Slack message triggers a Kestra execution that loads prior history, builds the full message context, calls OpenAI, posts the reply back to Slack, and saves the updated history for the next turn. It solves the core problem of stateless LLM calls: without external memory, every chatbot request starts from scratch and loses the thread of the conversation.

How it works

  1. The slack_message_webhook trigger (io.kestra.plugin.core.trigger.Webhook) receives a POST from the Slack Events API and passes the user_message, user_id, and channel_id as flow inputs.
  2. load_conversation_history (io.kestra.plugin.core.kv.Get) reads the user-scoped key chat_history_{{ inputs.user_id }} with errorOnMissing: false, so first-time users start cleanly.
  3. build_and_respond (io.kestra.plugin.scripts.python.Script) assembles the OpenAI messages array: the system_prompt, the trimmed history (sliding window of max_history_turns pairs), and the new user message.
  4. generate_response (io.kestra.plugin.openai.ChatCompletion) calls gpt-4o-mini with maxTokens: 800 to produce the reply.
  5. update_conversation_history appends the new user and assistant turns and re-trims the window, then save_conversation_history (io.kestra.plugin.core.kv.Set) writes it back to the KV store.
  6. post_reply_to_slack (io.kestra.plugin.core.http.Request) calls chat.postMessage with mrkdwn: true to deliver the answer.

What you get

  • Per-user conversation memory isolated by Slack user_id
  • Cost-efficient responses from GPT-4o-mini with bounded token growth
  • Automatic sliding-window history trimming via max_history_turns
  • A configurable bot persona through the system_prompt input
  • Markdown-rendered replies posted straight into the right channel or DM

Who it's for

  • Engineering and operations teams running an internal Slack assistant across multi-turn troubleshooting
  • Customer support teams building a first-line AI triage bot that holds context
  • Product and documentation teams shipping a knowledge assistant with a custom persona
  • Developers learning stateful AI conversations without a dedicated chat-memory service

Why orchestrate this with Kestra

OpenAI's API is stateless and has no scheduler, no durable memory, and no retry semantics of its own. Kestra fills that gap: the event-driven Webhook trigger fires the flow on every Slack message, the KV store persists per-user history between executions, declarative YAML keeps each step auditable, and built-in retries plus full execution lineage make every reply traceable and replayable. You get production reliability around the model call instead of a fragile script.

Prerequisites

  • A Kestra instance with the OpenAI plugin available
  • A Slack app with Event Subscriptions and a bot token with chat:write
  • An OpenAI account with API access to gpt-4o-mini

Secrets

  • OPENAI_API_KEY: authenticates the ChatCompletion call
  • SLACK_BOT_TOKEN: bearer token for posting via chat.postMessage
  • SLACK_WEBHOOK_KEY: secures the inbound Webhook trigger URL

Quick start

  1. Add the OPENAI_API_KEY, SLACK_BOT_TOKEN, and SLACK_WEBHOOK_KEY secrets to your Kestra instance.
  2. Create the flow and point your Slack app's Event Subscriptions URL at the Webhook endpoint shown in the trigger description.
  3. Map the Slack event payload to the user_message, user_id, and channel_id inputs.
  4. Message the bot in Slack and confirm the reply, then send a follow-up to see memory in action.

How to extend

  • Add a /reset command that clears the KV store history for a user.
  • Ground responses in your own data with RAG (io.kestra.plugin.ai.rag.IngestDocument).
  • Log every exchange to Postgres for analytics and audit.
  • Reply in threads to keep each conversation in its own Slack thread.
  • Escalate to a human when the model flags low confidence.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.