CommunitySchreiben & Editierengithub.com

outreachmagic/lead-enrich

Personenrecherche für KI-Agenten. Durchsucht Serper nach LinkedIn, Firmendomäne und Website. Kombinierbar mit Outreach Magic zur Credits sparenden Deduplizierung.

Was ist lead-enrich?

Lead Enrich ist ein Skill für KI-Agenten, der Personenrecherche (Name + Unternehmen) mittels Serper.dev Google Search automatisiert. Er nutzt ausschließlich das eingebaute Modell des Agenten zur Datenextraktion, benötigt also keine externe LLM-API. Der Skill kann standalone mit einem Serper-API-Key verwendet werden oder in Kombination mit Outreach Magic (OM), um Credits zu sparen: Vor einer Serper-Anfrage prüft OM, ob der Lead bereits vollständige Informationen (LinkedIn + E-Mail) im selben Unternehmen hat – in diesem Fall werden null Serper-Credits verbraucht. Die Suche umfasst Unternehmensdomain, LinkedIn-Profil und ggf. die offizielle Website. Ergebnisse werden strukturiert als JSON ausgegeben oder bei OM-Nutzung direkt in der lokalen SQLite-Pipeline gespeichert. Der Skill unterstützt Batch-Verarbeitung von CSV/JSON-Dateien, Deduplizierung, Backfill von Feldern wie Titel/Branche und kann mit dem email-finder-Skill zur E-Mail-Suche erweitert werden. Er ist für Claude Code, Cursor und Codex optimiert und folgt strikten Regeln zur Transparenz, Batch-Obergrenzen und zur Vermeidung von direktem Scraping.

Funktioniert mit✓Claude Code✓Codex CLI✓Cursor✓Gemini CLI
npx skills add outreachmagic/lead-enrich

Installed? Explore more Schreiben & Editieren skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Lead Enrich

Recherchiere eine Person (Name + Unternehmen) mit Serper.dev Google Search. Verwendet das eingebaute Modell des Agenten zur Extraktion. Keine externe LLM-API nötig.

Funktioniert standalone – nur ein Serper-Key. Kombinierbar mit Outreach Magic für Credits sparende Deduplizierung (Serper überspringen, wenn Leads bereits LinkedIn/E-Mail haben) und dauerhafte Speicherung über Sitzungen hinweg.

Credits sparen (mit OM): Prüft outreachmagic zuerst. Wenn der Lead bereits LinkedIn + E-Mail im selben Unternehmen hat, werden null Serper-Credits verbraucht. LinkedIn ohne E-Mail überspringt Serper – verwende email-finder für trykitt. Nur-E-Mail-Datensätze erhalten weiterhin LinkedIn-Suchen (1–2 Serper-Credits). Namensübereinstimmungen in einem anderen Unternehmen geben ambiguous zurück, damit APIs nicht verschwendet werden.

Einrichtung

Standalone (ohne OM)

Nur ein Serper-Key. Führe serper-search direkt aus. Ergebnisse werden als JSON ausgegeben.

SchlüsselZweck
SERPER_API_KEYserper.dev – Google Search API
python3 scripts/enrich.py serper-search --query '"Acme Corp" official website'
python3 scripts/enrich.py serper-search --query 'site:linkedin.com/in Jane Doe Acme Corp'
# → Leite Ergebnisse an dein Modell zur Extraktion weiter oder verwende serper-format

Setze SERPER_API_KEY in deiner Umgebung oder über ~/.hermes/skills/lead-enrich/config.json.

Mit Outreach Magic (Deduplizierung + Speichern)

Fügt eine Vorab-Deduplizierung hinzu (Überspringen von Leads, die bereits in OM sind) und speichert die strukturierte Anreicherung in deiner lokalen SQLite-Pipeline. Erfordert den outreachmagic skill mit pipeline.py login.

