行動項目 → Todoist + 郵件草稿
設定 — 開始前請先閱讀
讀取 ../config/user.json(解析為 ~/executive-assistant-skills/config/user.json)。
擷取並在後續步驟中使用以下值:
name、full_name— 用以在會議記錄中識別您的行動項目(例如「Gonto (Martin)」)whatsapp— 用於傳送結果workspace— OpenClaw 工作區的絕對路徑
在取得這些值之前,請勿繼續。
偵錯記錄(必做)
閱讀 ../config/DEBUG_LOGGING.md 以了解完整規範。在每個關鍵步驟使用 python3 {user.workspace}/scripts/skill_log.py action-items <level> "<message>" ['<details>']。在每次外部呼叫(gog、mcporter、todoist-cli)前後都進行記錄。若發生任何錯誤,請在繼續前記錄完整命令與 stderr。
步驟
0. 檢查今日日曆中的會議(兩個帳號)
在查詢 Granola 之前,先從兩個日曆取得今日實際的會議,以了解預期內容:
python3 {user.workspace}/scripts/skill_log.py action-items INFO "Starting action-items run"
# 取得今日日期(YYYY-MM-DD)和明日日期
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)
# 檢查兩個日曆
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
記錄結果:python3 {user.workspace}/scripts/skill_log.py action-items DEBUG "Calendar events found" '{"primary": N, "work": M, "total": N+M}'
合併兩個日曆的事件。篩選出有與會者的會議(跳過個人/獨自活動)。這能提供今日實際會議的真相,用以交叉比對 Granola 的結果,並找出 Granola 遺漏的任何會議。
關鍵日期語法: 使用帶有 -03:00 時區偏移的明確 ISO8601 日期。請勿在 gog 標誌中使用 +1 day、today 或 tomorrow 等相對表達式——它們可能不受支援。請始終計算實際日期字串。
1. 從 Granola 取得今日會議
時區注意事項: Granola 以 UTC 儲存會議時間。對於 ART(UTC-3),查詢「今天」意味著要使用今天的日期和明天的日期(UTC 時間)。例如,對於 ART 時間的 3 月 3 日,查詢 custom_start: "2026-03-03" 和 custom_end: "2026-03-04" 以捕捉所有 ART 白天時段的會議。
mcporter call granola list_meetings --args '{"time_range": "custom", "custom_start": "<today YYYY-MM-DD>", "custom_end": "<tomorrow YYYY-MM-DD>"}'
收集會議 ID 和標題。記錄:python3 {user.workspace}/scripts/skill_log.py action-items INFO "Granola meetings found" '{"count": N, "titles": [...]}'
與日曆交叉比對: 將 Granola 會議與步驟 0 的日曆事件進行比較。如果一個有與會者的日曆會議在 Granola 中沒有匹配項(時間重疊在 15 分鐘內),請記錄警告——該會議可能未被記錄。繼續處理 Granola 已有的資料,但在輸出中標註未匹配的會議。
如果(Granola 或日曆的)會議為空,則跳過。
2. 查詢 Granola 以取得我的行動項目 + 郵件觸發器
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>", ...]}'
傳入所有會議 ID。保留引用連結。
3. 建立 Todoist 任務
注意: 在相同命令中載入環境——每次 shell 呼叫都是一個新的工作階段。
閱讀 {user.workspace}/skills/todoist-api/SKILL.md 以了解 CLI 用法。對於每個行動項目:
source {user.workspace}/.env && todoist-cli add "<可執行的標題>" --description "<情境:會議名稱、會議日期/時間、提出者、Granola 連結>" --priority <1-4> --labels "<相關標籤>"
任務說明必須包含:
- 會議名稱(例如「Braintrust Weekly」)
- 會議日期和時間(例如「週三 3 月 5 日,15:00 ART」)
- 提出者/情境
- Granola 引用連結
規則:
- 僅限您的行動:Granola 摘要時常列出「下一步驟」而無明確負責人。請保持懷疑——若行動可能屬於對方(例如「消化自己的內容」、「檢查可行性」、「回覆我們」),請勿建立任務。有疑慮時,建立後續追蹤任務(「向 X 確認 Y 的進度」),而不是所有權任務。
- 記錄他人的承諾:如果對方表示會做某事(例如「我兩天後回覆」),請建立一個帶有適當到期日的後續/確認任務,而不是建立一個您要親自完成的任務。
- 明確性:每個任務必須包含具體的人員/公司/專案名稱
- 到期日:若有暗示的截止日期,請使用
--due搭配自然語言 - 標籤:依情況標記:介紹、後續追蹤、電子郵件、緊急
- 優先級:4=緊急/時效性,3=已承諾的 deliverables,2=一般後續追蹤,1=一般
不再為連續步驟拆分任務(必做)
切勿為屬於同一個工作流程的步驟建立單獨的任務。如果行動是「準備 X 然後寄送 X」——那是一個任務,而不是兩個。例如:
- ❌「建立提案」+「寄送提案」→ ✅「建立並寄送提案」
- ❌「撰寫草稿」+「寄送郵件」→ ✅「為 X 撰寫並寄送郵件」
- ❌「審閱簡報」+「分享簡報」→ ✅「向 X 審閱並分享簡報」
每個意圖一個任務。使用者自然會按順序執行這些步驟。
任務去重(必做)
在建立任務之前,請對已開啟的 Todoist 任務進行重複檢查:
- 標準化提議的標題(轉為小寫、移除標點符號、合併空白)
- 搜尋已開啟的任務(
source {user.workspace}/.env && todoist-cli list --filter "!completed")並比較標準化後的內容 - 將幾乎相同的介紹任務視為重複(例如「介紹 David 給 Marcos」vs「介紹 David (n8n) 給 Marcos Nils」)
- 如果重複項存在:請勿建立新任務;若有幫助,可將會議情境附加到現有任務的說明中
- 在輸出中,於「因重複而跳過:」下報告去重決定
4. 草擬後續郵件
對於任何需要草擬的電子郵件(介紹、後續追蹤、VC 回覆、寄送文件等):
- 閱讀並遵循
~/executive-assistant-skills/email-drafting/SKILL.md——它是所有草擬規則、風格、範本、人性化處理和傳送方式的唯一真實來源 - 從會議記錄中識別草擬觸發事件:
- 已承諾的介紹或後續追蹤
- 已承諾的文件/PDF/簡報
- 與 VC 或新客戶的第一次通話
- 任何承諾透過電子郵件聯絡某人的情況
- 不確定是否要草擬時 → 直接草擬
- 例外情況:下面的僅提案承諾規則會覆蓋此規則。如果承諾是先建立提案,請勿草擬——僅建立 Todoist 任務。
- HGP 簡報:
{user.workspace}/assets/HGP_Deck_2025.pdf——透過--attach {user.workspace}/assets/HGP_Deck_2025.pdf附加。在郵件內文中寫「Hypergrowth Partners 簡報」(而不是「一頁式文件」或「我們的簡報」) - 為已知聯絡人草擬介紹信時:搜尋已寄送的郵件中關於他們的先前介紹信,使用相同的格式、語氣和描述
介紹信特定硬性要求(必做)
如果行動項目包含介紹,請完全按照以下步驟操作:
- 為每個介紹配對建立一個獨立的介紹草稿(切勿將多個介紹合併到一個通用的後續追蹤郵件中)。
- 主旨必須明確:
介紹:<人員 A> <> <人員 B>。 - 內文必須包含:
- 各一行介紹每位人員的背景,
- 一行說明進行此介紹的情境,
- 以「接下來就交給你們兩位。」和
{user.signature}作結。
- 切勿在已承諾介紹時,用通用的會議總結郵件(例如「今天會議很棒」)來取代介紹草稿。
- 如果已知收件者郵件地址,請立即建立 Gmail 草稿;如果缺少任何郵件地址,仍產生完整的草稿文字,並報告
MISSING_EMAIL: <姓名>。 - 在 WhatsApp 結果中,包含「已建立的介紹草稿:」區段,列出每個介紹配對,並說明是在 Gmail 中草擬完成,還是因缺少郵件地址而受阻。
首次 VC / 首次 dealflow 通話後續追蹤(必做)
當會議是與 VC 或 dealflow 公司的第一次通話時:
- 建立第一次會議的後續追蹤草稿(除非被下面的僅提案規則阻止)。
- 在內文中使用會議特定的情境(討論了什麼、明確的下一步、具體的提議),而非通用的客套話。
- 在相關時,包含您的定位(您如何運作)並附加
{user.workspace}/assets/HGP_Deck_2025.pdf。 - 僅對於此類第一次會議的後續追蹤,允許使用「今天會議很棒」。
僅提案承諾規則(必做)
如果您承諾要「建立提案」(或類似:要優先準備的提案/簡報/範圍草案):
- 請勿草擬對外郵件。
- 建立一個單一的 Todoist 任務來建立並寄送提案——例如「建立並寄送給 Gabriel (BairesDev) 的顧問提案」。
- 不要為「建立」和「寄送」建立單獨的任務——那是多餘的。一個任務涵蓋整個生命週期。
5. 檢查今日會議是否完成了現有的 Todoist 任務
在處理行動項目後,也檢查是否有任何現有已開啟的 Todoist 任務在今日的會議中被處理/完成:
- 列出已開啟的任務:
source {user.workspace}/.env && todoist-cli list - 對於每個會議,檢查討論內容是否涵蓋或完成了任何已開啟的任務(例如,「與 Colin 分享 AI 策略」→ 在通話中直接與 Colin 討論了 AI 策略)
- 如果一個任務明顯在會議中已完成,將其標記為完成:
source {user.workspace}/.env && todoist-cli complete <task_id> - 在輸出中報告已完成的任務:「✅ 已完成:[任務] — 在 [會議名稱] 中已完成」
這能確保 Todoist 保持整潔並反映實際發生的情況。
錯誤處理
- 如果
gog calendar失敗:記錄錯誤(包含完整命令和 stderr)(python3 {user.workspace}/scripts/skill_log.py action-items ERROR "gog calendar failed" '{"command": "...", "stderr": "..."}'),繼續使用另一個帳號和/或僅使用 Granola。 - 如果
mcporter call granola因驗證錯誤失敗:報告「⚠️ Granola 驗證已過期,請執行mcporter auth granola --reset」並停止。 - 如果
todoist-cli失敗:驗證.env是否已載入且 token 有效。報告錯誤。 - 如果 Grain MCP 無法使用:繼續僅使用 Granola 提取,在輸出中註明「⚠️ Grain 無法使用,結果僅來自 Granola。」
- 如果任何步驟失敗,在可能的情況下繼續執行其餘步驟——不要因為一個失敗就中止整個執行。
去重(關鍵 — 防止重複任務)
會議層級去重
- 在任何處理之前的第一步:讀取
{user.workspace}/state/processed-meetings-YYYY-MM-DD.json(如果存在的話——Granola 會議 ID 的陣列) - 跳過任何 ID 已存在於該清單中的會議——不要重新處理它們
- 在處理完每個會議後立即(在處理下一個之前),將其 Granola 會議 ID 附加到該檔案中。不要等到最後——在每個會議後就寫入,以防止與其他 cron 任務發生競態條件。
- 該檔案是「這個會議今天是否已經被處理過?」的唯一事實來源。
注意: 對於共用相同名稱的週期性會議來說,標題是不可靠的。請始終使用 Granola 會議 ID 進行去重。
任務層級去重
- 在建立任何任務之前,檢查已開啟和最近完成的任務中是否有近似重複項:
- 取得已開啟的任務:
source {user.workspace}/.env && todoist-cli list - 取得今天完成的任務:使用 Todoist Sync API
completed/get_all,搭配since=<today 00:00 UTC>或source {user.workspace}/.env && todoist-cli list --filter "completed today"(如果支援)
- 相同人員 + 相同行動意圖 = 重複(例如「傳訊息給 Morgane 關於 Hank」和「在 Hank 通話後傳訊息給 Morgane (Braintrust)」)
- 標準化:轉為小寫、移除括號內的內容、合併空白
- 如果重複項存在於已開啟或已完成中 → 跳過,不要建立
- 取得已開啟的任務:
- 在輸出中報告跳過的重複項:「⏭️ 已跳過(已存在):[任務]」
- 為什麼要檢查已完成的任務:使用者可能已經完成了今天稍早會後 cron 所建立的任務。重新建立它是錯誤的——工作已經完成。
為什麼兩層都很重要
會後 cron 按會議觸發。每日結束 cron 處理所有會議。沒有會議層級去重,同一個會議會被處理兩次。沒有任務層級去重,即使會議被重新處理(例如檔案寫入失敗),個別任務也不會被重複。
去重是不可協商的
如果一個會議出現在 processed-meetings-YYYY-MM-DD.json 中,無論如何都不要再次處理它——即使您認為會後 cron「可能遺漏了某些東西」。會後 cron 已經處理過它了。如果它有問題,使用者會手動要求重新執行。
輸出
- 已建立的任務或已撰寫的草稿 → 列出任務及簡短摘要
- 已完成的任務(在會議中完成)→ 用 ✅ 列出
- 始終指定已處理的具體會議(例如「來自 Fyxer 通話、Braintrust 週會、HGP Staff」)——切勿說「來自今日會議」
- 無會議或無行動項目 → NO_REPLY
與 Grain 交叉比對(啟用中 — 逐字稿層級驗證)
Grain MCP 可用,具有完整的逐字稿存取權限。從 Granola 提取行動項目後:
- 在 Grain 中找到會議:
mcporter call grain.list_attended_meetings --args '{}'注意:Grain 的 schema 不支援start_date/end_date篩選器。使用空參數呼叫,並透過start_datetime手動篩選結果以匹配今天的日期範圍。 - 取得逐字稿:
mcporter call grain.fetch_me