$npx -y skills add mgonto/executive-assistant-skills --skill action-items-todoistExtract action items from today's Granola/Grain meetings, create Todoist tasks, complete fulfilled tasks, and draft meeting-triggered follow-up emails. Use when running the daily action items cron, post-meeting cron, or when user asks to process meeting action items. NOT for gene
| 1 | # Action Items → Todoist + Email Drafts |
| 2 | |
| 3 | ## Config — read before starting |
| 4 | Read `../config/user.json` (resolves to `~/executive-assistant-skills/config/user.json`). |
| 5 | Extract and use throughout: |
| 6 | - `name`, `full_name` — to identify your action items in meeting notes (e.g. "Gonto (Martin)") |
| 7 | - `whatsapp` — for result delivery |
| 8 | - `workspace` — absolute path to OpenClaw workspace |
| 9 | |
| 10 | Do not proceed until you have these values. |
| 11 | |
| 12 | ## Debug Logging (MANDATORY) |
| 13 | Read `../config/DEBUG_LOGGING.md` for the full convention. Use `python3 {user.workspace}/scripts/skill_log.py action-items <level> "<message>" ['<details>']` at every key step. Log BEFORE and AFTER every external call (gog, mcporter, todoist-cli). On any error, log the full command and stderr before continuing. |
| 14 | |
| 15 | ## Steps |
| 16 | |
| 17 | ### 0. Check today's calendar for meetings (BOTH accounts) |
| 18 | Before querying Granola, get today's actual meetings from BOTH calendars to know what to expect: |
| 19 | ```bash |
| 20 | python3 {user.workspace}/scripts/skill_log.py action-items INFO "Starting action-items run" |
| 21 | |
| 22 | # Get today's date in YYYY-MM-DD and tomorrow's |
| 23 | TODAY=$(date -u -d "$(TZ=America/Argentina/Buenos_Aires date +%Y-%m-%d)" +%Y-%m-%d) |
| 24 | TOMORROW=$(date -u -d "$(TZ=America/Argentina/Buenos_Aires date -d '+1 day' +%Y-%m-%d)" +%Y-%m-%d) |
| 25 | |
| 26 | # Check BOTH calendars |
| 27 | gog --account {user.primary_email} --no-input calendar list primary --from "${TODAY}T00:00:00-03:00" --to "${TOMORROW}T00:00:00-03:00" --json 2>&1 |
| 28 | gog --account {user.work_email} --no-input calendar list primary --from "${TODAY}T00:00:00-03:00" --to "${TOMORROW}T00:00:00-03:00" --json 2>&1 |
| 29 | ``` |
| 30 | Log the results: `python3 {user.workspace}/scripts/skill_log.py action-items DEBUG "Calendar events found" '{"primary": N, "work": M, "total": N+M}'` |
| 31 | |
| 32 | Merge events from both calendars. Filter for meetings with attendees (skip solo/personal events). This gives you the ground truth of what meetings happened today — use it to cross-check Granola results and catch any meetings Granola missed. |
| 33 | |
| 34 | **CRITICAL date syntax:** Use explicit ISO8601 dates with `-03:00` offset. Do NOT use relative expressions like `+1 day`, `today`, or `tomorrow` in gog flags — they may not be supported. Always compute the actual date strings. |
| 35 | |
| 36 | ### 1. Get today's meetings from Granola |
| 37 | |
| 38 | **Timezone note:** Granola stores meeting times in UTC. For ART (UTC-3), querying "today" means using today's date AND tomorrow's date in UTC. E.g., for March 3 ART, query `custom_start: "2026-03-03"` and `custom_end: "2026-03-04"` to capture all ART-day meetings. |
| 39 | |
| 40 | ```bash |
| 41 | mcporter call granola list_meetings --args '{"time_range": "custom", "custom_start": "<today YYYY-MM-DD>", "custom_end": "<tomorrow YYYY-MM-DD>"}' |
| 42 | ``` |
| 43 | Collect meeting IDs and titles. Log: `python3 {user.workspace}/scripts/skill_log.py action-items INFO "Granola meetings found" '{"count": N, "titles": [...]}'` |
| 44 | |
| 45 | **Cross-check with calendar:** Compare Granola meetings against the calendar events from Step 0. If a calendar meeting with attendees has no Granola match (by time overlap within 15 min), log a warning — it may not have been recorded. Proceed with what Granola has, but note unmatched meetings in the output. |
| 46 | |
| 47 | Skip if no meetings (from either Granola or calendar). |
| 48 | |
| 49 | ### 2. Query Granola for MY action items + email triggers |
| 50 | ```bash |
| 51 | mcporter call granola query_granola_meetings --args '{"query": "What are all of {user.name} ({user.full_name}) personal action items, follow-ups, and commitments from these meetings? Only things HE needs to do, not what others committed to. For each item, include the specific person, company, project, or candidate name involved — never use generic references. Also identify: any promises made to do ANYTHING via email (intros, follow-ups, sending docs, sharing info, connecting people, etc.), and whether each meeting was a FIRST meeting with that person/company or a follow-up.", "document_ids": ["<id1>", "<id2>", ...]}' |
| 52 | ``` |
| 53 | Pass ALL meeting IDs. Preserve citation links. |
| 54 | |
| 55 | ### 3. Create Todoist tasks |
| 56 | |
| 57 | > **Note:** Load env in the same command — each shell call is a fresh session. |
| 58 | |
| 59 | Read `{user.workspace}/skills/todoist-api/SKILL.md` for CLI usage. For each action item: |
| 60 | ```bash |
| 61 | source {user.workspace}/.env && todoist-cli add "<actionable title>" --description "<context: meeting name, meeting date/time, who requested, Granola link>" --priority <1-4> --labels "<relevant>" |
| 62 | ``` |
| 63 | |
| 64 | **Task description MUST include:** |
| 65 | - Meeting name (e.g. "Braintrust Weekly") |
| 66 | - Meeting date and time (e.g. "Wed Mar 5, 15:00 ART") |
| 67 | - Who requested / context |
| 68 | - Granola citation link |
| 69 | |
| 70 | **Rules:** |
| 71 | - **Only your actions**: Granola summaries often list "next steps" without clear ownersh |