SchlüsselZweck
Alle Standalone-Schlüssel oben +
OUTREACHMAGIC_AGENT_KEYOM-Login via pipeline.py login
python3 scripts/enrich.py check "Jane Doe" "Acme Corp"        # 0 Credits
python3 scripts/enrich.py batch-check --workspace W input.json # Batch-Deduplizierung

Speichere deinen Serper-Key im Outreach Magic Portal → Einstellungen → API-Schlüssel, führe dann pipeline.py sync-secrets aus. Überprüfe mit enrich.py config (serper_api_key_source sollte agent_secrets sein).

3. E-Mail-Suche (email-finder Skill)

Die E-Mail-Suche ist nicht in lead-enrich v2+ enthalten. Installiere email-finder mit outreachmagic gemäß der Plattform-Installationsanleitung. Oder installiere standalone via npx skills add outreachmagic/email-finder.

Nachdem die Serper-Anreicherung company_domain gespeichert hat, führe aus:

python3 ~/.hermes/skills/email-finder/scripts/email_finder.py find --name "Jane Doe" \
  --domain acme.com --linkedin "https://linkedin.com/in/janedoe" --save

Siehe references/email-finder.md und die Dokumentation des email-finder Skills.

Workspace-Zusammenfassungen (keine Serper-Credits): Nach dem Speichern von Leads verwende outreachmagic workspace summary --workspace <slug> --json für Tag-Anzahl und akzeptierte LinkedIn-Verbindungen pro Absender. Bei großen Workspaces (>2.000 Leads) füge --tags-only für schnellere Tag-Anzahlen hinzu. Nur lokale DB – Pull ist optional.

Häufige Workflows

Benutzer sagtDu tust
„Recherchiere diese Person“Serper-Suche → speichern via import-profiles
„Reichere meine CSV an“batch-check / import → fehlende Felder anreichern → in OM speichern
„Finde auch ihre E-Mail“Nach der Anreicherung an email-finder übergeben

Sales Nav / Vayne CSVs: Verwende outreachmagic import-profiles --file … (erkennt Spalten automatisch).

CSV / Award-Liste Workflow (bevorzugt für 10+ Personen)

Pfade wie outreachmagic/imports/awards.csv sind relativ zu deinem Workspace-Verzeichnis (wo der Agent den Befehl ausführt), nicht zum Skill-Installationsordner.

# 0 Credits – dedupliziere zuerst die gesamte Datei (markiert serper_attempted automatisch bei vollständigen Zeilen)
python3 scripts/enrich.py batch-check --workspace dein_workspace outreachmagic/imports/awards.csv

# Deduplizierung wiederholen, aber Leads mit Tag serper_attempted überspringen
python3 scripts/enrich.py batch-check --workspace dein_workspace --skip-tagged outreachmagic/imports/awards.csv

# Serper nur für Zeilen, die LinkedIn/Domain benötigen (überspringt team_award, exists_linkedin_*, skipped_serper_attempted)

# Nach der Recherche – Titel/Branche aktualisieren (0 Serper-Credits)
python3 scripts/enrich.py backfill --fields title,industry --workspace dein_workspace outreachmagic/imports/patch.csv

batch-check akzeptiert .json oder .csv. backfill erfordert email oder linkedin pro Zeile; verwendet chunked import-profiles via companion_common (200 Zeilen/Chunk, bis zu 300s/Chunk; füllt leere Felder; füge --overwrite hinzu, um zu ersetzen).

Wann verwenden

  • Benutzer sagt „recherchiere diese Person“ / „suche Jane Doe bei Acme“
  • Benutzer möchte eine Liste von Interessenten vor der Kontaktaufnahme anreichern
  • Benutzer fragt „haben wir diesen Lead schon?“ vor der Recherche
  • Benutzer stellt eine CSV/JSON mit Namen und Unternehmen zur Massenanreicherung bereit
  • Benutzer erwähnt Serper, Lead-Anreicherung oder Personenrecherche

