CommunityRedacción y edicióngithub.com

Lead Enrich

Investigación de personas para agentes de IA. Busca en Serper LinkedIn, dominio de empresa y sitio web. Se combina con Outreach Magic para deduplicación que ahorra créditos.

¿Qué es Lead Enrich?

Lead Enrich es una habilidad para agentes de IA como Claude Code, Cursor o Codex que permite investigar información de contacto y profesional de una persona a partir de su nombre y empresa. Utiliza la API de búsqueda de Serper.dev para encontrar el dominio de la empresa, su sitio web oficial y el perfil de LinkedIn de la persona, todo ello procesado por el modelo de lenguaje integrado del agente, sin necesidad de APIs LLM externas. La habilidad funciona de forma autónoma con solo una clave de Serper, pero se integra opcionalmente con Outreach Magic para realizar una deduplicación previa que ahorra créditos de Serper, evitando búsquedas en contactos que ya tienen LinkedIn y email, y para almacenar los resultados de forma persistente entre sesiones. Esto permite enriquecer listas de prospectos de manera eficiente, ya sea uno por uno o en lotes desde archivos CSV o JSON, con un flujo de trabajo que maximiza el uso de los créditos de la API de Serper.

Compatible con✓Claude Code✓Codex CLI✓Cursor✓Gemini CLI
npx skills add outreachmagic/lead-enrich

Installed? Explore more Redacción y edición skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

¿Qué hace Lead Enrich?

Investiga una persona (nombre + empresa) usando Serper.dev Google Search. Utiliza el modelo incorporado del agente para la extracción. No necesita API LLM externa.

Funciona de forma independiente — solo una clave de Serper. Se combina con Outreach Magic para deduplicación que ahorra créditos (evita Serper cuando los leads ya tienen LinkedIn/email) y almacenamiento persistente entre sesiones.

Ahorro de créditos (con OM): verifica outreachmagic primero. Si el lead ya tiene LinkedIn + email en la misma empresa, no gasta créditos de Serper. LinkedIn sin email evita Serper — use email-finder para trykitt. Los registros solo con email aún obtienen búsquedas de LinkedIn (1–2 créditos de Serper). Las coincidencias de nombre en una empresa diferente devuelven ambiguous para no desperdiciar APIs.

Configuración

Independiente (sin OM)

Solo una clave de Serper. Ejecute serper-search directamente. Los resultados se imprimen en JSON.

ClavePara
SERPER_API_KEYserper.dev — API de Búsqueda de Google
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'
# → canalice los resultados a su modelo para extracción, o use serper-format

Establezca SERPER_API_KEY en su entorno o mediante ~/.hermes/skills/lead-enrich/config.json.

Con Outreach Magic (deduplicación + guardado)

Agrega deduplicación previa (salta leads ya en OM) y guarda el enriquecimiento estructurado en su pipeline SQLite local. Requiere la habilidad outreachmagic con pipeline.py login.

ClavePara
Todas las claves independientes anteriores +
OUTREACHMAGIC_AGENT_KEYInicio de sesión OM mediante pipeline.py login
python3 scripts/enrich.py check "Jane Doe" "Acme Corp"        # 0 créditos
python3 scripts/enrich.py batch-check --workspace W input.json # deduplicación por lotes

Guarde su clave de Serper en Portal de Outreach Magic → Configuración → API Keys, luego ejecute pipeline.py sync-secrets. Verifique con enrich.py config (serper_api_key_source debe ser agent_secrets).

3. Búsqueda de correo electrónico (habilidad email-finder)

La búsqueda de correo no está en lead-enrich v2+. Instale email-finder con outreachmagic usando la guía de instalación de la plataforma. O instálelo de forma independiente mediante npx skills add outreachmagic/email-finder.

Después de que el enriquecimiento de Serper guarde company_domain, ejecute:

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

Consulte references/email-finder.md y la documentación de la habilidad email-finder.

Resúmenes de espacio de trabajo (sin créditos de Serper): después de guardar leads, use outreachmagic workspace summary --workspace <slug> --json para conteos de etiquetas y conexiones de LinkedIn aceptadas por remitente. En espacios de trabajo grandes (>2,000 leads), agregue --tags-only para conteos de etiquetas más rápidos. Solo base de datos local: opcional.

