Skip to content

Latest commit

Β 

History

303 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Meeting Agent

Slack 기반 AI λ―ΈνŒ… μ–΄μ‹œμŠ€ν„΄νŠΈ. λ―ΈνŒ…μ˜ μ „(Before) Β· 쀑(During) Β· ν›„(After) μ „ 단계λ₯Ό μžλ™ν™”ν•©λ‹ˆλ‹€.

Before Agent  β†’  During Agent  β†’  After Agent
업체/인물 λ¦¬μ„œμΉ˜    트랜슀크립트 μˆ˜μ§‘    회의둝 μ™ΈλΆ€ λ°œμ†‘
λΈŒλ¦¬ν•‘ 생성         μˆ˜λ™ λ…ΈνŠΈ μ„Έμ…˜       μ•‘μ…˜μ•„μ΄ν…œ μ•Œλ¦Ό
λ―ΈνŒ… 생성/μ˜ˆμ•½      λ‚΄λΆ€Β·μ™ΈλΆ€ 회의둝     Contacts μžλ™ κ°±μ‹ 

μ£Όμš” κΈ°λŠ₯

단계 κΈ°λŠ₯
Before μ™ΈλΆ€ λ―ΈνŒ… μžλ™ 감지 β†’ λ―ΈνŒ… 헀더 μ¦‰μ‹œ λ°œμ†‘ β†’ 업체·인물 λ¦¬μ„œμΉ˜ λ°±κ·ΈλΌμš΄λ“œ 순차 λ°œμ†‘
Before μžμ—°μ–΄ λ―ΈνŒ… 생성 (내일 μ˜€μ „ 10μ‹œ KISA λ―ΈνŒ… μž‘μ•„μ€˜) + μŠ€λ ˆλ“œ λ‹΅κΈ€λ‘œ 업체λͺ…Β·μž₯μ†Œ λ“± μˆ˜μ •
Before λͺ…함 DM μ—…λ‘œλ“œ β†’ Claude Vision OCR β†’ Contacts μžλ™ 등둝
During Google Meet 트랜슀크립트 μžλ™ 폴링 (10λΆ„ μ£ΌκΈ°) + 늦게 도착 μ‹œ 회의둝 μžλ™ 보강
During Slack μˆ˜λ™ λ…ΈνŠΈ μ„Έμ…˜ (/λ―ΈνŒ…μ‹œμž‘, /λ©”λͺ¨, /λ―ΈνŒ…μ’…λ£Œ)
During μŒμ„± 파일 μ—…λ‘œλ“œ β†’ Deepgram STT β†’ λ©”λͺ¨ μžλ™ 등둝
During ν…μŠ€νŠΈ λ¬Έμ„œ μ—…λ‘œλ“œ (TXT, MD, PDF, DOCX λ“±) β€” μ„Έμ…˜ 쀑엔 λ©”λͺ¨ μΆ”κ°€, μ„Έμ…˜ 없이 μ—…λ‘œλ“œ μ‹œ 트랜슀크립트둜 κ°„μ£Όν•΄ 회의둝 μ΄ˆμ•ˆ μ¦‰μ‹œ 생성 (μΊ˜λ¦°λ” μ—†λŠ” λ―ΈνŒ…λ„ 지원)
After λ‚΄λΆ€μš©Β·μ™ΈλΆ€μš© 회의둝 μ΄ˆμ•ˆ κ²€ν† /νŽΈμ§‘ ν›„ Drive μ €μž₯
After μ™ΈλΆ€μš© 회의둝 Gmail λ°œμ†‘ (μ‚¬μš©μž 승인 ν›„)
After μ•‘μ…˜μ•„μ΄ν…œ μΆ”μΆœ β†’ λ‹΄λ‹Ήμž DM β†’ 맀일 08:00 λ¦¬λ§ˆμΈλ”
검색 회의둝 검색 (업체λͺ…Β·νšŒμ˜λͺ…Β·λ‚ μ§œ β€” μžμ—°μ–΄ 지원: "μ§€λ‚œ λͺ©μš”일", "4μ›” 13일", "μ§€λ‚œλ‹¬")
λ©”λͺ¨ 업체 λ©”λͺ¨ μ €μž₯ (카카였 λ©”λͺ¨ β€” PoC μ˜ˆμ‚° 확보) β†’ Drive 업체 Wiki νŒŒμΌμ— 기둝
μ œμ•ˆμ„œ 회의 기반 μ œμ•ˆμ„œ κ°œμš”Β·μ΄ˆμ•ˆ 생성 (μŠ€λ ˆλ“œμ—μ„œ μˆ˜μ • κ°€λŠ₯)
Feedback μ‚¬μš©μž ν”Όλ“œλ°± (κΈ°λŠ₯ μš”μ²­Β·κ°œμ„ Β·λ²„κ·Έ) μˆ˜μ§‘ β†’ 맀일 22:00 κ΄€λ¦¬μž λ‹€μ΄μ œμŠ€νŠΈ λ°œμ†‘
Trello μ£Όκ°„ λ³΄κ³ μ„œ λ§€μ£Ό 금 21:00 μ›Œν¬μŠ€νŽ˜μ΄μŠ€ μ „ λ³΄λ“œ 변경사항 집계 β†’ Google Docs 원본 + Slack μš”μ•½ λ°œμ†‘

기술 μŠ€νƒ