Agent-Verhaltensregeln (Wichtig)

  1. Zuerst deduplizieren (mit OM). Vor jedem Serper-API-Aufruf enrich.py check ausführen. Wenn der Lead LinkedIn + E-Mail im selben Unternehmen hat, Serper komplett überspringen. Wenn LinkedIn existiert, aber keine E-Mail, Serper überspringen und email-finder anbieten, wenn der Benutzer eine Adresse möchte. Nie Serper-Credits für Leads ausgeben, die in outreachmagic bereits vollständig sind. Standalone: Prüfung überspringen – serper-search direkt ausführen.
  2. Nur Serper. Bevorzuge enrich.py serper-search --query "..." (stdlib HTTP, Key aus Konfiguration/Umgebung). Oder verwende curl mit $SERPER_API_KEY – Key niemals in Chat-Logs einbetten. Niemals Google oder LinkedIn direkt scrapen.
  3. Nur eingebautes Modell. Du (der Agent) extrahierst JSON aus Serper-Ergebnissen. Keine externen LLM-APIs (kein Gemini, kein OpenAI) – deine eigene Argumentation ist die Extraktions-Engine.
  4. Vollständige Recherche vor dem Speichern. Führe zuerst die vollständige Suchleiter aus, dann einmal speichern.
  5. Speichern via outreachmagic (mit OM). Verwende import-profiles für Leads mit LinkedIn. Hänge beim Speichern immer serper_attempted an die Tags an (automatisch in map-to-om Ausgabe enthalten). Für Leads ohne LinkedIn aber bekannter lead_id, markiere den Tag via stamp-attempted oder import-profiles mit id + Tags – verlasse dich nicht nur auf Notizen. Für schreibgeschützte Deduplizierungsprüfungen verwende pipeline.py query oder enrich.py check – niemals rohes INSERT/UPDATE. Führe niemals beide Speicherpfade für dieselbe Person aus. Standalone: Speichere JSON-Ausgabe in einer Datei – kein OM nötig.
  6. Taggen nach der Anreicherung (mit OM). Jeder Lead, der durch Serper geht, muss beim Speichern serper_attempted erhalten. Verhindert erneute Verarbeitung bei zukünftigen Läufen.
  7. Tag vor Serper prüfen (mit OM). Vor dem Ausgeben von Serper-Credits auf serper_attempted prüfen (via enrich.py check --skip-tagged oder skip_reason in der Prüfausgabe). Wenn vorhanden und LinkedIn immer noch leer, überspringen, es sei denn, der Benutzer möchte explizit einen erneuten Versuch (z.B. älter als 30 Tage).
  8. Transparenz. Zeige an, welche Serper-Abfragen ausgeführt wurden, die Konfidenz und was gespeichert wurde. Der Benutzer soll genau sehen, wohin seine Credits geflossen sind.
  9. Klug bündeln. Maximal 50 Personen pro Durchlauf. Für CSV/Award-Listen führe zuerst batch-check einmal auf der gesamten Datei (JSON oder CSV) vor Serper aus. Verarbeite Serper nur für Status, die LinkedIn/Domain benötigen. Überspringe team_award, exists_linkedin_email und skipped_serper_attempted Zeilen.
  10. E-Mail-Suche – verwende email-finder. Nachdem die Anreicherung company_domain gespeichert hat, übergib an email-finder (email_finder.py find --save). Siehe references/email-finder.md. Erfinde oder rate niemals E-Mails in diesem Skill.

Schnellstart

# Einzelperson (häufigster Fall)
python3 scripts/enrich.py check "Jane Doe" "Acme Corp"
# → wenn "not_found", mit dem Serper-Suchpaket unten fortfahren

# Mit Workspace (verknüpft Lead mit deinem Pipeline-Workspace)
python3 scripts/enrich.py check --workspace dein_workspace "Jane Doe" "Acme Corp"

# Stapelverarbeitung aus JSON oder CSV (vor Serper bei Listen ausführen)
python3 scripts/enrich.py batch-check --workspace dein_workspace outreachmagic/imports/people.json
python3 scripts/enrich.py batch-check --workspace dein_workspace --skip-tagged outreachmagic/imports/awards.csv