Flujos de trabajo comunes

El usuario diceUsted hace
"Investiga a esta persona"Búsqueda en Serper → guardar mediante import-profiles
"Enriquece mi CSV"batch-check / importar → enriquecer campos faltantes → guardar en OM
"Encuentra también su correo"Después del enriquecimiento, pasar a email-finder

CSV de Sales Nav / Vayne: use outreachmagic import-profiles --file … (detecta columnas automáticamente).

Flujo de trabajo CSV / lista de premios (preferido para 10+ personas)

Rutas como outreachmagic/imports/awards.csv son relativas a su directorio de espacio de trabajo (donde el agente ejecuta el comando), no a la carpeta de instalación de la habilidad.

# 0 créditos — deduplicar todo el archivo primero (marca automáticamente serper_attempted en filas completas)
python3 scripts/enrich.py batch-check --workspace your_workspace outreachmagic/imports/awards.csv

# Re-ejecutar deduplicación saltando leads ya etiquetados como serper_attempted
python3 scripts/enrich.py batch-check --workspace your_workspace --skip-tagged outreachmagic/imports/awards.csv

# Serper solo para filas que necesitan LinkedIn/dominio (salta team_award, exists_linkedin_*, skipped_serper_attempted)

# Después de la investigación — parchear título/industria solamente (0 créditos de Serper)
python3 scripts/enrich.py backfill --fields title,industry --workspace your_workspace outreachmagic/imports/patch.csv

batch-check acepta .json o .csv. backfill requiere email o linkedin por fila; usa import-profiles fragmentado mediante companion_common (200 filas/fragmento, hasta 300s/fragmento; completa campos vacíos; agregue --overwrite para reemplazar).

Cuándo usar

  • El usuario dice "investiga a esta persona" / "busca a Jane Doe en Acme"
  • El usuario quiere enriquecer una lista de prospectos antes del contacto
  • El usuario pregunta "¿ya tenemos este lead?" antes de investigar
  • El usuario proporciona un CSV/JSON de nombres y empresas para enriquecer en lote
  • El usuario menciona Serper, enriquecimiento de leads o investigación de personas

Reglas de comportamiento del agente (Importante)

  1. Deduplicar primero (con OM). Antes de cualquier llamada a la API de Serper, ejecute enrich.py check. Si el lead tiene LinkedIn + email en la misma empresa, salte Serper por completo. Si LinkedIn existe pero sin email, salte Serper y ofrezca email-finder cuando el usuario quiera una dirección. Nunca gaste créditos de Serper en leads ya completos en outreachmagic. Independiente: salte la verificación — ejecute serper-search directamente.
  2. Solo Serper. Prefiera enrich.py serper-search --query "..." (HTTP estándar, clave desde configuración/entorno). O use curl con $SERPER_API_KEY — nunca incruste la clave en registros de chat. Nunca raspe Google o LinkedIn directamente.
  3. Solo modelo incorporado. Usted (el agente) extrae JSON de los resultados de Serper. Sin APIs LLM externas (sin Gemini, sin OpenAI) — su propio razonamiento es el motor de extracción.
  4. Investigar completamente antes de guardar. Ejecute primero la escalera de búsqueda completa, luego guarde una vez.
  5. Guardar mediante outreachmagic (con OM). Use import-profiles para leads con LinkedIn. Siempre agregue serper_attempted a las etiquetas al guardar (incluido automáticamente en la salida map-to-om). Para leads sin LinkedIn pero con un lead_id conocido, marque la etiqueta mediante stamp-attempted o import-profiles con id + etiquetas — no confíe solo en notas. Para verificaciones de deduplicación de solo lectura use pipeline.py query o enrich.py check — nunca INSERT/UPDATE sin procesar. Nunca ejecute ambas rutas de guardado para la misma persona. Independiente: guarde la salida JSON en un archivo — no se necesita OM.
  6. Etiquetar después del enriquecimiento (con OM). Cada lead que pase por Serper debe obtener serper_attempted al guardar. Evita el reprocesamiento en ejecuciones futuras.
  7. Verificar etiqueta antes de Serper (con OM). Antes de gastar créditos de Serper, verifique serper_attempted (mediante enrich.py check --skip-tagged o skip_reason en la salida de check). Si está presente y LinkedIn aún está vacío, salte a menos que el usuario quiera explícitamente un reintento (p. ej., desactualizado >30 días).
  8. Transparencia. Muestre qué consultas de Serper se ejecutaron, la confianza y qué se guardó. El usuario debe ver exactamente dónde se gastaron sus créditos.
  9. Procesar por lotes con criterio. Limite a 50 personas por ejecución. Para CSV/listas de premios, ejecute batch-check una vez en todo el archivo (JSON o CSV) antes de cualquier Serper. Procese Serper solo para estados que necesiten LinkedIn/dominio. Salte las filas team_award, exists_linkedin_email y skipped_serper_attempted.
  10. Búsqueda de correo — use email-finder. Después de que el enriquecimiento guarde company_domain, pase a email-finder (email_finder.py find --save). Consulte references/email-finder.md. Nunca invente ni adivine patrones de correo electrónico en esta habilidad.

