How to turn messy #product-support Slack messages into auditable tasks
We’ve been experimenting with AI workflows (like most of the dev world lately — and of course, using Scalekit for the auth layer. Full disclosure: I work for Scalekit. Our offering is always free for devs tinkering with stuff).
For our first one, we tried automating Slack workflows with LangGraph and Scalekit. Here’s what we built 👇
🎫 Auto-create GitHub issues or Zendesk tickets directly from Slack messages
🔐 Simplify OAuth, token management, and API calls using Scalekit
🔁 Use LangGraph to design modular, observable workflows
The idea
Slack is great for fast communication, but terrible as a system of record. Important messages about bugs or support requests get buried almost instantly.
So we built an agent that:
- Watches specific Slack channels
- Classifies each message (bug, support, ignore)
- Creates a GitHub issue or Zendesk ticket based on that classification
- Posts a confirmation reply in Slack
Why LangGraph + Scalekit
Scalekit takes care of all the auth plumbing, so no need to manually store Slack or GitHub tokens, refresh them, or juggle SDKs. You just call execute_tool with the right parameters, and Scalekit securely handles the rest.
LangGraph gives you a clean, node-based workflow where each step is independent and observable. Instead of a big procedural script, you have a graph that shows exactly how data moves, which is perfect when you want to debug or extend it later.
How it works
Here’s the basic flow:
# triage.py
from routing import classify_route
from actions import create_github_issue, post_slack_confirmation, handle_zendesk_ticket
def triage_message(slack_user, channel, ts, text):
route = classify_route(text)
if route == "github":
issue = create_github_issue(slack_user, channel, ts, text)
post_slack_confirmation(slack_user, channel, ts, f"Created GitHub issue → {issue['url']}")
elif route == "zendesk":
handle_zendesk_ticket(slack_user, channel, ts)
else:
# ignored message
pass
Each message gets classified, turned into a structured task, and acknowledged back in Slack — no human in the loop.
Moving to LangGraph
Once we had the script working, we turned it into a LangGraph workflow:
from langgraph import StateGraph
graph = (
StateGraph()
.add("parse", parse_node)
.add("classify", classify_node)
.add("execute", execute_node)
.add("confirm", confirm_node)
.edge("parse", "classify")
.edge("classify", "execute")
.edge("execute", "confirm")
.entry("parse")
)
Each node handles one job, and you can easily replace or expand them later, like plugging in an LLM classifier, adding retries, or branching into multiple integrations.
Why is this useful?
- Keeps your Slack channels clean and actionable
- Saves hours of manual triage work
- Makes tasks traceable and auditable
- Easy to extend to Notion, Jira, or any API Scalekit supports
Try it yourself
- Connect Slack + GitHub via Scalekit
- Drop in the triage script
- Run your loop or use webhooks for real-time updates
- Watch your Slack messages turn into issues and tickets automatically
If you'd like a more comprehensive tutorial, head to this blog (It has working code, screenshots, and links to Git repos).
Top comments (0)