Meeting to Action — Devpost Submission

Tagline (one-liner)

Meeting talk becomes tracked work — a Slack agent that turns your notes into approved, tracked action items.


Inspiration

Every team we've worked on has the same quiet tax: a meeting ends, someone says "I'll write up the notes," and the action items evaporate into a wall of text nobody rereads. Decisions get made out loud, but they never make it into a task, an owner, or a deadline — so they get made again two weeks later.

We wanted to test a simple idea: what if the follow-up wrote itself? Not another notes-taking app competing for a tab in your browser, but something that lives exactly where the meeting notes already land — Slack — and turns raw text into tracked, owned, nudge-able work.

What it does

Meeting to Action watches for meeting notes pasted into a Slack channel and:

  1. Extracts action items, owners, and due dates using Gemini — including resolving loose relative dates like "Thursday" or "next sprint" into real calendar dates.
  2. Checks Slack's Real-Time Search (RTS) API for related past discussions before surfacing each item, so nothing gets proposed in a vacuum — if the topic came up before, the card shows how many related mentions exist.
  3. Proposes, doesn't decide. Every extracted item appears as an interactive Block Kit card with Approve and Discard buttons. Nothing gets tracked without a human confirming it.
  4. Persists approved items to a Google Sheet — task, owner, resolved due date, status, who approved it, and a link straight back to the original Slack message.
  5. Skips duplicates automatically, so re-mentioning the same task later doesn't create a second row.
  6. Flags overdue items by highlighting rows once their resolved due date passes.

How we built it

  • Slack Bolt SDK (Node.js) running in Socket Mode — no public URL or inbound webhook needed, which made local iteration fast.
  • Slack Block Kit for the interactive approval card (Approve/Discard buttons, owner/due display, related-mentions note).
  • Slack Real-Time Search API (assistant.search.context) — queried with a user token (search:read.public scope) to pull related past messages before an item is surfaced.
  • Gemini API for extraction — a single structured prompt returns task, owner, raw due date, and a resolved ISO date, given today's date as context.
  • Google Sheets API — approved items are appended as rows, with duplicate-checking against existing tasks and conditional background-highlighting for overdue items, all done via batchUpdate calls.
  • Google Cloud service account for Sheets auth, supporting both local file-based credentials and an environment-variable-based credential for hosted deployment (Render background worker).

Challenges we ran into

  • RTS token requirements. The RTS endpoint (assistant.search.context) requires an action_token when called with a bot token — tied to Slack's Assistant framework. We found that calling it with a user token instead avoids this requirement, which was the key unlock for getting it working without building the full Assistant integration.
  • A silent bug in our own related-mentions counter. assistant.search.context returns results as an object ({ messages: [...] }), not an array — so our first version's res.results.length was always undefined. The API was working the whole time; our display logic wasn't reading the response shape correctly. Caught this by adding temporary debug logging to see the raw response before concluding anything was broken.
  • Model deprecation mid-build. Our original extraction model was removed from availability for new API accounts partway through building, which meant swapping to a current model and re-verifying prompt behavior.
  • Sheets permission errors. Service account credentials alone aren't enough — the target Sheet has to be explicitly shared with the service account's email as an Editor. A 403 PERMISSION_DENIED pointed us to this directly.

Accomplishments we're proud of

  • A full working pipeline from a single Slack message to a persisted, deduplicated, context-checked row in Google Sheets — with a human approval step in between at every point.
  • Genuine RTS API integration that surfaces real related messages from workspace history, not a canned demo.
  • Deployable outside a single dev machine — the same codebase runs locally against a file-based service account key, or on a hosted background worker using an environment-variable-based credential.

What we learned

  • Meeting text is messier than it looks — commitments are often implicit, and good extraction needs conversational cues, not just keyword matching.
  • RTS is most valuable as a precision tool, not a blanket search — querying only when a real decision-like item is extracted kept it fast and useful rather than noisy.
  • A human-approval step doesn't slow an agent down as much as expected — it made the tool more trustworthy to actually rely on.

What's next

  • A "mark as done" button that updates the existing Sheet row instead of appending a new one.
  • Multi-language meeting support.
  • Per-channel or per-week Sheet tabs for teams running multiple concurrent projects.

Built With

slack, slack-api, slack-bolt, slack-block-kit, real-time-search, model-context-protocol, mcp, gemini, google-sheets-api, google-cloud, node.js, javascript, oauth, rest-api, json, socket-mode, render


Track

Best New Slack Agent

Built With

Share this project:

Updates