# Markiere serper_attempted nach fehlgeschlagener LinkedIn-Suche (wenn lead_id bekannt ist)
python3 scripts/enrich.py stamp-attempted --workspace dein_workspace --lead-ids 42,43 \
  --notes "Kein LinkedIn via Serper gefunden"

# Backfill von Titel/Branche bei bestehenden Leads (LinkedIn oder E-Mail erforderlich)
python3 scripts/enrich.py backfill --fields title,industry outreachmagic/imports/patch.csv

# Skill sicher von GitHub Release aktualisieren (Checksum-verifiziert)
python3 scripts/enrich.py update --check
python3 scripts/enrich.py update

update überprüft SHA256-Prüfsummen aus update-manifest.json, bevor Dateien ersetzt werden. Wenn Prüfsummen fehlen oder nicht übereinstimmen, wird das Update abgebrochen.

Kern-Workflow

Phase 1 – Deduplizierungsprüfung (0 Credits)

Für jede Person ausführen:

# Ohne Workspace (organisationsweite Suche)
python3 scripts/enrich.py check "Jane Doe" "Acme Corp"

# Mit Workspace (auf deinen Pipeline-Workspace beschränkt)
python3 scripts/enrich.py check --workspace dein_workspace "Jane Doe" "Acme Corp"

Ausgabe pro Person:

StatusBedeutungAktion
exists_linkedin_emailGleiches Unternehmen, LinkedIn + E-MailSerper und E-Mail-APIs überspringen
exists_linkedin_no_emailGleiches Unternehmen, LinkedIn, keine E-MailSerper überspringen → email-finder, wenn Benutzer E-Mail möchte
exists_no_linkedin_emailGleiches Unternehmen, E-Mail, kein LinkedInNur LinkedIn Serper-Abfragen
exists_no_linkedinGleiches Unternehmen, weder nochNur LinkedIn Serper-Abfragen
skipped_serper_attemptedHat Tag serper_attempted, kein LinkedInSerper überspringen – bereits versucht
ambiguousNamensübereinstimmung, Unternehmen weicht abVolles Serper-Paket ausführen – nicht überspringen
not_foundKeine ÜbereinstimmungVolles Serper-Suchpaket ausführen
team_awardTeam-/Gruppenzeile (keine Einzelperson)Serper überspringen – tagge team_award, Kontaktnotiz hinzufügen
dedup_disableddedup_before_search: false in KonfigurationSerper wie gewünscht ausführen

Prüfausgabe enthält tags und optionalen skip_reason (has_linkedin oder skipped_serper_attempted). Verwendet batch-lead-lookup (lokal, null Serper-Credits).

Phase 2 – Serper-Suchpaket

Nur für Personen ausführen, die es benötigen. 2–4 Suchen pro Person abhängig von der Ergebnisqualität:

Serper-Credit-Budget-Schätzer

  • Pro Person Minimum: 0 Serper-Credits (exists_linkedin_email).
  • Häufiger Pfad: 2 Credits (2a striktes Unternehmen + 2c LinkedIn-Profil).
  • Pro Person hartes Maximum: 4 Credits, wenn alle Fallbacks nötig sind (2a + 2b + 2c + 2e).
  • Batch-Formel: min=0, max=4*N wobei N die Anzahl der Personen im Durchlauf ist.
  • Batch-Obergrenze Beispiel: mit N=50 ist das harte Maximum 200 Credits (schlimmster Fall).

2a. Unternehmensfindung – strikt (immer)

Bevorzugt (kein Schlüssel in der Shell-Historie):

python3 scripts/enrich.py serper-search --query '"Acme Corp" offizielle website' --label company_discovery_strict

Oder Wiederholung mit einfacherer Abfrage:

python3 scripts/enrich.py serper-search --query 'Acme Corp website' --label company_discovery_broad

2b. Unternehmensfindung – breit (bedingt)

Nur ausführen, wenn 2a keine organischen Ergebnisse mit einem http:// oder https:// Link zurückgibt:

python3 scripts/enrich.py serper-search --query 'Acme Corp offizielle website' --label company_discovery_broad

(Gleiche Vorlage, Firmenname in Anführungszeichen.)

2c. LinkedIn-Profil (immer)

Abfrage erstellen (Firmenname ohne Anführungszeichen – passt auf verschiedene Arbeitgebervarianten in Snippets):

site:linkedin.com/in {Vorname Nachname} {bis zu 5 Wörter der Rolle} {Firmenname}

Beispiel:

python3 scripts/enrich.py serper-search \
  --query 'site:linkedin.com/in Jane Doe VP Marketing Acme Corp' \
  --label linkedin_profile

Phase 3 – Modellextraktion

Übergib die formatierten Serper-Ergebnisse an dich selbst (das Agentenmodell) mit dieser Systemanweisung:

Du bist ein Forschungsassistent. Die Benutzernachricht enthält Serper.dev Google-Suchergebnisse
in beschrifteten Abschnitten. Du hast KEINE Live-Websuche – verwende nur die eingefügten Blöcke.

Aufgabe: Für EINE bestimmte Person bei EINEM Unternehmen extrahiere:
- company_domain: registrierbarer Hostname nur (kein Pfad, kein www), oder leerer String
- company_website: vollständige https:// Startseiten-URL falls unterstützt, oder leerer String
- linkedin_url: https://linkedin.com/in/… für die genannte Person bei diesem Unternehmen, oder leerer String
- confidence: high | medium | low
- note: optionale Erklärung von Mehrdeutigkeiten oder Lücken

Regeln:
- Jede nicht-leere URL muss in den Serper-Blöcken vorkommen (geringfügige Query-String-Normalisierung ok)
- Name auf LinkedIn kann vom Input abweichen (Spitzname vs. legaler Name) – gleiche Person + Arbeitgeber erkennen
- Bevor du `linkedin_url` akzeptierst, überprüfe die Übereinstimmungsqualität:
  - Extrahiere Vor- und Nachnamen-Token aus "Full name: {full_name}" (ignoriere Satzzeichen)
  - Das gewählte `/in/` Ergebnis muss *beide* Token entweder im `title` oder `snippet` des Ergebnisses enthalten
  - Wenn kein `/in/` Ergebnis die Token-Anforderung erfüllt, gib `linkedin_url` als leeren String zurück und setze `confidence` auf `low`
- Die öffentliche Website des Unternehmens kann einen anderen Namen verwenden als der Input – bevorzuge offizielle Belege
- Bei der Auflösung von `company_domain`:
  - Bevorzuge `knowledgeGraph.website`, wenn vorhanden
  - Lehne allgemeine Aggregatoren/Register ab (Beispiele: `naceweb.org`, `usnews.com`, `wikipedia.org`, `niche.com`, `facebook.com`, `instagram.com`, `twitter.com`)
  - Wenn `company_name` zu fehlen scheint oder dem Personennamen stark ähnelt, gib leeren String zurück
- Erfinde niemals URLs oder Slugs

Antworte NUR mit einem einzelnen JSON-Objekt (keine Markdown-Umrandungen):
{"company_domain":"","company_website":"","linkedin_url":"","confidence":"medium","note":""}

Verwende diese Benutzernachrichtenvorlage:

### Zielperson
Vollständiger Name: {full_name}
Angegebene Rolle/Position: {stated_role}
Unternehmen (wie angegeben): {company_name}

### Suchergebnisse
{formatted_serper_sections}

### Aufgabe
Gib das JSON-Objekt zurück, das in der Systemanweisung beschrieben wird.

Dann analysiere deine eigene Antwort: Entferne Markdown-Umrandungen, extrahiere das JSON-Objekt.

LinkedIn-Harvest-Fallback: Wenn linkedin_url nach der Extraktion leer ist, durchsuche die rohen Serper-Ergebnisse nach /in/ URLs, deren Titel sowohl Vor- als auch Nachnamen-Token enthält. Bevorzuge Übereinstimmungen mit höherer Token-Überlappung.

