Claude
Skills
Sign in
Back

action-items-todoist

Included with Lifetime
$97 forever

Extract 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 general email drafting without meeting context.

Productivitybusinessaction-items

What this skill does

# Action Items → Todoist + Email Drafts

## Config — read before starting

Read `../config/user.json` (resolves to `~/executive-assistant-skills/config/user.json`).
Extract and use throughout:

- `name`, `full_name` — to identify your action items in meeting notes (e.g. "Gonto (Martin)")
- `whatsapp` — for result delivery
- `workspace` — absolute path to OpenClaw workspace

Do not proceed until you have these values.

## Debug Logging (MANDATORY)

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.

## Steps

### 0. Check today's calendar for meetings (BOTH accounts)

Before querying Granola, get today's actual meetings from BOTH calendars to know what to expect:

```bash
python3 {user.workspace}/scripts/skill_log.py action-items INFO "Starting action-items run"

# Get today's date in YYYY-MM-DD and tomorrow's
TODAY=$(date -u -d "$(TZ=America/Argentina/Buenos_Aires date +%Y-%m-%d)" +%Y-%m-%d)
TOMORROW=$(date -u -d "$(TZ=America/Argentina/Buenos_Aires date -d '+1 day' +%Y-%m-%d)" +%Y-%m-%d)

# Check BOTH calendars
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
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
```

Log the results: `python3 {user.workspace}/scripts/skill_log.py action-items DEBUG "Calendar events found" '{"primary": N, "work": M, "total": N+M}'`

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.

**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.

### 1. Get today's meetings from Granola

**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.

```bash
mcporter call granola list_meetings --args '{"time_range": "custom", "custom_start": "<today YYYY-MM-DD>", "custom_end": "<tomorrow YYYY-MM-DD>"}'
```

Collect meeting IDs and titles. Log: `python3 {user.workspace}/scripts/skill_log.py action-items INFO "Granola meetings found" '{"count": N, "titles": [...]}'`

**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.

Skip if no meetings (from either Granola or calendar).

### 2. Query Granola for MY action items + email triggers

```bash
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>", ...]}'
```

Pass ALL meeting IDs. Preserve citation links.

### 3. Create Todoist tasks

> **Note:** Load env in the same command — each shell call is a fresh session.

Read `{user.workspace}/skills/todoist-api/SKILL.md` for CLI usage. For each action item:

```bash
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>"
```

**Task description MUST include:**

- Meeting name (e.g. "Braintrust Weekly")
- Meeting date and time (e.g. "Wed Mar 5, 15:00 ART")
- Who requested / context
- Granola citation link

**Rules:**

- **Only your actions**: Granola summaries often list "next steps" without clear ownership. Be skeptical — if the action could belong to the other person (e.g. "digest their own content", "check availability", "get back to us"), do NOT create a task. When in doubt, create a FOLLOW-UP task ("Ping X about Y") rather than an ownership task.
- **Capture commitments from others**: If the other person said they'd do something (e.g. "I'll get back in 2 days"), create a follow-up/ping task with the appropriate due date, not a task to do the thing yourself.
- **Specificity**: Every task MUST include specific name of person/company/project
- **Due dates**: If implied deadline, use `--due` with natural language
- **Labels**: Tag: intro, follow-up, email, urgent as appropriate
- **Priority**: 4=urgent/time-sensitive, 3=promised deliverables, 2=general follow-ups, 1=normal

#### No split tasks for sequential steps (MANDATORY)

Never create separate tasks for steps that are part of the same workflow. If the action is "prepare X then send X" — that's ONE task, not two. Examples:

- ❌ "Build proposal" + "Send proposal" → ✅ "Build and send proposal"
- ❌ "Write draft" + "Send email" → ✅ "Draft and send email to X"
- ❌ "Review deck" + "Share deck" → ✅ "Review and share deck with X"

One task per intent. The user will naturally do the steps in order.

#### Todo dedup (MANDATORY)

Before creating a task, run a duplicate check against open Todoist tasks:

1. Normalize proposed title (lowercase, trim punctuation, collapse whitespace)
2. Search open tasks (`source {user.workspace}/.env && todoist-cli list --filter "!completed"`) and compare normalized content
3. Treat near-identical intro tasks as duplicates (e.g., "Intro David to Marcos" vs "Intro David (n8n) to Marcos Nils")
4. If duplicate exists: do NOT create a new task; append meeting context to the existing task description when useful
5. In output, report dedup decisions under `Skipped as duplicates:`

### 4. Draft follow-up emails

For ANY email that needs drafting (intros, follow-ups, VC replies, sending docs, etc.):

- **Read and follow `~/executive-assistant-skills/email-drafting/SKILL.md`** — it is the single source of truth for all drafting rules, style, templates, humanization, and delivery
- Identify draft triggers from meeting notes:
  - Promised intros or follow-ups
  - Promised docs/PDFs/decks
  - First call with a VC or new lead
  - Any promise to email someone
- When in doubt about whether to draft → DRAFT IT
- **Exception**: The proposal-only commitment rule below overrides this. If the commitment is to build a proposal first, do NOT draft — create a Todoist task only.
- **HGP Deck**: `{user.workspace}/assets/HGP_Deck_2025.pdf` — attach via `--attach {user.workspace}/assets/HGP_Deck_2025.pdf`. Say "Hypergrowth Partners deck" in the email body (not "one-pager" or "our deck")
- **When drafting intros to known contacts**: search sent emails for previous intros to them, use the same format, tone, and description

#### Intro-specific hard requirements (MANDATORY)

If action items include intros, follow this exactly:

1. Create **one separate intro draft per intro pair** (never merge multiple intros into one generic follow-up).
2. Subject must be explicit: `Intro: <Person A> <> <Person B>`.
3. Body must include:
   - one-line who each person is,
   - one-line context for why this intro is happening,
   - close with `I'll let you two take it from

Related in Productivity