액션 아이템 → 투두리스트 + 이메일 초안
설정 — 시작 전 필독
../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) 전후에 로그를 기록하세요. 오류 발생 시, 계속 진행하기 전에 전체 명령어와 표준 에러를 로그에 기록하세요.
단계
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가 놓친 회의를 포착하는 데 사용합니다.
중요 날짜 구문: gog 플래그에는 +1 day, today, tomorrow 같은 상대 표현을 사용하지 말고, 명시적으로 -03:00 오프셋이 포함된 ISO8601 날짜를 사용하세요. 항상 실제 날짜 문자열을 계산하세요.
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단계의 캘린더 이벤트와 비교하세요. 참석자가 있는 캘린더 회의 중 15분 이내 시간 중복으로 Granola와 일치하지 않는 항목이 있으면 경고를 로그에 기록하세요. 해당 회의는 기록되지 않았을 수 있습니다. 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 작업 생성
참고: 동일한 명령어에서 env를 로드하세요. 각 셸 호출은 새로운 세션입니다.
CLI 사용법은 {user.workspace}/skills/todoist-api/SKILL.md를 읽으세요. 각 액션 아이템에 대해:
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>"
작업 설명에는 반드시 다음이 포함되어야 합니다:
- 회의 이름 (예: "Braintrust Weekly")
- 회의 날짜 및 시간 (예: "Wed Mar 5, 15:00 ART")
- 요청자 / 맥락
- Granola 인용 링크
규칙:
- 내 작업만: Granola 요약에는 소유권이 명확하지 않은 "다음 단계"가 자주 나열됩니다. 의심스러우면 행동이 상대방에게 속할 수 있는 경우(예: "자신의 콘텐츠 소화", "가능 여부 확인", "우리에게 다시 연락") 작업을 생성하지 마세요. 의심스러우면 소유권 작업 대신 후속 작업("X에게 Y에 대해 연락하기")을 생성하세요.
- 상대방의 약속 캡처: 상대방이 어떤 일을 하겠다고 말한 경우(예: "2일 후에 다시 연락드리겠습니다"), 그 일을 직접 수행하는 작업이 아니라 적절한 기한이 있는 후속/연락 작업을 생성하세요.
- 구체성: 모든 작업에는 특정 사람/회사/프로젝트 이름이 반드시 포함되어야 합니다.
- 마감일: 암시된 마감일이 있으면 자연어로
--due를 사용하세요. - 라벨: 상황에 맞게 태그: intro, follow-up, email, urgent
- 우선순위: 4=긴급/시간 중요, 3=약속된 인도물, 2=일반 후속 조치, 1=일반
순차적 단계에 대한 작업 분할 금지 (필수)
동일한 워크플로우의 일부인 단계에 대해 별도의 작업을 절대 생성하지 마세요. 작업이 "X를 준비한 다음 X를 보내는 것"이라면 — 그것은 두 개의 작업이 아니라 하나의 작업입니다. 예:
- ❌ "제안서 작성" + "제안서 보내기" → ✅ "제안서 작성 및 보내기"
- ❌ "초안 작성" + "이메일 보내기" → ✅ "X에게 초안 작성 및 이메일 보내기"
- ❌ "덱 검토" + "덱 공유" → ✅ "X와 덱 검토 및 공유"
의도당 하나의 작업. 사용자는 자연스럽게 단계를 순서대로 수행할 것입니다.
작업 중복 제거 (필수)
작업을 생성하기 전에 열려 있는 Todoist 작업에 대해 중복 확인을 실행하세요:
- 제안된 제목 정규화 (소문자, 구두점 제거, 공백 축소)
- 열린 작업 검색(
source {user.workspace}/.env && todoist-cli list --filter "!completed") 및 정규화된 내용 비교 - 거의 동일한 인트로 작업은 중복으로 처리 (예: "David을 Marcos에게 소개" vs "David (n8n)을 Marcos Nils에게 소개")
- 중복이 있는 경우: 새 작업을 생성하지 말고, 유용한 경우 기존 작업 설명에 회의 맥락을 추가하세요.
- 출력에서 중복 결정 사항을
Skipped as duplicates:아래에 보고하세요.
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: <name>을 보고하세요. - WhatsApp 결과에
생성된 소개 초안:섹션을 포함하여 각 소개 쌍과 그것이 Gmail에서 초안 작성되었는지 또는 이메일 누락으로 차단되었는지 나열하세요.
첫 VC / 첫 딜플로우 콜 후속 (필수)
VC 또는 딜플로우 회사와의 첫 통화인 경우:
- 첫 번째 회의 후속 초안을 생성하세요 (아래 제안서 전용 규칙에 의해 차단되지 않는 한).
- 일반적인 인사말이 아닌 회의별 맥락(논의된 내용, 명시적 다음 단계, 구체적인 제안)을 본문에 사용하세요.
- 자신의 포지셔닝(업무 방식)을 포함하고 관련된 경우
{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가 실패하면: 전체 명령어 + 표준 에러와 함께 오류를 로그에 기록하고(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가 소싱되었고 토큰이 유효한지 확인하세요. 오류를 보고하세요.- Grain MCP를 사용할 수 없으면: Granola 전용 추출로 진행하고, 출력에 "⚠️ Grain 사용 불가, 결과는 Granola 전용입니다."라고 기록하세요.
- 어떤 단계가 실패하더라도 가능한 경우 나머지 단계를 계속 진행하세요. 하나의 실패로 전체 실행을 중단하지 마세요.
중복 제거 (매우 중요 — 중복 작업 방지)
회의 수준 중복 제거
- 처리 전 첫 단계:
{user.workspace}/state/processed-meetings-YYYY-MM-DD.json파일을 읽으세요 (존재하는 경우 — Granola 회의 ID 배열). - 이미 해당 목록에 있는 ID의 회의는 건너뛰세요. 다시 처리하지 마세요.
- 각 회의를 처리한 직후(다음 회의로 넘어가기 전), 해당 Granola 회의 ID를 파일에 추가하세요. 마지막까지 기다리지 마세요. 각 회의 후에 작성하여 다른 크론과의 경합을 방지하세요.
- 이 파일은 "이 회의가 오늘 이미 처리되었는가?"에 대한 단일 진실 공급원입니다.
참고: 제목은 동일한 이름을 공유하는 반복 회의의 경우 취약합니다. 항상 Granola 회의 ID로 중복을 제거하세요.
작업 수준 중복 제거
- 어떤 작업을 생성하기 전에, 열려 있는 작업 과 최근 완료된 작업 모두에서 거의 중복되는 항목이 있는지 확인하세요:
- 열린 작업 가져오기:
source {user.workspace}/.env && todoist-cli list - 오늘 완료된 작업 가져오기:
since=<오늘 00:00 UTC>와 함께 Todoist Sync APIcompleted/get_all을 사용하거나 지원되는 경우source {user.workspace}/.env && todoist-cli list --filter "completed today"를 사용하세요.
- 동일한 사람 + 동일한 행동 의도 = 중복 (예: "Morgane에게 Hank에 대해 문자"와 "Morgane(Braintrust)에게 Hank 통화 후 문자")
- 정규화: 소문자, 괄호 안 내용 제거, 공백 축소
- 열려 있거나 완료된 항목 중 하나라도 중복이 있으면 → 건너뛰고, 생성하지 마세요.
- 열린 작업 가져오기:
- 건너뛴 중복을 출력에 보고하세요: "⏭️ 건너뜀 (이미 존재함): [작업]"
- 완료된 작업을 확인하는 이유: 사용자가 오늘 일찍 회의 후 크론에 의해 생성된 작업을 이미 완료했을 수 있습니다. 다시 생성하는 것은 잘못입니다. 작업이 완료되었기 때문입니다.
두 계층이 중요한 이유
회의 후 크론은 회의별로 실행됩니다. 일일 하루 마감 크론은 모든 회의를 처리합니다. 회의 수준 중복 제거가 없으면 동일한 회의가 두 번 처리됩니다. 작업 수준 중복 제거가 없으면, 회의가 다시 처리되더라도(예: 파일 쓰기 실패) 개별 작업은 중복되지 않습니다.
중복 제거는 협상 불가입니다
회의가 processed-meetings-YYYY-MM-DD.json에 나타나면 어떤 상황에서도 다시 처리하지 마세요. 회의 후 크론이 "무언가를 놓쳤을 수도 있다"고 생각하더라도 마찬가지입니다. 회의 후 크론이 이미 처리했습니다. 문제가 있었다면 사용자가 수동으로 재실행을 요청할 것입니다.
출력
- 생성된 작업 또는 초안 → 짧은 요약과 함께 작업 나열
- 완료된 작업 (회의에서 완료됨) → ✅와 함께 나열
- 항상 처리된 특정 회의 이름을 명시하세요 (예: "Fyxer 통화, Braintrust 주간 회의, HGP Staff에서") — 절대 "오늘 회의에서"라고 말하지 마세요.
- 회의가 없거나 액션 아이템이 없으면 → NO_REPLY
Grain과 교차 검증 (활성 — 대본 수준 확인)
Grain MCP를 사용할 수 있으며 전체 대본에 접근할 수 있습니다. Granola에서 액션 아이템을 추출한 후:
- Grain에서 회의 찾기:
mcporter call grain.list_attended_meetings --args '{}'참고: Grain 스키마는start_date/end_date필터를 지원하지 않습니다. 빈 인수로 호출하고start_datetime으로 결과를 수동으로 필터링하여 오늘 날짜 범위와 일치시키세요. - 대본 가져오기:
mcporter call grain.fetch_meeting --args '{"meeting_id": "<grain_meeting_id>"}' - 분석: 각 Grain 회의 대본에 대해
python3 {user.workspace}/scripts/skill_log.py action-items DEBUG "Grain transcript for <meeting_title> fetched; character count: <length>" - 비교 및 보강: 각 회의의 Grain 대본과 Granola 노트를 병렬로 비교하세요:
- Granola가 모든 액션 아이템을 포착했는지 확인하세요. Grain에서 Granola가 놓친 추가 액션 아이템을 찾으면 이를 포함하고 태그를
[Grain에서 확인됨]으로 지정하세요. - Granola가 액션 아이템을 잘못 귀속했는지 확인하세요 (예: 사용자에게 속한 것으로 보이지만 실제로는 상대방이 한 약속인 경우). 그러한 경우, 소유권을 전환하거나 작업을 생성하지 마세요.
- Grain이 Granola의 세부 사항(이름, 회사, 약속)을 확인하는 경우, 해당 액션 아이템에
✅ Grain 확인됨: [구체적 세부 사항]을 추가하여 출력을 보강하세요. - Grain이 액션 아이템과 관련된 모호성을 명확히 하는 경우, 명확히 된 내용을 포함하여 작업이나 이메일 초안을 보강하세요.
- Granola가 모든 액션 아이템을 포착했는지 확인하세요. Grain에서 Granola가 놓친 추가 액션 아이템을 찾으면 이를 포함하고 태그를
최종 전달
모든 작업을 생성하고 이메일 초안을 작성한 후(또는 아무것도 할 것이 없는 경우 NO_REPLY), 다음을 통해 결과를 {user.whatsapp}으로 보내세요:
python3 {user.workspace}/scripts/send_whatsapp.py "{user.whatsapp}" "<message_body>"
메시지 본문에는 다음이 포함되어야 합니다:
- 📋 생성된 Todoist 작업 수
- ✉️ 생성된 이메일 초안 수 (있는 경우)
- ✅ 완료된 작업 (회의에서 완료된 경우)
- ⏭️ 중복으로 건너뛴 작업
- 처리된 특정 회의 목록
- Grain을 찾을 수 있는 경우 및 확인/보강이 발생한 경우: 🔍 Grain 확인됨: [세부 사항]