ν•­λͺ© λ‚΄μš©
LLM Claude claude-haiku-4-5 (κΈ°λ³Έ / λͺ…함 OCR) + claude-sonnet-4-5 (회의둝 μƒμ„±Β·μˆ˜μ •, μ œμ•ˆμ„œ)
STT Deepgram REST API (nova-2 λͺ¨λΈ, ν•œκ΅­μ–΄)
μΈν„°νŽ˜μ΄μŠ€ Slack Bolt (Socket Mode)
Google 연동 Calendar Β· Drive Β· Gmail Β· Docs Β· Meet API
μŠ€μΌ€μ€„λŸ¬ APScheduler (λΈŒλ¦¬ν•‘ 09:00, 트랜슀크립트 폴링 10λΆ„, λ¦¬λ§ˆμΈλ” 08:00, ν”Όλ“œλ°± λ‹€μ΄μ œμŠ€νŠΈ 22:00, Trello μ£Όκ°„ λ³΄κ³ μ„œ 금 21:00)
μ €μž₯μ†Œ SQLite + Fernet μ•”ν˜Έν™” (μ‚¬μš©μž 토큰), Google Drive (Contacts Β· 회의둝)

λΉ λ₯Έ μ‹œμž‘

1. μ˜μ‘΄μ„± μ„€μΉ˜

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

2. ν™˜κ²½ λ³€μˆ˜ μ„€μ •

.env 파일 생성:

# Slack
SLACK_BOT_TOKEN=xoxb-...
SLACK_APP_TOKEN=xapp-...

# LLM
GOOGLE_API_KEY=...
ANTHROPIC_API_KEY=...

# STT
DEEPGRAM_API_KEY=...

# Google OAuth
OAUTH_CALLBACK_URL=https://your-domain.com/oauth/callback

# μ•”ν˜Έν™” ν‚€ (Fernet)
ENCRYPTION_KEY=...

# λ‚΄λΆ€ 도메인 (μ‰Όν‘œ ꡬ뢄)
INTERNAL_DOMAINS=parametacorp.com,iconloop.com

# ν”Όλ“œλ°± λ‹€μ΄μ œμŠ€νŠΈ λ°œμ†‘ 채널 (Slack 채널 ID λ˜λŠ” κ΄€λ¦¬μž μ‚¬μš©μž ID)
FEEDBACK_CHANNEL=C0123456789

# Trello μ£Όκ°„ λ³΄κ³ μ„œ μ„€μ • (선택)
# - TRELLO_WORKSPACE: λŒ€μƒ μ›Œν¬μŠ€νŽ˜μ΄μŠ€ 이름/displayName (κΈ°λ³Έ CorpDev_BS)
# - TRELLO_REPORT_CHANNEL: λ³΄κ³ μ„œ λ°œμ†‘ Slack 채널 (λ―Έμ„€μ • μ‹œ FEEDBACK_CHANNEL μ‚¬μš©)
# - TRELLO_REPORT_USER_ID: DriveΒ·Trello 토큰을 μ‚¬μš©ν•  Slack user_id (λ―Έμ„€μ • μ‹œ μžλ™ 선택)
# - TRELLO_REPORT_FOLDER_NAME: Drive μ €μž₯ 폴더λͺ… (κΈ°λ³Έ "Trello μ£Όκ°„ λ³΄κ³ μ„œ")
TRELLO_WORKSPACE=CorpDev_BS
TRELLO_REPORT_CHANNEL=C0123456789

# ParaScope 연동 (선택)
PARASCOPE_BOT_ID=...
PARASCOPE_BOT_APP_ID=...
PARASCOPE_CHANNEL_ID=...

3. μ„œλ²„ μ‹€ν–‰

bash start.sh

start.shλŠ” κΈ°μ‘΄ ν”„λ‘œμ„ΈμŠ€λ₯Ό μ’…λ£Œν•˜κ³  단일 μΈμŠ€ν„΄μŠ€λ‘œ μ‹€ν–‰ν•©λ‹ˆλ‹€.

4. Slackμ—μ„œ 등둝

Google 계정 연동 (ν•„μˆ˜)

/등둝

Google OAuth 인증 ν›„ Drive 폴더 μžλ™ 생성. λΈŒλ¦¬ν•‘Β·λ―ΈνŒ… μƒμ„±Β·νšŒμ˜λ‘ λ“± 핡심 κΈ°λŠ₯에 ν•„μš”ν•©λ‹ˆλ‹€.

Trello 연동 (선택 β€” νŒŒμ΄ν”„λΌμΈ 관리 μ‹œ ν•„μš”)

/trello

Slack DM으둜 μ „μ†‘λ˜λŠ” 인증 링크λ₯Ό ν΄λ¦­ν•˜μ—¬ Trello 계정을 μ—°κ²°ν•©λ‹ˆλ‹€. 연동 μ‹œ λΈŒλ¦¬ν•‘μ— 업체별 Trello μΉ΄λ“œ μ»¨ν…μŠ€νŠΈκ°€ ν¬ν•¨λ˜κ³ , 회의둝 μ™„λ£Œ ν›„ μ•‘μ…˜μ•„μ΄ν…œμ„ Trello에 등둝할 수 μžˆμŠ΅λ‹ˆλ‹€.

λ“œλ¦Όν”ŒλŸ¬μŠ€ 계정 등둝 (선택 β€” νšŒμ˜μ‹€ μ˜ˆμ•½ μ‹œ ν•„μš”)

/λ“œλ¦Όν”ŒλŸ¬μŠ€

λ“œλ¦Όν”ŒλŸ¬μŠ€ νšŒμ˜μ‹€ μ˜ˆμ•½Β·μ‘°νšŒΒ·μ·¨μ†Œ 및 ν¬λ ˆλ”§ 관리 κΈ°λŠ₯을 μ‚¬μš©ν•˜λ €λ©΄ λ“œλ¦Όν”ŒλŸ¬μŠ€ 계정 정보λ₯Ό 등둝해야 ν•©λ‹ˆλ‹€.


ν‚€ 및 토큰 λ°œκΈ‰ κ°€μ΄λ“œ

Slack Bot Token & App Token

  1. api.slack.com/apps 접속 β†’ Create New App β†’ From scratch
  2. App Name μž…λ ₯, μ›Œν¬μŠ€νŽ˜μ΄μŠ€ 선택 ν›„ 생성

