Turn Grain meeting action items into owned Asana tasks
As soon as a Grain recording finalizes, an agent extracts every action item, files it as an assigned Asana task, and DMs you the list in Slack.
Build me an agent that triggers on a Grain webhook when a recording finalizes (recording_ready / recording.added) and turns every action item from the call into an owned Asana task, then DMs me a recap in Slack.
Trigger: Grain webhook for recording_ready. The payload includes the recording id.
Step 1, gather the source material from Grain. Use Get Recording on the recording id and request the workspace API enrichments: intelligence_notes, ai_summary, participants, highlights, and the recording's deep-link URL. Then call Get Transcript on the same recording id to get the full speaker-stamped transcript with timestamps. Prefer the structured 'Action items' section inside intelligence_notes when it is present (Business/Enterprise plans); fall back to extracting action items from the transcript and AI summary when it is not.
Step 2, decide whether to skip this meeting. If the participants list contains only people whose emails match our own workspace domains (no external participants), stop and do nothing. This rule should be configurable so the user can flip it off or change the 'internal' definition.
Step 3, extract action items. For each candidate, capture: the action text (rewritten as a short imperative task title), the owner mentioned in the call (name or email if spoken), any natural-language due date phrase from the conversation ('by Friday', 'next week', 'EOM', 'end of quarter'), and the verbatim transcript snippet (with its timestamp) that produced the item. Drop vague items with no clear owner and no concrete verb (e.g. 'follow up later').
Step 4, resolve owners against Asana. Call Get Users in a Workspace once to fetch the workspace roster, then match each spoken name/email against that list to get an Asana user GID. If no confident match exists, leave the task unassigned and surface the unresolved name in the Slack recap.
Step 5, pick the destination project. Call Get Multiple Projects in the workspace and apply simple keyword matching from the meeting title against project names (e.g. 'Acme' in the title → 'Acme Onboarding' project). If no project matches, use the user-configured default project. Both the default and the keyword map should be configurable.
Step 6, parse each due-date phrase relative to the meeting's start time and create the Asana task. For each action item, call Create a Task in the chosen project with: name = short imperative title, assignee = resolved Asana user (or unassigned), due_on = parsed date (omit if none), and notes containing (a) the verbatim transcript snippet that produced the item, (b) the speaker, (c) a deep link to that exact timestamp in the Grain recording, and (d) the recording URL itself. Use the recording's permalink format with the timestamp suffix that Grain supports.
Step 7, DM the meeting host in Slack. Look the host up by email with Look Up User by Email, Open a Conversation with that user to get the DM channel id, then Send a Message as the bot with a tidy bullet list: one line per created task showing the task title, the assignee (or 'unassigned' if not resolved), the due date (or 'no due date'), and a clickable link to the Asana task URL. Include a one-line header noting the meeting title and a link back to the Grain recording. If any owners could not be resolved, call those out explicitly at the bottom of the message so the host can fix them in seconds.
Failure handling: if Grain returns 404 for the recording (still processing), wait briefly and retry once. Never create duplicate tasks for the same recording id on retries; treat the recording id as the idempotency key.
Additional information
What does this prompt do?
- Triggers the moment a Grain call wraps and the recording is ready, so follow-ups land in Asana before the next meeting starts.
- Pulls every action item out of the call, figures out who owns it, parses phrases like 'by Friday' into real due dates, and routes the task to the right Asana project.
- Files each action item as a real Asana task with the verbatim quote that produced it and a deep link back to the exact moment in the Grain recording.
- DMs you in Slack with a tidy bullet list of every task it just created, with one-click links into Asana so you can fix anything misassigned in seconds.
- Quietly skips internal-only calls and vague items with no owner so your Asana stays clean.
What do I need to use this?
- A Grain account on a plan that includes the meeting intelligence features (Business or Enterprise) so the agent can read AI notes, highlights, and the transcript.
- An Asana login with permission to create tasks in the projects you want follow-ups to land in.
- A Slack workspace where you can install the Geni bot so it can DM you the summary.
How can I customize it?
- Set a default Asana project for action items, plus simple keyword rules that route specific projects based on the meeting title (for example, 'Acme' calls go to the Acme Onboarding project).
- Decide which Slack channel or person should get the recap. The default is a DM to the meeting host.
- Tune the skip rules. The default skips internal-only meetings and vague action items, but you can change what counts as internal or what gets dropped.
Frequently asked questions
Does this work on the free Grain plan?
What happens if the action item names someone who is not in our Asana?
How does it figure out the due date?
Will it spam Asana for short internal standups?
Can I send the recap to a channel instead of a DM?
Related templates
Stop chasing action items after every call.
Connect Grain, Asana, and Slack once, and Geni files owned follow-ups the moment your meeting ends.