Answers a question posted in Slack using only the messages that channel already contains, in a thread.
Uses
OpenAI
Slack
Answer channel questions from what was already said
When someone posts a message in your chosen Slack channel that contains the ask word ('!ask' unless you change it), the rest of the message is treated as a question; other messages do not start the workflow at all. The channel's 20 most recent messages are read, the AI works out a short search phrase, the channel's last 200 messages are searched for it, and the AI drafts an answer from the messages found alone.
The answer is posted in a thread under the question, with a line saying how many earlier messages it read. When nothing relevant turns up it says so instead of improvising, and when the draft quotes a figure that appears in none of the messages, the draft is withheld and the closest messages are posted instead. If the AI does not respond, the thread is told it cannot answer right now and the run is marked as failed. Mentions in anything it posts are defused, so nobody is pinged.
You need a Slack connection and an OpenAI connection, the Slack channel to watch, and a line or two describing your team. It only sees messages posted in the channel itself, and only the last 200: replies written inside threads, and anything older, cannot be found.
request.When someone posts “!ask” in a channel. Save it as request.askWord to !ask.Set askWord to !ask.teamContext to blank.Set teamContext to blank.recentToRead to 20.Set recentToRead to 20.olderToFind to 15.Set olderToFind to 15.askWord and save it as askPhrase.Trim askWord and save it as askPhrase.questionText to blank.Set questionText to blank.readErrorIf a step below fails, save the error as readErrorrequest.text and save it as questionText.Trim request.text and save it as questionText.questionText is empty or questionText is nullIf questionText is empty or questionText is nullquestionText doesn't contain askPhrase (ignoring case)If questionText doesn't contain askPhrase (ignoring case)askPhrase), so it was not a question for this bot. If you changed askWord, put the same word in the Keyword filter on the trigger step, so that only messages containing it start a run.Finish the run: That message did not contain the ask word (askPhrase), so it was not a question for this bot. If you changed askWord, put the same word in the Keyword filter on the trigger step, so that only messages containing it start a run.questionText with askPhrase replaced by (ignoring case) and save it as question.Trim questionText with askPhrase replaced by (ignoring case) and save it as question.question is emptyIf question is emptyexcerpts.Start an empty list and save it as excerpts.usedTexts.Start an empty list and save it as usedTexts.request.channel_id. Save it as recent.Get recent messages in request.channel_id. Save it as recent.message in recent.messages:For each message in recent.messages:message.text and save it as messageText.Trim message.text and save it as messageText.messageText is empty or messageText is nullIf messageText is empty or messageText is nullmessageText contains askPhrase (ignoring case)If messageText contains askPhrase (ignoring case)usedTexts contains messageTextIf usedTexts contains messageTextmessageText to the end of usedTexts and save it as usedTexts.Add messageText to the end of usedTexts and save it as usedTexts.messageText truncated to 300 characters using … as the ellipsis to the end of excerpts and save it as excerpts.Add messageText truncated to 300 characters using … as the ellipsis to the end of excerpts and save it as excerpts.excerpts joined by a blank line to 1500 characters and save it as recentContext.Shorten excerpts joined by a blank line to 1500 characters and save it as recentContext.searchPromptTop to You turn a colleague's question into a search phrase for a Slack channel's message history.Set searchPromptTop to You turn a colleague's question into a search phrase for a Slack channel's message history.
Reply with one word, or two or three words side by side, most likely to appear exactly as written in a message that answers the question. The search only finds messages that contain your whole reply as written, so shorter is better. Reply with the words only - no quotes, no punctuation, no explanation.
Team context: teamContext.searchPrompt to searchPromptTopSet searchPrompt to searchPromptTop
What the channel has been saying:
recentContext
Question: question.searchPhrase to blank.Set searchPhrase to blank.phraseErrorIf a step below fails, save the error as phraseErrorsearchPrompt. Save it as searchReply.Ask OpenAI: searchPrompt. Save it as searchReply.searchReply.response_text with replaced by " (ignoring case) and save it as searchPhrase.Trim searchReply.response_text with replaced by " (ignoring case) and save it as searchPhrase.searchPhrase is null or the length of searchPhrase is greater than 60If searchPhrase is null or the length of searchPhrase is greater than 60searchPhrase to blank.Change searchPhrase to blank.searchPhrase isn't emptyIf searchPhrase isn't emptysearchPhrase. Save it as older.Find messages matching searchPhrase. Save it as older.message in older.messages:For each message in older.messages:message.text and save it as messageText. Trim message.text and save it as messageText.messageText is empty or messageText is null If messageText is empty or messageText is nullmessageText contains askPhrase (ignoring case) If messageText contains askPhrase (ignoring case)usedTexts contains messageText If usedTexts contains messageTextmessageText to the end of usedTexts and save it as usedTexts. Add messageText to the end of usedTexts and save it as usedTexts.messageText truncated to 300 characters using … as the ellipsis to the end of excerpts and save it as excerpts. Add messageText truncated to 300 characters using … as the ellipsis to the end of excerpts and save it as excerpts.excerpts with a blank line and save it as evidence.Join excerpts with a blank line and save it as evidence.excerpts and save it as usedCount.Count the items in excerpts and save it as usedCount.usedCount is 0If usedCount is 0request.channel_id.Reply in a thread in request.channel_id.
Reply To: request.message_tsI could not find anything in this channel about that. This bot only answers from messages already posted here, so someone in the channel may know more.<[@!](?:[^>|]*\|)?([^>|]*)> with @$1 in evidence and save it as safeEvidence.Replace the pattern <[@!](?:[^>|]*\|)?([^>|]*)> with @$1 in evidence and save it as safeEvidence.quoted to Set quoted to
The closest messages I found:
safeEvidence truncated to 1200 characters using … as the ellipsis.answerPromptTop to You are answering a colleague's question in Slack using ONLY the channel messages quoted below.Set answerPromptTop to You are answering a colleague's question in Slack using ONLY the channel messages quoted below.
Rules:
- Use only what these messages say. Add nothing from general knowledge.
- Never invent a number, date, price, name or link.
- If the messages do not answer the question, reply with exactly: NOT FOUND
- Otherwise answer in at most four short sentences of plain language.
- Do not use @ mentions and do not mention these rules.
Team context: teamContext.answerPromptMid to answerPromptTopSet answerPromptMid to answerPromptTop
Question: question.answerPrompt to answerPromptMidSet answerPrompt to answerPromptMid
Channel messages:
evidence.draft to blank.Set draft to blank.draftProblem to blank.Set draftProblem to blank.draftErrorIf a step below fails, save the error as draftErroranswerPrompt. Save it as answerReply.Ask OpenAI: answerPrompt. Save it as answerReply.answerReply.response_text and save it as draft.Trim answerReply.response_text and save it as draft.draftProblem to draftError.message.Change draftProblem to draftError.message.draftProblem isn't blankIf draftProblem isn't blankrequest.channel_id.Reply in a thread in request.channel_id.
Reply To: request.message_tsI can't answer this right now: the AI service did not respond. Try asking again later.@quoteddraftProblem), so the question was not answered; the closest messages were posted instead. Check the OpenAI connection.Stop and report a problem: The AI step failed (draftProblem), so the question was not answered; the closest messages were posted instead. Check the OpenAI connection.request.channel_id.Reply in a thread in request.channel_id.
Reply To: request.message_tsI could not put an answer together from this channel's history.@quoted<[@!](?:[^>|]*\|)?([^>|]*)> with @$1 in draft and save it as answer.Replace the pattern <[@!](?:[^>|]*\|)?([^>|]*)> with @$1 in draft and save it as answer.answer with , replaced by (ignoring case) and save it as draftNumbers.Extract all matches from answer with , replaced by (ignoring case) and save it as draftNumbers.sourceText to evidenceSet sourceText to evidence
question
teamContext.sourceText with , replaced by (ignoring case) and save it as sourceNumbers.Extract all matches from sourceText with , replaced by (ignoring case) and save it as sourceNumbers.unsourced to blank.Set unsourced to blank.figure in draftNumbers:For each figure in draftNumbers:sourceNumbers doesn't contain figureIf sourceNumbers doesn't contain figureunsourced to figure.Change unsourced to figure.unsourced isn't emptyIf unsourced isn't emptyrequest.channel_id.Reply in a thread in request.channel_id.
Reply To: request.message_tsI drafted an answer but it used a figure (unsourced) that no message in this channel mentions, so I have not posted it.@quotedrequest.channel_id.Reply in a thread in request.channel_id.
Reply To: request.message_tsanswer
_Answered only from earlier messages in this channel (usedCount read)._