미팅 브리프 생성기
회사명과 선택적 연락처를 입력받습니다. Tavily를 통해 회사를 조사합니다. Gemini로 1페이지 분량의 미팅 사전 브리프를 작성합니다. 선택적으로 Notion에 저장할 수 있습니다.
중요 규칙: 구체적인 내용을 임의로 생성하지 마십시오. 브리프에 포함된 모든 사실, 수치, 주장은 반드시 Tavily 검색 결과에서 가져와야 합니다. 검색 데이터가 없는 섹션은 "공개 정보가 제한적으로 확인되었습니다."라고 표시하세요. 자금 조달 금액, 직원 수, 제품 세부 정보를 절대 허위로 작성하지 마십시오.
1단계: 설정 확인
필요한 환경 변수를 확인합니다:
echo "TAVILY_API_KEY: ${TAVILY_API_KEY:+set}"
echo "GEMINI_API_KEY: ${GEMINI_API_KEY:+set}"
echo "NOTION_TOKEN: ${NOTION_TOKEN:-not set}"
echo "NOTION_DATABASE_ID: ${NOTION_DATABASE_ID:-not set}"
TAVILY_API_KEY가 없는 경우: 중단합니다. 사용자에게 다음 메시지를 표시합니다: "TAVILY_API_KEY가 필요합니다. app.tavily.com에서 발급받아 .env 파일에 추가하세요."
GEMINI_API_KEY가 없는 경우: 중단합니다. 사용자에게 다음 메시지를 표시합니다: "GEMINI_API_KEY가 필요합니다. aistudio.google.com에서 발급받아 .env 파일에 추가하세요."
NOTION_TOKEN 또는 NOTION_DATABASE_ID가 없는 경우: 계속 진행합니다. 브리프는 텍스트로만 출력됩니다. Notion 저장은 생략됩니다.
입력값이 있는지 확인합니다. 사용자는 최소한 회사명을 제공해야 합니다. 제공되지 않은 경우 "어느 회사와 미팅을 진행하시나요?"라고 물어보십시오.
2단계: 컨텍스트 수집
다음 정보를 수집합니다. 누락된 정보만 물어보십시오.
필수:
- 회사명 (또는 도메인/URL이 제공된 경우)
- 미팅 날짜
선택 사항 (없어도 진행 가능):
- 연락처 이름 및 직함
- 미팅 유형 (디스커버리, 데모, 후속 미팅, QBR)
- 사용자가 다루고자 하는 특정 주제 또는 목표
사용자가 회사 URL이나 도메인을 제공한 경우, Tavily 검색을 더 정확하게 수행하기 위해 활용하십시오 (예: site:example.com 또는 검색어에 도메인 포함).
3단계: Tavily로 리서치
다음 검색을 순서대로 실행합니다. 각 검색은 브리프의 한 섹션을 대상으로 합니다. 각 검색의 상위 결과(제목, URL, 내용 조각, 점수)를 저장합니다.
점수가 0.5 이상인 결과만 유지합니다. 검색 결과가 0개인 경우 해당 섹션은 "공개 정보가 제한적으로 확인되었습니다."로 표시합니다.
검색 1: 회사 개요
curl -s -X POST "https://api.tavily.com/search" \
-H "Content-Type: application/json" \
-d '{
"api_key": "'"$TAVILY_API_KEY"'",
"query": "\"COMPANY\" overview founded employees headquarters",
"search_depth": "advanced",
"max_results": 5,
"include_answer": true
}'
검색 2: 최근 뉴스 (지난 30일)
curl -s -X POST "https://api.tavily.com/search" \
-H "Content-Type: application/json" \
-d '{
"api_key": "'"$TAVILY_API_KEY"'",
"query": "\"COMPANY\" news announcement",
"search_depth": "advanced",
"max_results": 5,
"include_answer": true,
"topic": "news",
"time_range": "month"
}'
검색 3: 기술 스택
curl -s -X POST "https://api.tavily.com/search" \
-H "Content-Type: application/json" \
-d '{
"api_key": "'"$TAVILY_API_KEY"'",
"query": "\"COMPANY\" technology stack engineering infrastructure tools",
"search_depth": "advanced",
"max_results": 5,
"include_answer": true
}'
검색 4: 제품 및 가격
curl -s -X POST "https://api.tavily.com/search" \
-H "Content-Type: application/json" \
-d '{
"api_key": "'"$TAVILY_API_KEY"'",
"query": "\"COMPANY\" product features pricing use case",
"search_depth": "advanced",
"max_results": 5,
"include_answer": true
}'
검색 5: 경쟁사
curl -s -X POST "https://api.tavily.com/search" \
-H "Content-Type: application/json" \
-d '{
"api_key": "'"$TAVILY_API_KEY"'",
"query": "\"COMPANY\" competitors alternatives vs",
"search_depth": "advanced",
"max_results": 5,
"include_answer": true
}'
검색 6: 자금 및 성장
curl -s -X POST "https://api.tavily.com/search" \
-H "Content-Type: application/json" \
-d '{
"api_key": "'"$TAVILY_API_KEY"'",
"query": "\"COMPANY\" funding raised valuation growth",
"search_depth": "advanced",
"max_results": 5,
"include_answer": true
}'
연락처 이름이 제공된 경우, 다음 두 가지 검색을 추가로 실행합니다:
검색 7: 연락처 프로필
curl -s -X POST "https://api.tavily.com/search" \
-H "Content-Type: application/json" \
-d '{
"api_key": "'"$TAVILY_API_KEY"'",
"query": "\"CONTACT_NAME\" \"COMPANY\" role title",
"search_depth": "advanced",
"max_results": 5,
"include_answer": true
}'
검색 8: 연락처 배경
curl -s -X POST "https://api.tavily.com/search" \
-H "Content-Type: application/json" \
-d '{
"api_key": "'"$TAVILY_API_KEY"'",
"query": "\"CONTACT_NAME\" background career LinkedIn",
"search_depth": "advanced",
"max_results": 5,
"include_answer": true
}'
4단계: Gemini로 합성
references/brief-format.md 파일 전체를 읽습니다. references/output-template.md 파일을 읽고 템플릿을 사용합니다.
Gemini 요청을 임시 파일에 작성합니다:
cat > /tmp/meeting-brief-request.json << 'ENDJSON'
{
"system_instruction": {
"parts": [{
"text": "당신은 영업 또는 비즈니스 개발 미팅을 위한 1페이지 분량의 사전 통화 브리프를 준비하는 GTM 리서치 분석가입니다. 규칙: 모든 주장은 제공된 리서치의 소스 URL을 인용해야 합니다. 발언 포인트는 '리서치 결과 [결과]에 따르면, [목표]를 위해 [포인트]를 언급하세요' 형식을 사용합니다. 허위 데이터는 금지됩니다. 특정 섹션에 리서치 데이터가 없는 경우 '공개 정보가 제한적으로 확인되었습니다.'라고 작성합니다. 줄표(--)는 사용하지 않습니다. 금지어는 사용하지 않습니다. 총 400단어 미만으로 작성합니다. 브리프는 3분 안에 훑어볼 수 있어야 합니다."
}]
},
"contents": [{
"parts": [{
"text": "RESEARCH_RESULTS_AND_INSTRUCTIONS_HERE"
}]
}],
"generationConfig": {
"temperature": 0.3,
"maxOutputTokens": 2500
}
}
ENDJSON
curl -s -X POST \
"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=$GEMINI_API_KEY" \
-H "Content-Type: application/json" \
-d @/tmp/meeting-brief-request.json \
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d['candidates'][0]['content']['parts'][0]['text'])"
RESEARCH_RESULTS_AND_INSTRUCTIONS_HERE를 다음으로 대체합니다:
- 모든 Tavily 검색 결과 (결과당 제목, URL, 내용 조각)
- output-template.md의 브리프 템플릿 구조
- 회사명, 연락처 이름(제공된 경우), 미팅 날짜, 미팅 유형(제공된 경우)
5단계: 자체 QA
제시하기 전에 다음 사항을 확인합니다:
- 허위 데이터 없음. 모든 사실은 Tavily 결과의 소스 URL이 있음
- 발언 포인트는 "[결과]에 따르면, [목표]를 위해 [포인트]를 언급하세요" 형식을 사용함
- 모든 줄에 줄표(--)가 없음
- 금지어 없음
- 브리프가 400단어 미만임
- 의사 결정권자 섹션에 연락처가 제공되지 않은 경우 "지정되지 않음"으로 표시됨
- 데이터가 없는 섹션은 추측 대신 "공개 정보가 제한적으로 확인되었습니다."라고 표시됨
- 개방형 질문은 일반적인 질문이 아닌 해당 회사에 특화됨
위반 사항이 발견되면 제시하기 전에 수정합니다.
6단계: 출력 또는 Notion에 저장
전체 브리프를 코드 블록 안에 표시합니다.
NOTION_TOKEN과 NOTION_DATABASE_ID가 모두 설정된 경우, "이 브리프를 Notion에 저장할까요?"라고 묻습니다.
확인 시:
cat > /tmp/notion-brief-payload.json << 'ENDJSON'
{
"parent": { "database_id": "NOTION_DATABASE_ID_HERE" },
"properties": {
"Name": {
"title": [{ "text": { "content": "Meeting Brief: COMPANY, DATE" } }]
},
"Date": {
"date": { "start": "YYYY-MM-DD" }
}
},
"children": [
{
"object": "block",
"type": "paragraph",
"paragraph": {
"rich_text": [{ "type": "text", "text": { "content": "BRIEF_CONTENT_HERE" } }]
}
}
]
}
ENDJSON
curl -s -X POST "https://api.notion.com/v1/pages" \
-H "Authorization: Bearer $NOTION_TOKEN" \
-H "Content-Type: application/json" \
-H "Notion-Version: 2022-06-28" \
-d @/tmp/notion-brief-payload.json
게시 후: "브리프가 Notion에 저장되었습니다. 데이터베이스를 확인하세요."
Notion이 설정되지 않은 경우: 브리프만 표시합니다. Notion에 대해 언급하지 않습니다.