$npx -y skills add mgonto/executive-assistant-skills --skill meeting-prepPrepare briefings for today's meetings — attendee research, email history, past meeting notes, LinkedIn, and company context. Use when running the daily meeting prep cron, or when user asks to prepare for meetings, review who they're meeting with, or get context on upcoming calls
| 1 | # Daily Meeting Prep |
| 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` — user's name |
| 7 | - `primary_email`, `work_email` — Gmail accounts to check |
| 8 | - `whatsapp` — WhatsApp number for delivery |
| 9 | - `timezone` — IANA timezone (e.g. America/Argentina/Buenos_Aires) |
| 10 | - `slack_username` — Slack DM target |
| 11 | - `workspace` — absolute path to OpenClaw workspace (e.g. /home/user/.openclaw/workspace) |
| 12 | |
| 13 | Do not proceed until you have these values. |
| 14 | |
| 15 | ## Debug Logging (MANDATORY) |
| 16 | Read `../config/DEBUG_LOGGING.md` for the full convention. Use `python3 {user.workspace}/scripts/skill_log.py meeting-prep <level> "<message>" ['<details>']` at every key step. Log BEFORE and AFTER every external call (gog, mcporter, Granola, web search). On any error, log the full command and stderr before continuing. |
| 17 | |
| 18 | ## Scope |
| 19 | - Timezone: {user.timezone} |
| 20 | - Calendars: primary of {user.primary_email} AND {user.work_email} |
| 21 | - Today's meetings only |
| 22 | |
| 23 | **Timezone note:** Use explicit ART-bounded ISO8601 timestamps for calendar queries, NOT `--date`. Example: `gog calendar list primary --account <email> --from "2026-03-03T00:00:00-03:00" --to "2026-03-04T00:00:00-03:00" --json`. The `--date` flag uses UTC boundaries which misaligns with ART. |
| 24 | - **ALL meetings with attendees** — both external and internal |
| 25 | - Skip personal/solo events with no attendees (e.g. "Personal Trainer", "Golf", all-day reminders) |
| 26 | |
| 27 | ## Meeting types |
| 28 | |
| 29 | ### External meetings (attendees outside your email domains) |
| 30 | Full research brief (email context, Granola, LinkedIn, company research) — see below. |
| 31 | |
| 32 | ### Internal meetings (all attendees from your email domains: hypergrowthpartners.com, growth.li) |
| 33 | Lighter brief — no LinkedIn/company research needed, but still include: |
| 34 | - Attendee list |
| 35 | - Granola context from previous instances of this recurring meeting |
| 36 | - Recent email threads related to the meeting topic/agenda |
| 37 | - Any open action items from last time |
| 38 | - Format: same structure but skip LinkedIn/company sections |
| 39 | |
| 40 | ### Recurring collaborative meetings (e.g. podcasts, content sessions with external co-hosts) |
| 41 | These are external meetings — give them full briefs. Don't skip recurring meetings just because they're familiar. |
| 42 | |
| 43 | ## Error handling |
| 44 | - If `gog calendar` fails for one account: continue with the other account, note "⚠️ [account] calendar unavailable" in output. |
| 45 | - If Granola/Grain fails: continue without meeting history, note it per meeting. |
| 46 | - If WhatsApp delivery fails: attempt Slack delivery. If both fail, save to state file and report error. |
| 47 | |
| 48 | ## For each meeting |
| 49 | |
| 50 | ### 1. Event basics |
| 51 | Title, local time ({user.timezone}), attendees. |
| 52 | |
| 53 | **RSVP status (MANDATORY):** For each attendee, check `responseStatus` from the calendar event: |
| 54 | - `accepted` → no flag needed |
| 55 | - `needsAction` → flag as "⚠️ hasn't responded" |
| 56 | - `declined` → flag as "❌ declined" |
| 57 | - `tentative` → flag as "❓ tentative" |
| 58 | |
| 59 | If ANY non-organizer external attendee has NOT accepted (`needsAction`, `tentative`, or `declined`), add a visible line in the brief: |
| 60 | > ⚠️ *RSVP:* <name> hasn't accepted yet |
| 61 | |
| 62 | This is informational — it doesn't mean they won't join, but it's useful to know ahead of time, especially for first calls or important meetings. |
| 63 | |
| 64 | ### 2. Email context (90-day lookback, with historical fallback) |
| 65 | Search Gmail both accounts for exchanges with attendees. For EACH attendee, search using these strategies in order: |
| 66 | 1. **Email address** (primary — from calendar invite): `from:<email> OR to:<email>` |
| 67 | 2. **Full name**: `"firstname lastname"` |
| 68 | 3. **First name + "intro"**: `"intro firstname"` (catches informal intro subjects) |
| 69 | 4. **First name + company**: `"firstname companyname"` |
| 70 | |
| 71 | The attendee's email from the calendar invite is the most reliable identifier — always start there. |
| 72 | |
| 73 | **Intro discovery** (after general email search): |
| 74 | 5. Search for intro emails involving the attendee: `subject:intro <email>`, `subject:intro <firstname>`, `subject:introduction <email>` |
| 75 | 6. Also check threads where a third party CC'd/introduced the attendee |
| 76 | |
| 77 | **Recent email context** (after intro discovery): |
| 78 | 7. Pull the most recent email threads with this attendee (by email address) to surface any recent updates, asks, or context leading into today's call |
| 79 | |
| 80 | **Historical fallback** (if no results from 90-day search): |
| 81 | 8. Run a broader search with NO date filter: `from:<email> OR to:<email>` — this catches long-standing relationships where the last email was months/years ago. If older threads exist, this is NOT a first call — note the relationship history. |
| 82 | |
| 83 | - First call vs follow-up? Base this on ALL email history found (including historical), not just 90- |