Bot Token (SLACK_BOT_TOKEN)

  1. 쒌츑 메뉴 OAuth & Permissions 이동
  2. Bot Token Scopes μ—μ„œ μ•„λž˜ κΆŒν•œ μΆ”κ°€:
 app_mentions:read
 channels:history
 chat:write
 commands
 files:read
 groups:history
 im:history
 im:read
 im:write
 users:read
  1. Install to Workspace β†’ μ„€μΉ˜ μ™„λ£Œ ν›„ Bot User OAuth Token 볡사 β†’ SLACK_BOT_TOKEN

App Token (SLACK_APP_TOKEN)

  1. 쒌츑 메뉴 Basic Information β†’ App-Level Tokens β†’ Generate Token
  2. Token Name μž…λ ₯, Scope에 connections:write μΆ”κ°€ β†’ 생성
  3. μƒμ„±λœ xapp-... 토큰 볡사 β†’ SLACK_APP_TOKEN

Socket Mode ν™œμ„±ν™”

  1. 쒌츑 메뉴 Socket Mode β†’ Enable Socket Mode 켜기

Event Subscriptions μ„€μ •

  1. 쒌츑 메뉴 Event Subscriptions β†’ Enable Events 켜기
  2. Subscribe to bot events 에 μΆ”κ°€: app_mention, message.im

Interactivity μ„€μ •

  1. 쒌츑 메뉴 Interactivity & Shortcuts β†’ Interactivity 켜기

Socket Modeμ—μ„œλŠ” Event/Interactivity의 Request URL μž…λ ₯이 λΆˆν•„μš”ν•©λ‹ˆλ‹€.

Slash Commands 등둝

  1. 쒌츑 메뉴 Slash Commands β†’ Create New Command 둜 μ•„λž˜ μŠ¬λž˜μ‹œ μ»€λ§¨λ“œ μ„Ήμ…˜μ˜ μ»€λ§¨λ“œλ₯Ό λͺ¨λ‘ 등둝

ngrok β€” 개발용 Public URL

Google OAuth μ½œλ°±μ„ λ‘œμ»¬μ—μ„œ λ°›μœΌλ €λ©΄ μ™ΈλΆ€μ—μ„œ μ ‘κ·Ό κ°€λŠ₯ν•œ URL이 ν•„μš”ν•©λ‹ˆλ‹€.

# ngrok μ„€μΉ˜ (macOS)
brew install ngrok

# 인증 (https://ngrok.com μ—μ„œ 토큰 λ°œκΈ‰)
ngrok config add-authtoken <your-authtoken>

# 포트 8000 ν¬μ›Œλ”© (OAuth μ„œλ²„ κΈ°λ³Έ 포트)
ngrok http 8000

ngrok μ‹€ν–‰ ν›„ 좜λ ₯λ˜λŠ” https://xxxx-xxx.ngrok-free.app μ£Όμ†Œλ₯Ό .env에 μ„€μ •ν•©λ‹ˆλ‹€:

OAUTH_CALLBACK_URL=https://xxxx-xxx.ngrok-free.app/oauth/callback

무료 ν”Œλžœμ€ μ„Έμ…˜ μ’…λ£Œ μ‹œ URL이 λ³€κ²½λ©λ‹ˆλ‹€. μž¬μ‹€ν–‰ ν›„ .env와 Google Cloud Console의 λ¦¬λ‹€μ΄λ ‰νŠΈ URIλ₯Ό ν•¨κ»˜ μ—…λ°μ΄νŠΈν•΄μ•Ό ν•©λ‹ˆλ‹€.


라이브 μ„œλ²„ 배포

개발 ν™˜κ²½(ngrok)이 μ•„λ‹Œ μƒμ‹œ 운영 μ„œλ²„μ— λ°°ν¬ν•˜λŠ” λ°©λ²•μž…λ‹ˆλ‹€.

μ „μ œ 쑰건

  • Ubuntu VPS (Python 3.10+)
  • 도메인 + Cloudflare ν”„λ‘μ‹œ μ„€μ • μ™„λ£Œ

포트 μš”κ΅¬μ‚¬ν•­

Socket ModeλŠ” μ•„μ›ƒλ°”μš΄λ“œ WebSocket만 μ‚¬μš©ν•˜λ―€λ‘œ Slack ν†΅μ‹ μ—λŠ” μΈλ°”μš΄λ“œ ν¬νŠΈκ°€ ν•„μš” μ—†μŠ΅λ‹ˆλ‹€. Google OAuth 콜백용 FastAPI μ„œλ²„(8000 포트)만 μ™ΈλΆ€ 접근이 ν•„μš”ν•˜λ©°, Cloudflare Origin Rules둜 μ²˜λ¦¬ν•©λ‹ˆλ‹€.

개발용 vs 라이브용 Slack μ•±

라이브 μ„œλ²„μš© Slack 앱을 λ³„λ„λ‘œ 생성해야 ν•©λ‹ˆλ‹€. Socket ModeλŠ” ν•˜λ‚˜μ˜ μ•± ν† ν°μœΌλ‘œ ν•˜λ‚˜μ˜ μ—°κ²°λ§Œ μœ μ§€ν•˜λ―€λ‘œ, 동일 앱을 둜컬과 μ„œλ²„μ—μ„œ λ™μ‹œμ— μ‹€ν–‰ν•˜λ©΄ μ΄λ²€νŠΈκ°€ 랜덀으둜 λΆ„λ°°λ©λ‹ˆλ‹€. Slack ν† ν°λ§Œ λΆ„λ¦¬ν•˜κ³  Google/Trello/LLM ν‚€λŠ” λ™μΌν•˜κ²Œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ›Œν¬μŠ€νŽ˜μ΄μŠ€κ°€ λ‹€λ₯΄λ©΄ μ•± μ΄λ¦„Β·μŠ¬λž˜μ‹œ μ»€λ§¨λ“œ λͺ¨λ‘ 동일해도 좩돌 μ—†μŠ΅λ‹ˆλ‹€.

