Meeting Brief Generator
Nimmt einen Firmennamen und optional einen Kontakt entgegen. Recherchiert das Unternehmen über Tavily. Synthetisiert ein einseitiges Pre-Call-Briefing mit Gemini. Optional in Notion speicherbar.
Wichtige Regel: KEINE DETAILS ERFINDEN. Jede Tatsache, Zahl und Behauptung im Briefing muss aus einem Tavily-Suchergebnis stammen. Markiere Abschnitte ohne Suchergebnisse mit „Begrenzte öffentliche Informationen gefunden.“ Erfinde niemals Finanzierungsbeträge, Mitarbeiterzahlen oder Produktdetails.
Schritt 1: Setup-Prüfung
Prüfe die erforderlichen Umgebungsvariablen:
echo "TAVILY_API_KEY: ${TAVILY_API_KEY:+gesetzt}"
echo "GEMINI_API_KEY: ${GEMINI_API_KEY:+gesetzt}"
echo "NOTION_TOKEN: ${NOTION_TOKEN:-nicht gesetzt}"
echo "NOTION_DATABASE_ID: ${NOTION_DATABASE_ID:-nicht gesetzt}"
Wenn TAVILY_API_KEY fehlt: Stopp. Teile dem Benutzer mit: „TAVILY_API_KEY wird benötigt. Hole ihn unter app.tavily.com ab und füge ihn deiner .env-Datei hinzu.“
Wenn GEMINI_API_KEY fehlt: Stopp. Teile dem Benutzer mit: „GEMINI_API_KEY wird benötigt. Hole ihn unter aistudio.google.com ab und füge ihn deiner .env-Datei hinzu.“
Wenn NOTION_TOKEN oder NOTION_DATABASE_ID fehlt: Fahre fort. Das Briefing wird nur als Text ausgegeben. Das Speichern in Notion wird übersprungen.
Bestätige, dass eine Eingabe vorhanden ist. Der Benutzer muss mindestens einen Firmennamen angeben. Falls nicht vorhanden, frage: „Mit welchem Unternehmen hast du das Meeting?“
Schritt 2: Kontext sammeln
Sammle die folgenden Informationen. Frage nur nach dem, was fehlt.
Erforderlich:
- Firmenname (oder Domain/URL, falls angegeben)
- Meeting-Datum
Optional (nicht blockierend, wenn fehlend):
- Kontaktname und -position
- Meeting-Typ (Discovery, Demo, Follow-up, QBR)
- Bestimmte Themen oder Ziele, die der Benutzer besprechen möchte
Falls der Benutzer eine Firmen-URL oder Domain angibt, nutze sie für präzisere Tavily-Abfragen (z. B. site:beispiel.com oder die Domain in die Suchbegriffe einfügen).
Schritt 3: Recherche mit Tavily
Führe diese Suchen nacheinander aus. Jede zielt auf einen Abschnitt des Briefings. Speichere die besten Ergebnisse jeder Suche (Titel, URL, Inhaltsausschnitt, Bewertung).
Behalte Ergebnisse mit einer Bewertung >= 0,5. Falls eine Suche 0 qualifizierende Ergebnisse liefert, markiere diesen Abschnitt als „Begrenzte öffentliche Informationen gefunden.“
Suche 1: Firmenübersicht
curl -s -X POST "https://api.tavily.com/search" \
-H "Content-Type: application/json" \
-d '{
"api_key": "'"$TAVILY_API_KEY"'",
"query": "\"FIRMA\" Überblick Gründung Mitarbeiter Hauptsitz",
"search_depth": "advanced",
"max_results": 5,
"include_answer": true
}'
Suche 2: Aktuelle Neuigkeiten (letzte 30 Tage)
curl -s -X POST "https://api.tavily.com/search" \
-H "Content-Type: application/json" \
-d '{
"api_key": "'"$TAVILY_API_KEY"'",
"query": "\"FIRMA\" Neuigkeiten Ankündigung",
"search_depth": "advanced",
"max_results": 5,
"include_answer": true,
"topic": "news",
"time_range": "month"
}'
Suche 3: Tech-Stack
curl -s -X POST "https://api.tavily.com/search" \
-H "Content-Type: application/json" \
-d '{
"api_key": "'"$TAVILY_API_KEY"'",
"query": "\"FIRMA\" Technologie-Stack Entwicklung Infrastruktur Werkzeuge",
"search_depth": "advanced",
"max_results": 5,
"include_answer": true
}'
Suche 4: Produkt und Preise
curl -s -X POST "https://api.tavily.com/search" \
-H "Content-Type: application/json" \
-d '{
"api_key": "'"$TAVILY_API_KEY"'",
"query": "\"FIRMA\" Produkt Funktionen Preise Anwendungsfall",
"search_depth": "advanced",
"max_results": 5,
"include_answer": true
}'
Suche 5: Wettbewerber
curl -s -X POST "https://api.tavily.com/search" \
-H "Content-Type: application/json" \
-d '{
"api_key": "'"$TAVILY_API_KEY"'",
"query": "\"FIRMA\" Wettbewerber Alternativen vs",
"search_depth": "advanced",
"max_results": 5,
"include_answer": true
}'
Suche 6: Finanzierung und Wachstum
curl -s -X POST "https://api.tavily.com/search" \
-H "Content-Type: application/json" \
-d '{
"api_key": "'"$TAVILY_API_KEY"'",
"query": "\"FIRMA\" Finanzierung aufgenommen Bewertung Wachstum",
"search_depth": "advanced",
"max_results": 5,
"include_answer": true
}'
Falls ein Kontaktname angegeben ist, führe zwei weitere Suchen durch:
Suche 7: Kontaktprofil
curl -s -X POST "https://api.tavily.com/search" \
-H "Content-Type: application/json" \
-d '{
"api_key": "'"$TAVILY_API_KEY"'",
"query": "\"KONTAKTNAME\" \"FIRMA\" Rolle Position",
"search_depth": "advanced",
"max_results": 5,
"include_answer": true
}'
Suche 8: Kontakthintergrund
curl -s -X POST "https://api.tavily.com/search" \
-H "Content-Type: application/json" \
-d '{
"api_key": "'"$TAVILY_API_KEY"'",
"query": "\"KONTAKTNAME\" Hintergrund Karriere LinkedIn",
"search_depth": "advanced",
"max_results": 5,
"include_answer": true
}'
Schritt 4: Synthese mit Gemini
Lies references/brief-format.md vollständig. Lies references/output-template.md und verwende die Vorlage.
Schreibe die Gemini-Anfrage in eine temporäre Datei:
cat > /tmp/meeting-brief-request.json << 'ENDJSON'
{
"system_instruction": {
"parts": [{
"text": "Du bist ein GTM Research Analyst, der ein einseitiges Pre-Call-Briefing für ein Vertriebs- oder Geschäftsentwicklungsmeeting vorbereitet. Regeln: Jede Behauptung muss eine Quell-URL aus der bereitgestellten Recherche zitieren. Verwende das Format 'Weil [Erkenntnis aus der Recherche], erwähne [Punkt], um [Ziel zu erreichen]' für Gesprächspunkte. Keine erfundenen Daten. Wenn ein Abschnitt keine Recherchedaten hat, schreibe 'Begrenzte öffentliche Informationen gefunden.' Keine Gedankenstriche. Keine verbotenen Wörter. Maximal 400 Wörter insgesamt. Das Briefing muss in maximal 3 Minuten überfliegbar sein."
}]
},
"contents": [{
"parts": [{
"text": "FORSCHUNGSERGEBNISSE_UND_ANWEISUNGEN_HIER"
}]
}],
"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'])"
Ersetze FORSCHUNGSERGEBNISSE_UND_ANWEISUNGEN_HIER durch:
- Alle Tavily-Suchergebnisse (Titel, URL, Inhaltsausschnitt pro Ergebnis)
- Die Struktur der Briefing-Vorlage aus output-template.md
- Den Firmennamen, den Kontaktnamen (falls vorhanden), das Meeting-Datum, den Meeting-Typ (falls vorhanden)
Schritt 5: Selbst-QA
Prüfe vor der Präsentation:
- Keine erfundenen Daten. Jede Tatsache hat eine Quell-URL aus Tavily-Ergebnissen.
- Gesprächspunkte verwenden das Format „Weil [Erkenntnis], erwähne [Punkt], um [Ziel]“
- Keine Gedankenstriche in keiner Zeile
- Keine verbotenen Wörter
- Briefing unter 400 Wörtern
- Abschnitt „Entscheidungsträger“ sagt „Nicht angegeben“, wenn kein Kontakt bereitgestellt wurde
- Abschnitte ohne Daten sagen „Begrenzte öffentliche Informationen gefunden“ anstatt zu raten
- Offene Fragen sind spezifisch für dieses Unternehmen, nicht allgemein
Behebe jede Verletzung, bevor du präsentierst.
Schritt 6: Ausgabe oder Speichern in Notion
Präsentiere das vollständige Briefing in einem Codeblock.
Wenn sowohl NOTION_TOKEN als auch NOTION_DATABASE_ID gesetzt sind, frage: „Dieses Briefing in Notion speichern?“
Nach Bestätigung:
cat > /tmp/notion-brief-payload.json << 'ENDJSON'
{
"parent": { "database_id": "NOTION_DATABASE_ID_HIER" },
"properties": {
"Name": {
"title": [{ "text": { "content": "Meeting Brief: FIRMA, DATUM" } }]
},
"Date": {
"date": { "start": "YYYY-MM-DD" }
}
},
"children": [
{
"object": "block",
"type": "paragraph",
"paragraph": {
"rich_text": [{ "type": "text", "text": { "content": "BRIEFING_INHALT_HIER" } }]
}
}
]
}
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
Nach dem Posten: „Briefing in Notion gespeichert. Überprüfe deine Datenbank.“
Falls Notion nicht konfiguriert ist: gib nur das Briefing aus. Erwähne Notion nicht.