Phase 4 – Speichern (mit OM: import-profiles)

# Formatiere den extrahierten JSON-Lead für OM (wandelt Feldnamen um, hängt serper_attempted an Tags an)
python3 scripts/enrich.py map-to-om
# → liest von stdin und gibt formatiertes JSON aus

# Beispiel mit Pipe:
echo '{"company_domain":"acme.com","company_website":"https://acme.com","linkedin_url":"https://linkedin.com/in/janedoe","confidence":"high"}' | \
  python3 scripts/enrich.py map-to-om

# Speichere in OM mit Workspace-Scope
python3 scripts/enrich.py map-to-om | \
  python3 -m outreachmagic.pipeline import-profiles --workspace dein_workspace

map-to-om akzeptiert JSON von stdin. Ausgabe: formatiertes import-profiles JSON mit hinzugefügten Tags (serper_attempted, ggf. team_award).

Wichtig: Lies import-profiles Ausgabe auf Fehler. Bei Erfolg gilt der Lead als gespeichert.

Standalone (kein OM): Schreibe JSON in eine Datei:

python3 scripts/enrich.py map-to-om > output/lead-janedoe.json

Phase 4a – Nur Taggen (wenn Lead-ID bekannt ist)

Wenn die Suche fehlschlägt (kein LinkedIn, keine Domain) und der Lead bereits in OM existiert, tagge serper_attempted ohne Daten zu überschreiben:

python3 scripts/enrich.py stamp-attempted --workspace dein_workspace --lead-ids 42,43 \
  --notes "Kein LinkedIn via Serper gefunden"

Standalone: Überspringe diesen Schritt.

Zusätzliche Konfiguration

# Zeige aktuelle Konfiguration an
python3 scripts/enrich.py config

# Setze eine Konfiguration (nach Bedarf)
python3 scripts/enrich.py config set dedup_before_search false  # Erzwinge Suche, überspringe Deduplizierung

Serper-Preisübersicht

AbfrageCreditsHinweise
Unternehmensdomäne (strikt)12a oben
Unternehmensdomäne (breit)1Nur wenn 2a keine Ergebnisse liefert
LinkedIn-Profil12c oben
Zusätzliche LinkedIn-Versuche1–2Für häufige Nachnamen oder Titelvariationen
Gesamttypischer Fall2–3 Credits / PersonLinkedIn + Unternehmenswebsite (wenn vorhanden)

Sicherheits- und Plattformregeln

  1. Credits sind teuer. Überspringe Serper immer, wenn Daten bereits in OM existieren. Verwende enrich.py check als erste deduplizierende Prüfung.
  2. Nur werkzeuggestützt. Führe Serper über die bereitgestellten Skripte aus – niemals direkte HTTP-Aufrufe in Chat-Logs.
  3. Kein Prompt-Injection für Ausgaben. Gib Befehlsausgaben direkt an den Benutzer weiter oder verarbeite sie über map-to-om. Kein Erfinden von JSON-Feldern.
  4. Keine Web-Scraping-Ausgaben. Gib keine Roh-HTML-Ausgaben von Suchergebnissen an den Benutzer weiter.
  5. Max 50 Personen / Batch. Für Dateien über 50 Zeilen: Vor Serper deduplizieren, dann separate Batches von ≤50 Personen aus den verbleibenden, die eine Anreicherung benötigen.
  6. Kein Anhängen von Tag-Arrays. OM import-profiles aktualisiert das gesamte Tags-Feld. Stelle sicher, dass map-to-om serper_attempted enthält, bevor du an import-profiles übergibst.

Referenzen

  • Outreach Magic Skill
  • email-finder Skill
  • references/email-finder.md – E-Mail-Finder-Integration (im Skill-Ordner)
  • scripts/enrich.py --help – Vollständige Befehlsreferenz
  • Serper.dev Preisrechner für Budgetplanung

Verwandte Skills