A smart Slack bot powered by LangGraph and local Qwen3-8B (with optional Gemini fallback) for agentic workflow orchestration.
| Feature | Command | Description |
|---|---|---|
| Summarize | /sab summarize or mention |
Summarizes recent messages using local LLM |
| Reminders | /sab -r "task" @30m |
Set timed reminders (persisted in SQLite) |
| Natural Language Reminders | /sab remind me to... |
dateparser handles "tomorrow at 3pm" |
| List Reminders | /sab reminders |
Show all pending reminders with IDs |
| Cancel Reminder | /sab reminder cancel <id> |
Cancel by job ID |
| GitHub Issue/PR Lookup | owner/repo#123 or paste URL |
Fetches issue/PR details |
| Latest Issues | /sab latest issues |
Newest open issues across all repos |
| Latest PRs | /sab latest prs |
Newest open PRs across all repos |
| Code Review | /sab codereview owner/repo#123 |
3-subagent review (Security + Performance + Best Practices) |
| PR Risk Score | (auto in code review) | 🔴 High / 🟡 Medium / 🟢 Low from Semgrep + LLM |
| Semgrep Security | (auto in code review) | Real static analysis grounding |
| Learning Paths | /sab learn <topic> |
3-agent research → structure → resources |
| Web Search | (auto in /learn) | Tavily API for real URLs |
| MCP Source Footer | (auto in review/learn) | Visible "via GitHub MCP" or fallback note |
| Slack mrkdwn Auto-fix | (auto) | Bold, links, and bare URLs converted to Slack format |
| Help | /sab or "what can you do" |
Static command list |
| System Diagnostics | /sab test |
Checks LLM provider + all 3 MCP sessions |
| Daily Digest | /sab digest subscribe |
Proactive daily GitHub issues/PRs post |
| Digest Demo | /sab digest demo |
Preview digest in ~2 minutes |
| Duplicate Check | /sab duplicate owner/repo "title" |
Find similar open issues via difflib |
| Release Notes | /sab release notes owner/repo |
Generate notes from merged PRs |
| Dual LLM | LLM_PROVIDER=local|gemini |
Local Qwen3 primary, Gemini cross-fallback |
| Typo Tolerance | "coderview", "review", "pr" | difflib fuzzy matching |
| Real-Time Search | /sab search <query> or @bot find discussions about X |
Cross-channel search via Slack RTS API |
Built with LangGraph StateGraph for deterministic, debuggable agentic workflows:
┌─────────────────────────────────────────────────────────────────────┐
│ Slack Workspace │
└────────────────────────────┬────────────────────────────────────────┘
│ Socket Mode (WebSocket)
▼
┌─────────────────────────────────────────────────────────────────────┐
│ main.py (Bolt App) │
│ ├── /sab command ──► cmd_sab() ──► handle_sab_command() │
│ ├── app_mention ──► on_mention() ──► handle_app_mention() │
│ └── message ──► on_message() ──► handle_message_event() │
│ │
│ [trigger_id dedup on /sab] [event_ts dedup on mention/message] │
│ [processing reaction decorator] [MCP init in background thread] │
└────────────────────────────┬────────────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────────────┐
│ graph/workflow.py (LangGraph StateGraph) │
│ ┌──────────┐ │
│ │ classify │ ◄── entry_point │
│ └────┬─────┘ │
│ │ 15 conditional routes │
│ ├──► reminder (parse → schedule / list / cancel) │
│ ├──► github (extract → fetch → response) │
│ ├──► context (summarize → response) │
│ ├──► learn (research → structure → resources → response) │
│ ├──► codereview (fetch → [security,performance,best] → merge) │
│ ├──► search (RTS via assistant.search.context) │
│ ├──► digest / duplicate / release_notes │
│ ├──► help / greeting / chat / test_llm │
└────────────────────────────┬────────────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────────────┐
│ services/ │
│ ├── llm_service.py ──► llama-server (Qwen3-8B, localhost:8080) │
│ ├── github_service.py ──► GitHub API (TTL cache, rate-limit track) │
│ ├── codereview_service.py ──► Semgrep + 3 LLM subagents │
│ ├── learn_service.py ──► Tavily search + GitHub repos + LLM │
│ ├── reminder_service.py ──► SQLite-backed APScheduler │
│ ├── slack_search_service.py ──► Slack RTS (assistant.search) │
│ └── mcp_client.py ──► GitHub/Fetch/Slack MCP servers │
└─────────────────────────────────────────────────────────────────────┘
GitHub lookups work for public repos without a token. Set GITHUB_TOKEN in .env for private repos and higher rate limits (5,000/hr vs 60/hr unauthenticated).
- LangGraph — StateGraph workflow orchestration with fan-out/fan-in
- Slack Bolt — Socket Mode event handling
- Local Qwen3-8B — LLM via llama-server (zero API cost, no data leaves machine)
- APScheduler — SQLite-persisted reminder scheduling
- GitHub API — Issue/PR lookup with TTL cache (works without token for public repos)
- MCP — Model Context Protocol for extensible tool access (GitHub, Fetch, custom Slack server)
- Semgrep — Real static analysis for security reviews (pinned ruleset, no network lookup)
- Tavily — Web search for verified learning resources
- dateparser — Natural language time parsing
- difflib — Typo-tolerant command matching
- Pydantic — Type-safe state models
Slack-Action-Bot/
├── main.py # Bolt app, MCP init, dedup guards (trigger_id + event_ts)
├── config.py # Env vars (tokens, endpoints)
├── graph/
│ ├── state.py # BotState TypedDict, ReminderData
│ ├── nodes.py # 30+ node functions
│ └── workflow.py # StateGraph build, routing logic
├── handlers/
│ ├── commands.py # /sab slash command handler
│ ├── events.py # app_mention + message handlers
│ └── shared.py # is_real_message, fetch_*, build_initial_state
├── services/
│ ├── llm_service.py # Local LLM calls, PERSONA, summarize
│ ├── github_service.py # GitHub API, TTL cache, rate-limit tracking
│ ├── codereview_service.py # 3-subagent review, Semgrep, risk score
│ ├── learn_service.py # 3-agent learning path, Tavily search
│ ├── reminder_service.py # SQLite-backed APScheduler
│ ├── mcp_client.py # MCP AsyncExitStack, background loop, _evict_session()
│ ├── mcp_slack_server.py # Custom Slack MCP server (stdio)
│ ├── slack_summarize_service.py # MCP-first channel summary
│ ├── slack_search_service.py # Real-time search via assistant.search.context
│ └── slack_features.py # Processing reaction decorator
├── reminders.db # SQLite persistent reminders
├── test_all.py # 168 unit tests
├── test_e2e.py # 57 end-to-end tests
└── pyproject.toml # Dependencies (uv-managed)
-
Start llama-server with Qwen3-8B:
cd ~/llama.cpp ./build/bin/llama-server \ -m <path-to>/Qwen3-8B-Q4_K_M.gguf \ -ngl 999 \ -c 16384 \ --parallel 4 \ --host 0.0.0.0 \ --port 8080
-
Copy
.env.exampleto.envand fill in:SLACK_BOT_TOKEN=xoxb-... SLACK_APP_TOKEN=xapp-... SLACK_SIGNING_SECRET=... GITHUB_TOKEN=ghp-... # optional for public repos LLAMA_BASE_URL=http://localhost:8080 LLAMA_PARALLEL=4 LLM_PROVIDER=local LLM_FALLBACK_ENABLED=true GOOGLE_API_KEY=... # optional, Gemini fallback when local fails GEMINI_MODEL=gemini-2.0-flash TAVILY_API_KEY=tvly-... # optional, for /learn web search -
Install dependencies:
uv sync uv sync --group optional # installs semgrep for code review static analysis -
Enable Real-Time Search (optional):
- Go to https://api.slack.com/apps → your app → App Home → enable Assistant
- Add Bot Token Scopes:
search:read.public,search:read.files,search:read.users - Reinstall app to workspace
-
Run the bot:
uv run main.py
| Command | Description |
|---|---|
/sab |
Show help / command list |
/sab summarize |
Summarize channel or thread messages |
/sab -r "task" @30m |
Set a reminder in 30 minutes |
/sab remind me to... |
Natural language reminder |
/sab reminders |
List pending reminders |
/sab reminder cancel <id> |
Cancel a reminder |
/sab latest issues |
Newest open issues across all repos |
/sab latest prs |
Newest open PRs across all repos |
/sab codereview owner/repo#123 |
3-perspective code review with risk score |
/sab learn <topic> |
Structured learning path |
/sab digest subscribe |
Daily GitHub digest at 9am UTC |
/sab digest demo |
Preview digest in ~2 minutes |
/sab duplicate owner/repo "title" |
Find similar open issues |
/sab release notes owner/repo |
Generate release notes from merged PRs |
/sab test |
Diagnostics: LLM provider + MCP health check |
/sab search <query> |
Real-time cross-channel search (needs search:read scopes) |
@bot find discussions about X |
Same, via @mention (action_token required) |
owner/repo#123 |
Auto-fetch issue/PR details |
| Paste GitHub URL | Auto-fetch issue/PR details |