New to Kestra?
Use blueprints to kickstart your first workflows.
Build a stateful Slack AI chatbot with Kestra and OpenAI. Loads per-user conversation history from the KV store and keeps context across messages.
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.
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.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.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.generate_response (io.kestra.plugin.openai.ChatCompletion) calls gpt-4o-mini with maxTokens: 800 to produce the reply.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.post_reply_to_slack (io.kestra.plugin.core.http.Request) calls chat.postMessage with mrkdwn: true to deliver the answer.user_idmax_history_turnssystem_prompt inputOpenAI'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.
chat:writegpt-4o-miniOPENAI_API_KEY: authenticates the ChatCompletion callSLACK_BOT_TOKEN: bearer token for posting via chat.postMessageSLACK_WEBHOOK_KEY: secures the inbound Webhook trigger URLOPENAI_API_KEY, SLACK_BOT_TOKEN, and SLACK_WEBHOOK_KEY secrets to your Kestra instance.user_message, user_id, and channel_id inputs./reset command that clears the KV store history for a user.io.kestra.plugin.ai.rag.IngestDocument).