1. μ„œλ²„ ν™˜κ²½ μ„€μ •

# μ‹œμŠ€ν…œ νŒ¨ν‚€μ§€ μ„€μΉ˜
sudo apt update
sudo apt install python3.11 python3.11-venv python3.11-dev libffi-dev build-essential -y

# μ½”λ“œ 배포
git clone <repo-url> ~/workspace/meeting-agent
cd ~/workspace/meeting-agent

# venv 생성 및 μ˜μ‘΄μ„± μ„€μΉ˜
python3.11 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

libffi-dev, python3.11-dev, build-essential은 cffi/cryptography λ„€μ΄ν‹°λΈŒ λΉŒλ“œμ— ν•„μš”ν•©λ‹ˆλ‹€.

2. Slack μ•± 생성 (라이브용)

api.slack.com/apps β†’ Create New App β†’ From scratch 으둜 라이브 μ „μš© 앱을 μƒμ„±ν•©λ‹ˆλ‹€.

μ„€μ • ν•­λͺ©:

  1. Socket Mode β†’ Enable Socket Mode β†’ 토큰 생성 (xapp-...) β†’ SLACK_APP_TOKEN

  2. OAuth & Permissions β†’ Bot Token Scopes μΆ”κ°€ ν›„ Install β†’ SLACK_BOT_TOKEN

    app_mentions:read, channels:history, chat:write, commands,
    files:read, files:write, groups:history, im:history, im:read,
    im:write, users:read, users:read.email, users.profile:read
    
  3. Event Subscriptions β†’ Enable Events β†’ Subscribe to bot events: app_mention, message.im

  4. Interactivity & Shortcuts β†’ Interactivity 켜기

  5. Slash Commands β†’ μŠ¬λž˜μ‹œ μ»€λ§¨λ“œ μ„Ήμ…˜μ˜ μ»€λ§¨λ“œλ₯Ό λͺ¨λ‘ 등둝 (Socket Modeμ—μ„œλŠ” Request URL λΆˆν•„μš”)

3. ν™˜κ²½ λ³€μˆ˜ μ„€μ •

λΉ λ₯Έ μ‹œμž‘ > ν™˜κ²½ λ³€μˆ˜ μ„€μ •κ³Ό λ™μΌν•œ .env νŒŒμΌμ„ μƒμ„±ν•˜λ˜, μ•„λž˜ ν•­λͺ©μ„ 라이브 ν™˜κ²½μ— 맞게 λ³€κ²½ν•©λ‹ˆλ‹€:

# 라이브용 Slack μ•± ν† ν°μœΌλ‘œ ꡐ체
SLACK_BOT_TOKEN=xoxb-...
SLACK_APP_TOKEN=xapp-...

# 라이브 λ„λ©”μΈμœΌλ‘œ λ³€κ²½
OAUTH_CALLBACK_URL=https://meeting.yourdomain.com/oauth/callback

# Trello 연동 μ‹œ μΆ”κ°€
TRELLO_API_KEY=...
TRELLO_BOARD_ID=...

# Trello μ£Όκ°„ λ³΄κ³ μ„œ (선택 β€” λ―Έμ„€μ • μ‹œ FEEDBACK_CHANNEL·첫 토큰 보유자둜 폴백)
TRELLO_WORKSPACE=CorpDev_BS
TRELLO_REPORT_CHANNEL=C0123456789
TRELLO_REPORT_USER_ID=U0123456789

4. Google Cloud Console μ„€μ •

개발용과 λ™μΌν•œ Google Cloud ν”„λ‘œμ νŠΈλ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.

console.cloud.google.com β†’ APIs & Services β†’ Credentials β†’ OAuth 2.0 Client β†’ Authorized redirect URIs 에 라이브 콜백 URL μΆ”κ°€:

https://meeting.yourdomain.com/oauth/callback

개발용(ngrok) URIλ₯Ό ν•¨κ»˜ 등둝해두면 ν•˜λ‚˜μ˜ Google ν”„λ‘œμ νŠΈλ‘œ 개발/라이브 λͺ¨λ‘ μ‚¬μš© κ°€λŠ₯ν•©λ‹ˆλ‹€.

5. Cloudflare μ„€μ •

Cloudflareκ°€ HTTPSλ₯Ό μ²˜λ¦¬ν•˜λ―€λ‘œ μ„œλ²„μ— Nginxλ‚˜ SSL μΈμ¦μ„œκ°€ λΆˆν•„μš”ν•©λ‹ˆλ‹€.

  1. DNS: A λ ˆμ½”λ“œλ‘œ meeting.yourdomain.com β†’ μ„œλ²„ IP, ν”„λ‘μ‹œ ν™œμ„±ν™” (주황색 ꡬ름)
  2. Origin Rules: Cloudflare λŒ€μ‹œλ³΄λ“œ β†’ Rules β†’ Origin Rules β†’ Create Rule
    • 쑰건: Hostname equals meeting.yourdomain.com
    • μ•‘μ…˜: Destination Port β†’ 8000
  3. λ°©ν™”λ²½: μ„œλ²„μ—μ„œ 8000 포트λ₯Ό Cloudflare IP λŒ€μ—­μ—λ§Œ μ˜€ν”ˆ

6. systemd μ„œλΉ„μŠ€ 등둝

sudo tee /etc/systemd/system/meeting-agent.service <<'EOF'
[Unit]
Description=Meeting Agent Slack Bot
After=network.target

