Inspiration
Volunteer and nonprofit teams don't get the luxury of a daily standup meeting. Everyone's checking in around day jobs, at different hours, with wildly irregular engagement. Existing standup bots (Geekbot, Standuply) are just forms — they collect whatever people type and post it, with no idea whether a reported blocker is still actually blocking or has already been resolved somewhere else in the workspace. We wanted something that behaves like a teammate checking in, not a survey.
What it does
- Collects async standups via DM —
/standup-requestDMs every member of a channel with a freeform prompt (Yesterday / Today / Blockers). No rigid format — reply however you want, and the agent parses it into structured fields. - Pulls live task context via the Slack MCP Server — the agent can search messages, read channel/thread history, and reason over real workspace context, not just what's logged in standup replies.
- Answers "what's blocked?" using the Real-Time Search API — cross-checks reported blockers against live, in-workspace conversation to see if something is still actually stuck or has since been resolved elsewhere.
- Responds with Block Kit — every digest and blocker report renders as a structured, scannable card, never a wall of text.
How we built it
StandupPilot is built on Slack Bolt for JavaScript with Socket Mode, scaffolded via the Slack CLI (slack create agent). The conversational layer uses the OpenAI Agents SDK, with Groq wired in through its OpenAI-compatible endpoint for both standup parsing and conversational reasoning. Two Slack capabilities are load-bearing, not decorative: the Slack MCP Server (MCPServerStreamableHttp) gives the agent broader read access to workspace context, and the Real-Time Search API (assistant.search.context) lets it verify whether a reported blocker is still actually open before answering. All structured output — digests, blocker reports — renders as Block Kit.
Challenges we ran into
- Provider migration friction: we originally built against Gemini's OpenAI-compatible endpoint, then moved to Groq for better throughput. The two providers' JSON Schema validation isn't identical — Groq rejected a zero-argument tool schema that Gemini accepted without complaint, which taught us to keep tool parameter schemas explicit rather than relying on provider leniency.
- In-memory state: standup data resets on restart. Fine for demo scope, but it's the first thing we'd swap for a real datastore in production.
- RTS API is beta: response shape isn't fully stable yet, so we built defensively around it.
What's next
- Move standup storage to a real datastore (Postgres/Redis) so state survives restarts.
- Schedule
/standup-requestautomatically instead of requiring manual triggering. - Expand blocker cross-checking to also search linked tools (e.g. GitHub issues, Asana) via additional MCP servers.
Built With
- block-kit
- groq
- javascript
- llama-3.3
- model-context-protocol
- node.js
- openai-agents-sdk
- slack
- slack-bolt
- slack-cli
- slack-mcp-server
- slack-real-time-search-api
- socket-mode
- zod


Log in or sign up for Devpost to join the conversation.