Inicio rápido

# Persona individual (más común)
python3 scripts/enrich.py check "Jane Doe" "Acme Corp"
# → si "not_found", proceda con el paquete de búsqueda de Serper a continuación

# Con espacio de trabajo (asocia el lead con su pipeline de espacio de trabajo)
python3 scripts/enrich.py check --workspace your_workspace "Jane Doe" "Acme Corp"

# Lote desde JSON o CSV (ejecute esto antes de Serper en listas)
python3 scripts/enrich.py batch-check --workspace your_workspace outreachmagic/imports/people.json
python3 scripts/enrich.py batch-check --workspace your_workspace --skip-tagged outreachmagic/imports/awards.csv

# Marcar serper_attempted después de una búsqueda fallida de LinkedIn (cuando se conoce lead_id)
python3 scripts/enrich.py stamp-attempted --workspace your_workspace --lead-ids 42,43 \
  --notes "No se encontró LinkedIn mediante Serper"

# Rellenar título/industria en leads existentes (se requiere linkedin o email)
python3 scripts/enrich.py backfill --fields title,industry outreachmagic/imports/patch.csv

# Actualizar la habilidad de forma segura desde el lanzamiento de GitHub (verificado por suma de verificación)
python3 scripts/enrich.py update --check
python3 scripts/enrich.py update

update verifica sumas de verificación SHA256 de update-manifest.json antes de reemplazar archivos. Si las sumas de verificación faltan o no coinciden, la actualización se cancela.

Flujo de trabajo principal

Fase 1 — Verificación de deduplicación (0 créditos)

Para cada persona, ejecute:

# Sin espacio de trabajo (búsqueda en toda la organización)
python3 scripts/enrich.py check "Jane Doe" "Acme Corp"

# Con espacio de trabajo (limitado a su pipeline de espacio de trabajo)
python3 scripts/enrich.py check --workspace your_workspace "Jane Doe" "Acme Corp"

Salida por persona:

EstadoSignificadoAcción
exists_linkedin_emailMisma empresa, LinkedIn + emailSaltar Serper y APIs de correo
exists_linkedin_no_emailMisma empresa, LinkedIn, sin emailSaltar Serper → email-finder si el usuario quiere correo
exists_no_linkedin_emailMisma empresa, email, sin LinkedInSolo consultas de LinkedIn en Serper
exists_no_linkedinMisma empresa, ningunoSolo consultas de LinkedIn en Serper
skipped_serper_attemptedTiene etiqueta serper_attempted, sin LinkedInSaltar Serper — ya se intentó
ambiguousCoincidencia de nombre, desajuste de empresaEjecutar paquete completo de Serper — no saltar
not_foundSin coincidenciaEjecutar paquete de búsqueda completo de Serper
team_awardFila de equipo/grupo (sin individuo)Saltar Serper — etiquetar team_award, agregar nota de contacto
dedup_disableddedup_before_search: false en configuraciónEjecutar Serper según lo solicitado

La salida de check incluye tags y skip_reason opcional (has_linkedin o skipped_serper_attempted). Usa batch-lead-lookup (local, cero créditos de Serper).

Fase 2 — Paquete de búsqueda de Serper

Ejecutar solo para personas que lo necesiten. 2–4 búsquedas por persona dependiendo de la calidad del resultado:

Estimador de presupuesto de créditos de Serper

  • Mínimo por persona: 0 créditos de Serper (exists_linkedin_email).
  • Ruta común: 2 créditos (2a empresa estricta + 2c perfil de LinkedIn).
  • Máximo duro por persona: 4 créditos cuando se necesitan todos los respaldos (2a + 2b + 2c + 2e).
  • Fórmula de lote: min=0, max=4*N donde N son las personas en la ejecución.
  • Ejemplo de límite de lote: con N=50, el máximo duro es 200 créditos (peor caso).

2a. Descubrimiento de empresa — estricto (siempre)

Preferido (sin clave en el historial del shell):

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

O reintentar con una consulta más simple:

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

2b. Descubrimiento de empresa — amplio (condicional)

Ejecutar solo si 2a no devuelve ningún resultado orgánico con un enlace http:// o https://:

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

(Misma plantilla, nombre de empresa sin comillas.)

2c. Perfil de LinkedIn (siempre)

Construir consulta (empresa sin comillas — coincide con nombres de empleador variantes en fragmentos):

site:linkedin.com/in {Primer Apellido} {hasta 5 palabras del rol} {Nombre de la Empresa}

Ejemplo:

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

Fase 3 — Extracción del modelo

Pase los resultados formateados de Serper a usted mismo (el modelo del agente) con esta instrucción del sistema:

Eres un asistente de investigación. El mensaje del usuario contiene resultados de búsqueda de Google
Serper.dev en secciones etiquetadas. NO tienes búsqueda web en vivo — usa solo los bloques
pegados.

Tarea: para UNA persona específica en UNA empresa, extrae:
- company_domain: nombre de host registrable solamente (sin ruta, sin www), o cadena vacía
- company_website: URL completa de https:// página de inicio si es compatible, o cadena vacía
- linkedin_url: https://linkedin.com/in/… para la persona nombrada en esta empresa, o cadena vacía
- confidence: high | medium | low
- note: explicación opcional de ambigüedad o lagunas

Reglas:
- Cada URL no vacía debe aparecer en los bloques de Serper (normalización menor de cadena de consulta está bien)
- El nombre en LinkedIn puede diferir de la entrada (apodo vs nombre legal) — coincidir en la misma persona + empleador
- Antes de aceptar `linkedin_url`, verifique la calidad de coincidencia:
  - Extraiga tokens de primer nombre + apellido de `Full name: {full_name}` (ignore la puntuación)
  - El resultado `/in/` elegido debe tener *ambos* tokens presentes en el `title` o `snippet` del resultado
  - Si ningún resultado `/in/` cumple con el requisito de token, devuelva `linkedin_url` como cadena vacía y establezca `confidence` en `low`
- El sitio público de la empresa puede usar un nombre de banner diferente al de la entrada — prefiera evidencia oficial
- Al resolver `company_domain`:
  - Prefiera `knowledgeGraph.website` cuando esté presente
  - Rechace agregadores/registros comunes (ejemplos: `naceweb.org`, `usnews.com`, `wikipedia.org`, `niche.com`, `facebook.com`, `instagram.com`, `twitter.com`)
  - Si `company_name` parece faltante o coincide estrechamente con el nombre de la persona, devuelva cadena vacía
- Nunca invente URLs o slugs

Responda SOLO con un único objeto JSON (sin fences de markdown):
{"company_domain":"","company_website":"","linkedin_url":"","confidence":"medium","note":""}

Use esta plantilla de mensaje de usuario:

### Persona objetivo
Nombre completo: {full_name}
Rol/título declarado: {stated_role}
Empresa (según lo proporcionado): {company_name}

### Resultados de búsqueda
{formatted_serper_sections}

### Tarea
Devuelva el objeto JSON descrito en la instrucción del sistema.

Luego analice su propia respuesta: elimine los fences de markdown, extraiga el objeto JSON.

Respaldo de cosecha de LinkedIn: si linkedin_url está vacío después de la extracción, escanee los resultados orgánicos sin procesar de Serper en busca de URLs /in/ donde el título contenga tanto el primer nombre como el token del apellido. Prefiera coincidencias ...

[truncado para traducción]

Skills relacionados