[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/workspace/meeting-agent
EnvironmentFile=/home/ubuntu/workspace/meeting-agent/.env
ExecStart=/home/ubuntu/workspace/meeting-agent/.venv/bin/python3.11 main.py
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable meeting-agent
sudo systemctl start meeting-agent

μ„œλΉ„μŠ€ 관리:

sudo systemctl status meeting-agent     # μƒνƒœ 확인
sudo journalctl -u meeting-agent -f     # 둜그 확인
sudo systemctl restart meeting-agent    # μž¬μ‹œμž‘

7. 배포 μ—…λ°μ΄νŠΈ

cd ~/workspace/meeting-agent
git pull
sudo systemctl restart meeting-agent

main λΈŒλžœμΉ˜μ— ν‘Έμ‹œν•˜λ©΄ GitHub Actionsκ°€ μžλ™μœΌλ‘œ λ°°ν¬ν•˜λ©°, 배포 μ™„λ£Œ μ‹œ FEEDBACK_CHANNEL에 버전·변경사항 μ•Œλ¦Όμ΄ λ°œμ†‘λ©λ‹ˆλ‹€.

8. 데이터 λ°±μ—… (선택)

SQLite DBλ₯Ό 주기적으둜 λ°±μ—…ν•©λ‹ˆλ‹€:

# crontab -e 에 μΆ”κ°€
0 3 * * * cp /home/ubuntu/workspace/meeting-agent/store/users.db /home/ubuntu/backups/users_$(date +\%Y\%m\%d).db

Google API Key (GOOGLE_API_KEY)

Gemini LLM 호좜용 ν‚€μž…λ‹ˆλ‹€.

  1. Google AI Studio 접속
  2. Create API key 클릭 β†’ ν”„λ‘œμ νŠΈ 선택 λ˜λŠ” μ‹ κ·œ 생성
  3. μƒμ„±λœ ν‚€ 볡사 β†’ GOOGLE_API_KEY

Google OAuth ν΄λΌμ΄μ–ΈνŠΈ μ„€μ •

Calendar / Drive / Gmail / Docs / Meet API 연동에 μ‚¬μš©λ˜λŠ” OAuth 2.0 자격 증λͺ…μž…λ‹ˆλ‹€.

  1. Google Cloud Console 접속 β†’ ν”„λ‘œμ νŠΈ 선택/생성
  2. APIs & Services β†’ Library μ—μ„œ μ•„λž˜ API ν™œμ„±ν™”:
  • Google Calendar API
  • Google Drive API
  • Gmail API
  • Google Docs API
  • Google Meet API (Google Workspace Meeting API)
  • People API
  1. APIs & Services β†’ OAuth consent screen μ„€μ •:
  • User Type: Internal (쑰직 λ‚΄λΆ€μš©) λ˜λŠ” External
  • μ•± 이름, 지원 이메일 μž…λ ₯
  1. APIs & Services β†’ Credentials β†’ Create Credentials β†’ OAuth client ID:
  • Application type: Web application
  • Authorized redirect URIs에 OAUTH_CALLBACK_URL κ°’ μΆ”κ°€
  1. μƒμ„±λœ Client ID Β· Client Secret β†’ server/oauth.py의 GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET ν™˜κ²½λ³€μˆ˜λ‘œ μ„€μ •
GOOGLE_CLIENT_ID=...apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-...

Fernet μ•”ν˜Έν™” ν‚€ (ENCRYPTION_KEY)

μ‚¬μš©μž Google OAuth 토큰을 SQLite에 μ €μž₯ν•  λ•Œ μ•”ν˜Έν™”μ— μ‚¬μš©λ©λ‹ˆλ‹€.

python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"

좜λ ₯된 값을 .env에 μ„€μ •ν•©λ‹ˆλ‹€:

ENCRYPTION_KEY=abc123...==

이 ν‚€λ₯Ό λΆ„μ‹€ν•˜λ©΄ μ €μž₯된 λͺ¨λ“  μ‚¬μš©μž 토큰을 λ³΅ν˜Έν™”ν•  수 μ—†μŠ΅λ‹ˆλ‹€. μ•ˆμ „ν•œ 곳에 λ°±μ—…ν•˜μ„Έμš”.


Deepgram API Key (DEEPGRAM_API_KEY)

μŒμ„± 파일 STT(Speech-to-Text) λ³€ν™˜μ— μ‚¬μš©λ©λ‹ˆλ‹€.

  1. console.deepgram.com 접속 β†’ νšŒμ›κ°€μž… λ˜λŠ” 둜그인
  2. 쒌츑 메뉴 API Keys β†’ Create a New API Key
  3. Key Name μž…λ ₯, Permissions: Member 선택 β†’ 생성
  4. μƒμ„±λœ ν‚€ 볡사 β†’ DEEPGRAM_API_KEY

μ‚¬μš© λͺ¨λΈ: nova-2 (ν•œκ΅­μ–΄ 지원, smart_format, punctuate μ˜΅μ…˜ ν™œμ„±ν™”)

지원 포맷: MP3, MP4, M4A, WAV, OGG, WebM, AAC λ“± (μ΅œλŒ€ 500MB)

사내 λ°©ν™”λ²½ ν™˜κ²½μ—μ„œ SSL μΈμ¦μ„œ 였λ₯˜ λ°œμƒ μ‹œ tools/stt.py의 verify=False μ„€μ •μœΌλ‘œ μš°νšŒν•©λ‹ˆλ‹€.


μŠ¬λž˜μ‹œ μ»€λ§¨λ“œ

μ»€λ§¨λ“œ μ„€λͺ…
/등둝 / /register Google 계정 연동
/μž¬λ“±λ‘ / /reregister Google 계정 재인증 (μŠ€μ½”ν”„ λ³€κ²½ μ‹œ ν™œμš©)
/λΈŒλ¦¬ν•‘ / /brief 였늘 λ―ΈνŒ… λΈŒλ¦¬ν•‘ μˆ˜λ™ μ‹€ν–‰
/λ―ΈνŒ…μΆ”κ°€ / /meet μžμ—°μ–΄λ‘œ λ―ΈνŒ… 생성
/κΈ°μ—… / /company κΈ°μ—… 정보 κ°•μ œ λ¦¬μ„œμΉ˜
/인물 / /person 인물 정보 κ°•μ œ λ¦¬μ„œμΉ˜
/λ―ΈνŒ…μ‹œμž‘ μˆ˜λ™ λ…ΈνŠΈ μ„Έμ…˜ μ‹œμž‘ (후보 일정 있으면 선택 UI + μƒˆ λ―ΈνŒ… μΆ”κ°€ λ²„νŠΌ)
/λ©”λͺ¨ λ―ΈνŒ… 쀑 λ…ΈνŠΈ μΆ”κ°€ (μ„Έμ…˜ μ—†μœΌλ©΄ μžλ™ μ‹œμž‘)
/λ―ΈνŒ…μ’…λ£Œ μ„Έμ…˜ μ’…λ£Œ + 회의둝 μ¦‰μ‹œ 생성 + κ²€ν†  단계
/νšŒμ˜λ‘μž‘μ„± 회의둝 μˆ˜λ™ 생성
/회의둝 μ €μž₯된 회의둝 λͺ©λ‘ 쑰회 (검색어 지원: /회의둝 카카였, /회의둝 2026-04)
/μ—…λ°μ΄νŠΈ / /update company_knowledge.md κ°±μ‹ 
/λ“œλ¦Όν”ŒλŸ¬μŠ€ / /dreamplus λ“œλ¦Όν”ŒλŸ¬μŠ€ 계정 등둝/λ³€κ²½
/νšŒμ˜μ‹€μ˜ˆμ•½ λ“œλ¦Όν”ŒλŸ¬μŠ€ νšŒμ˜μ‹€ μ˜ˆμ•½
/νšŒμ˜μ‹€μ‘°νšŒ νšŒμ˜μ‹€ μ˜ˆμ•½ 쑰회
/νšŒμ˜μ‹€μ·¨μ†Œ νšŒμ˜μ‹€ μ˜ˆμ•½ μ·¨μ†Œ
/ν¬λ ˆλ”§μ‘°νšŒ λ“œλ¦Όν”ŒλŸ¬μŠ€ ν¬λ ˆλ”§ 쑰회
/trello Trello 계정 μ—°κ²°
/trello-disconnect Trello μ—°κ²° ν•΄μ œ
/트렐둜쑰회 / /trello-search Trello μΉ΄λ“œ 검색
/νŠΈλ λ‘œμ£Όκ°„λ³΄κ³  / /trello-weekly Trello μ£Όκ°„ λ³΄κ³ μ„œ 생성 (인자: 일수, κΈ°λ³Έ 7)
/도움말 / /help μ‚¬μš© κ°€λŠ₯ν•œ μ»€λ§¨λ“œ 및 μžμ—°μ–΄ λͺ…λ Ήμ–΄ μ•ˆλ‚΄

μžμ—°μ–΄ DM도 μ§€μ›ν•©λ‹ˆλ‹€ (λΈŒλ¦¬ν•‘ ν•΄μ€˜, 내일 3μ‹œ KISA λ―ΈνŒ… μž‘μ•„μ€˜, μ§€λ‚œ λͺ©μš”일 회의둝, 카카였 λ©”λͺ¨ β€” PoC μ˜ˆμ‚° 확보, μ£Όκ°„λ³΄κ³ μ„œ, μ§€λ‚œ 2μ£Ό 트렐둜 λ³΄κ³ μ„œ, ~κΈ°λŠ₯ μΆ”κ°€ν•΄μ€˜, ~버그 κ°™μ•„ λ“±).


λΈŒλ¦¬ν•‘ λ™μž‘ 방식

μ™ΈλΆ€ λ―ΈνŒ… λΈŒλ¦¬ν•‘μ€ 2단계 비동기 λ°©μ‹μœΌλ‘œ λ™μž‘ν•©λ‹ˆλ‹€. λ¦¬μ„œμΉ˜ λŒ€κΈ° 없이 λ―ΈνŒ… 정보λ₯Ό μ¦‰μ‹œ μˆ˜μ‹ ν•˜κ³ , λ¦¬μ„œμΉ˜ κ²°κ³ΌλŠ” μ™„λ£Œλ˜λŠ” μˆœμ„œλŒ€λ‘œ μŠ€λ ˆλ“œμ— μΆ”κ°€λ©λ‹ˆλ‹€.

1단계 (μ¦‰μ‹œ)     λ―ΈνŒ… 헀더 λ°œμ†‘
                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                  β”‚ πŸ“‹ 업체λͺ… β€” μ˜€ν›„ 3:00 (Google Meet) β”‚
                  β”‚ [μ–΄μ  λ‹€ λ‚΄μš© λ˜λŠ” μŠ€λ ˆλ“œ λ‹΅κΈ€ μ•ˆλ‚΄]   β”‚
                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

2단계 (λ°±κ·ΈλΌμš΄λ“œ, 업체별 순차)
  β†’ 업체 λ¦¬μ„œμΉ˜ μ™„λ£Œ  🏒 업체λͺ… λ¦¬μ„œμΉ˜ κ²°κ³Ό (ParaScope / 업체 동ν–₯ / μ„œλΉ„μŠ€ 연결점)
  β†’ λ‹΄λ‹Ήμž μ™„λ£Œ       πŸ‘€ λ‹΄λ‹Ήμž 정보
  β†’ λ§₯락 쑰회 μ™„λ£Œ    πŸ“Œ 이전 λ―ΈνŒ… λ§₯락 + πŸ“§ 이메일 λ§₯락

닀쀑 업체 λΈŒλ¦¬ν•‘ μ‹œμ—λ„ 단일 μŠ€λ ˆλ“œμ—μ„œ 순차 μ²˜λ¦¬ν•˜λ―€λ‘œ 두 μ—…μ²΄μ˜ κ²°κ³Όκ°€ μ„žμ΄μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.


ν”„λ‘¬ν”„νŠΈ ν…œν”Œλ¦Ώ μ»€μŠ€ν„°λ§ˆμ΄μ§•

LLM에 μ „λ‹¬λ˜λŠ” μ£Όμš” ν”„λ‘¬ν”„νŠΈλŠ” prompts/templates/ ν΄λ”μ˜ λ§ˆν¬λ‹€μš΄ 파일둜 κ΄€λ¦¬λ©λ‹ˆλ‹€. νŒŒμΌμ„ μˆ˜μ •ν•œ λ’€ μ„œλ²„λ₯Ό μž¬μ‹€ν–‰ν•˜λ©΄ λ³€κ²½ λ‚΄μš©μ΄ μ¦‰μ‹œ λ°˜μ˜λ©λ‹ˆλ‹€ (μ½”λ“œ μˆ˜μ • λΆˆν•„μš”).

prompts/templates/
β”œβ”€β”€ minutes_internal.md     # λ‚΄λΆ€μš© 회의둝 생성 ν”„λ‘¬ν”„νŠΈ
β”œβ”€β”€ minutes_external.md     # μ™ΈλΆ€μš© 회의둝 생성 ν”„λ‘¬ν”„νŠΈ
β”œβ”€β”€ company_news.md         # 업체 졜근 동ν–₯ 검색 ν”„λ‘¬ν”„νŠΈ
β”œβ”€β”€ person_info.md          # 인물 정보 검색 ν”„λ‘¬ν”„νŠΈ
└── service_connection.md   # μ„œλΉ„μŠ€ 연결점 뢄석 ν”„λ‘¬ν”„νŠΈ

ν…œν”Œλ¦Ώ λ‚΄ λ³€μˆ˜λŠ” {{λ³€μˆ˜λͺ…}} ν˜•μ‹μœΌλ‘œ μž‘μ„±ν•©λ‹ˆλ‹€:

ν…œν”Œλ¦Ώ 파일 μ‚¬μš© λ³€μˆ˜
minutes_internal.md {{title}}, {{date}}, {{attendees}}, {{sources}}
minutes_external.md {{title}}, {{date}}, {{attendees}}, {{internal_minutes}}
company_news.md {{today}}, {{company_name}}
person_info.md {{person_name}}, {{company_name}}
service_connection.md {{knowledge}}, {{company_info}}

인라인으둜 κ΄€λ¦¬λ˜λŠ” ν”„λ‘¬ν”„νŠΈ(λ―ΈνŒ… νŒŒμ‹±, μΈν…νŠΈ λΆ„λ₯˜, μ•‘μ…˜μ•„μ΄ν…œ μΆ”μΆœ λ“±)λŠ” prompts/briefing.pyμ—μ„œ 직접 μˆ˜μ •ν•©λ‹ˆλ‹€.


Drive 폴더 ꡬ쑰

MeetingAgent/
β”œβ”€β”€ Contacts/
β”‚   β”œβ”€β”€ Companies/          # {업체λͺ…}.md (λ¦¬μ„œμΉ˜ κ²°κ³Ό + λ‚΄λΆ€ λ©”λͺ¨)
β”‚   └── People/             # {이름}.md
β”œβ”€β”€ Minutes/                # {λ‚ μ§œ}_{제λͺ©}_λ‚΄λΆ€μš©.md / _μ™ΈλΆ€μš©.md
β”œβ”€β”€ Sources/                # 원본 데이터 보관
β”‚   └── Research/           # {λ‚ μ§œ}_{업체λͺ…}_web_search.md
└── company_knowledge.md    # μžμ‚¬ μ„œλΉ„μŠ€ μš”μ•½

ν”„λ‘œμ νŠΈ ꡬ쑰

meeting-agent/
β”œβ”€β”€ main.py                 # Slack Bolt + APScheduler μ§„μž…μ 
β”œβ”€β”€ start.sh                # 단일 μΈμŠ€ν„΄μŠ€ μ‹€ν–‰ 슀크립트 (개발용)
β”œβ”€β”€ .github/
β”‚   └── workflows/
β”‚       └── deploy.yml      # GitHub Actions μžλ™ 배포 (μ›Ήν›… 방식)
β”œβ”€β”€ agents/
β”‚   β”œβ”€β”€ before.py           # Before μ—μ΄μ „νŠΈ (λΈŒλ¦¬ν•‘, λ¦¬μ„œμΉ˜, λ―ΈνŒ… 생성)
β”‚   β”œβ”€β”€ during.py           # During μ—μ΄μ „νŠΈ (트랜슀크립트, λ…ΈνŠΈ, μŒμ„±STT, λ¬Έμ„œμ—…λ‘œλ“œ, 회의둝)
β”‚   β”œβ”€β”€ after.py            # After μ—μ΄μ „νŠΈ (회의둝 λ°œμ†‘, μ•‘μ…˜μ•„μ΄ν…œ, Trello 등둝)
β”‚   β”œβ”€β”€ proposal.py         # μ œμ•ˆμ„œ μ—μ΄μ „νŠΈ (κ°œμš”Β·μ΄ˆμ•ˆ 생성, μŠ€λ ˆλ“œ μˆ˜μ •)
β”‚   β”œβ”€β”€ card.py             # λͺ…함 OCR μ—μ΄μ „νŠΈ
β”‚   β”œβ”€β”€ room.py             # λ“œλ¦Όν”ŒλŸ¬μŠ€ νšŒμ˜μ‹€ μ˜ˆμ•½Β·μ‘°νšŒΒ·μ·¨μ†Œ (Slack Modal)
β”‚   β”œβ”€β”€ dreamplus.py        # λ“œλ¦Όν”ŒλŸ¬μŠ€ API 래퍼 (JWT 인증)
β”‚   β”œβ”€β”€ feedback.py         # ν”Όλ“œλ°± μˆ˜μ§‘Β·λΆ„λ₯˜Β·λ‹€μ΄μ œμŠ€νŠΈ μ—μ΄μ „νŠΈ
β”‚   └── trello_report.py    # Trello μ£Όκ°„ λ³΄κ³ μ„œ (Google Docs + Slack μš”μ•½)
β”œβ”€β”€ tools/
β”‚   β”œβ”€β”€ calendar.py         # Google Calendar API
β”‚   β”œβ”€β”€ docs.py             # Google Docs API (트랜슀크립트 읽기)
β”‚   β”œβ”€β”€ drive.py            # Google Drive API
β”‚   β”œβ”€β”€ gmail.py            # Gmail API
β”‚   β”œβ”€β”€ stt.py              # Deepgram STT API
β”‚   β”œβ”€β”€ slack_tools.py      # Slack Block Kit λ©”μ‹œμ§€ λΉŒλ”
β”‚   β”œβ”€β”€ trello.py           # Trello REST API 래퍼
β”‚   β”œβ”€β”€ dreamplus.py        # λ“œλ¦Όν”ŒλŸ¬μŠ€ API ν΄λΌμ΄μ–ΈνŠΈ
β”‚   └── text_extract.py     # ν…μŠ€νŠΈ μΆ”μΆœ μœ ν‹Έλ¦¬ν‹°
β”œβ”€β”€ prompts/
β”‚   β”œβ”€β”€ briefing.py         # LLM ν”„λ‘¬ν”„νŠΈ ν•¨μˆ˜ (ν…œν”Œλ¦Ώ λ‘œλ” 포함)
β”‚   └── templates/          # μ™ΈλΆ€ ν”„λ‘¬ν”„νŠΈ ν…œν”Œλ¦Ώ (μ„œλ²„ μž¬μ‹€ν–‰μœΌλ‘œ 반영)
β”‚       β”œβ”€β”€ minutes_internal.md
β”‚       β”œβ”€β”€ minutes_external.md
β”‚       β”œβ”€β”€ briefing_summary.md
β”‚       β”œβ”€β”€ company_news.md
β”‚       β”œβ”€β”€ person_info.md
β”‚       β”œβ”€β”€ service_connection.md
β”‚       β”œβ”€β”€ proposal_intake.md
β”‚       └── proposal_generate.md
β”œβ”€β”€ store/
β”‚   └── user_store.py       # SQLite + Fernet μ‚¬μš©μž 토큰 관리
β”œβ”€β”€ server/
β”‚   └── oauth.py            # FastAPI (OAuth 콜백 + Trello 인증 + 배포 μ›Ήν›…)
β”œβ”€β”€ tests/                  # λ‹¨μœ„ ν…ŒμŠ€νŠΈ
β”œβ”€β”€ requirements.txt
└── docs/                   # 섀계 λ¬Έμ„œ

λ¬Έμ„œ

λ¬Έμ„œ λ‚΄μš©
μš”κ΅¬μ‚¬ν•­ 전체 μ‹œμŠ€ν…œ μš”κ΅¬μ‚¬ν•­ 및 κ΅¬ν˜„ ν˜„ν™©
Before Agent 섀계 λΈŒλ¦¬ν•‘, λ¦¬μ„œμΉ˜, λ―ΈνŒ… 생성 상세 섀계
During Agent 섀계 트랜슀크립트 μˆ˜μ§‘, μˆ˜λ™ λ…ΈνŠΈ μ„Έμ…˜ 섀계
After Agent 섀계 회의둝 λ°œμ†‘, μ•‘μ…˜μ•„μ΄ν…œ, Contacts κ°±μ‹  섀계
LLM μ‚¬μš© ν˜„ν™© LLM 호좜 ν•¨μˆ˜Β·ν”„λ‘¬ν”„νŠΈ λͺ©λ‘
ν…ŒμŠ€νŠΈ κ°€μ΄λ“œ ν…ŒμŠ€νŠΈ μ‹€ν–‰ 방법 및 ꡬ성

ν…ŒμŠ€νŠΈ

pytest tests/
pytest tests/ -v             # 상세 좜λ ₯
pytest tests/test_before.py  # νŠΉμ • 파일만

Google OAuth κΆŒν•œ λ²”μœ„

Scope μš©λ„
calendar λ―ΈνŒ… μ‘°νšŒΒ·μƒμ„±Β·μ„€λͺ… μ—…λ°μ΄νŠΈΒ·extendedProperties 패치
drive Contacts·회의둝·company_knowledge.md 읽기/μ“°κΈ°
gmail.readonly 이메일 λ§₯락 검색, 이메일 μ£Όμ†Œ μΆ”μΆœ
gmail.send μ™ΈλΆ€μš© 회의둝 이메일 λ°œμ†‘
documents.readonly Google Meet 트랜슀크립트 읽기
contacts.readonly Google μ£Όμ†Œλ‘ μ°Έμ„μž 이메일 쑰회 (μ‹ κ·œ λ“±λ‘μžλΆ€ν„° 적용, κΈ°μ‘΄ μ‚¬μš©μžλŠ” /μž¬λ“±λ‘ ν•„μš”)
meetings.space.created Google Meet νŠΈλžœμŠ€ν¬λ¦½μ…˜ μžλ™ ν™œμ„±ν™”

About

Parameta meeting assistant

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages