event-prospecting
browserbase/skills
Toma la URL de los ponentes de una conferencia o evento, extrae los nombres de las personas, filtra sus empresas según el perfil de cliente ideal (ICP) del usuario y analiza en profundidad únicamente a los ponentes de las empresas que se ajustan a dicho perfil. Genera un informe HTML centrado en las personas, con una justificación de «por qué contactar» para cada una de ellas.
...Expandir todoProspección en eventos
Introduce la URL de una conferencia → obtén una lista ordenada de personas con las que el representante comercial debería ponerse en contacto, con una justificación de «por qué contactar» para cada persona.
Requisitos: la variable de entorno BROWSERBASE_API_KEY y la CLI de browse instalada (npm install -g browse). Utiliza browse cloud... para las llamadas a la API y browse open / browse get markdown para las páginas de ponentes con mucho código JS.
Reglas de ruta: utiliza siempre la ruta literal completa en todos los comandos de Bash —NO ~ ni $HOME (ambos activan mensajes de confirmación de «sintaxis de expansión de shell»). Resuelve el directorio de inicio una sola vez y utilízalo en todas partes. Al crear mensajes para los subagentes, sustituye {SKILL_DIR} por la ruta literal completa (normalmente /Users/jay/skills/skills/event-prospecting).
Directorio de salida: toda la salida de la prospección de eventos se guarda en ~/Desktop/{event_slug}_prospects_{AAAA-MM-DD-HHMM}/. El resultado final es index.html (personas agrupadas por empresa, clasificadas según el ICP de la empresa), con companies.html y people.html (filtrables) como vistas alternativas, además de results.csv para la importación de contactos en frío.
IMPORTANTE — Restricciones de la herramienta (se aplica al agente principal Y a todos los subagentes):
- Todas las búsquedas en la web: utiliza
la búsqueda en la nube de Browse. NUNCA utilices WebSearch. - Toda extracción de contenido de páginas: utiliza
el nodo {SKILL_DIR}/scripts/extract_page.mjs ". Este script realiza la recuperación mediante" «browse cloud fetch --output», analiza el título, las etiquetas meta y el texto visible del cuerpo, y recurre automáticamente a«browse get markdown»cuando la recuperación falla o devuelve contenido escaso renderizado en JS. NUNCA crees manualmente una cadena de comandos«browse cloud fetch | sed». NUNCA utilices WebFetch. - Todos los resultados de la investigación: los subagentes deben escribir un archivo Markdown por empresa O por persona en
{OUTPUT_DIR}/companies/{slug}.mdo{OUTPUT_DIR}/people/{slug}.mdutilizando bash heredoc. NUNCA utilices la herramienta «Write» nipython3 -c. Consultareferences/example-research.mdpara ver ambos formatos de archivo. - Compilación del informe: utiliza
el comando node {SKILL_DIR}/scripts/compile_report.mjs {OUTPUT_DIR} --open. - Los subagentes deben utilizar ÚNICAMENTE la herramienta de Bash. No se permiten otras herramientas.
- LÍMITE MÁXIMO DE LLAMADAS: Triaje ICP = 1 llamada/empresa; investigación en profundidad = 5 llamadas/empresa; enriquecimiento de datos personales = 4 llamadas/persona. Consulta
references/workflow.mdpara conocer los detalles de aplicación.
CRÍTICO — Normas contra las «alucinaciones» (se aplican al agente principal Y a todos los subagentes):
- NUNCA deduzcas
la descripción del producto,el sectorola razón del cargode una persona a partir de las fuentes, el marco de trabajo, el sistema de diseño o la tipografía de un sitio web. Estos son aspectos estéticos y no dicen nada sobre lo que vende la empresa o lo que hace la persona. - NUNCA dejes que el propio ICP del usuario se filtre en la descripción de un destinatario. Si no sabes a qué se dedica el destinatario, escribe
«Desconocido»; no lo compares con el ICP. «product_description»DEBE citar o parafrasear una frase concreta de la salida de«extract_page.mjs». Si ninguno de los elementos TITLE/META/OG/HEADINGS/BODY ofrece una descripción del producto reconocible, escribe«Desconocido» —contenido de la página de inicio no accesible—y limita«icp_fit_score»a 3.El ganchode una persona DEBE citar o parafrasear un hallazgo específico de un resultadode búsqueda en la nube de navegación(título de un podcast, titular de un blog, repositorio de GitHub, resumen de una ponencia). Si no existe ninguna señal pública en los últimos 6 meses, recurre al contexto del evento (el título de su ponencia en dicho evento).
CRÍTICO — Minimizar las solicitudes de permiso:
- Los subagentes DEBEN agrupar TODAS las escrituras de archivos en una ÚNICA llamada a Bash utilizando heredocs encadenados. Una llamada a Bash = una solicitud de permiso.
- Agrupa TODAS las búsquedas y TODAS las recuperaciones en llamadas únicas de Bash utilizando el encadenamiento
&&.
Descripción general del proceso
Sigue estos 10 pasos en orden. No te saltes ningún paso ni cambies el orden.
- Configuración — directorio de salida + borrado completo
- Cargar perfil: leer
profiles/{user_slug}.json - Reconocimiento: detectar la plataforma de eventos
- Extracción de personas:
people.jsonl - Agrupar por empresa —
seed_companies.txt - Clasificación ICP: puntuación rápida a nivel de empresa (1 llamada por empresa)
- Filtrar — empresas con
icp_fit_score >= --icp-threshold - Investigación en profundidad — proceso completo «Planificar→Investigar→Sintetizar» sobre la adecuación al ICP
- Ampliar la lista de ponentes: preguntar al usuario si quiere solo los que encajan con el ICP (por defecto) o todos los ponentes
- Compilar informe — HTML + CSV, abrir en el navegador
El usuario activa la skill con una URL como /event-prospecting . Analiza EVENT_URL a partir de ese mensaje de activación. Valores por defecto: DEPTH=deep, ICP_THRESHOLD=6. El USER_SLUG (perfil ICP) se resuelve automáticamente en el paso 1 a partir de los archivos de perfil que existan localmente; no hay ningún perfil predeterminado integrado. NO pidas al usuario que confirme la URL: ya te la ha facilitado.
Paso 0: Configuración del directorio de salida
Obtén el directorio de salida a partir de la URL que te ha facilitado el usuario. NO codifiques ningún nombre de evento de forma fija.
# EVENT_URL procede del mensaje de invocación (lo que el usuario haya escrito después de `/event-prospecting`)
EVENT_SLUG=$(node -e 'const h = new URL(process.argv[1]).hostname.replace(/^www\./,""); console.log(h.split(".")[0])' "$EVENT_URL")
TIMESTAMP=$(date +%Y-%m-%d-%H%M)
OUTPUT_DIR=/Users/jay/Desktop/${EVENT_SLUG}_prospects_${TIMESTAMP}
mkdir -p "$OUTPUT_DIR/companies" "$OUTPUT_DIR/people"
Utiliza la ruta completa literal de inicio; nunca ~ ni $HOME. Pasa {OUTPUT_DIR} como la ruta completa literal a todas las solicitudes de los subagentes.
Paso 1: Cargar el perfil de usuario
El perfil define el ICP con respecto al cual se realiza la clasificación y la puntuación de investigación en profundidad del ICP. Cárgalo desde {SKILL_DIR}/profiles/{user_slug}.json (intercambiable entre todas las habilidades de GTM; tiene la misma estructura que company-research). example.json es una plantilla, no un perfil real; nunca lo utilices.
NO busques perfilesfuera de {SKILL_DIR}/profiles/; nunca accedas a los directorios de otras habilidades. Si se necesita un perfil en otro lugar, el usuario debe copiarlo explícitamente.
Orden de resolución:
- Si el usuario ha ejecutado la skill con
--user-company, utiliza ese slug. - De lo contrario, enumera
los archivos profiles/*.jsonexcluyendoexample.json. Si existe exactamente un perfil, utilízalo (e indica al usuario cuál es). Si hay varios, pregunta al usuario (mediante chat sencillo) cuál desea. - Si no existe ningún perfil, muestra un mensaje de error claro e indica al usuario que cree uno (copiando
profiles/example.jsonaprofiles/y rellenándolo, o ejecutando la habilidad «company-research», que crea uno automáticamente)..json
PROFILES=$(ls {SKILL_DIR}/profiles/*.json 2>/dev/null | xargs -n1 basename | sed 's/\.json$//' | grep -v '^example$')
COUNT=$(echo "$PROFILES" | grep -c .)
if [ -z "$USER_SLUG" ]; then
if [ "$COUNT" -eq 0 ]; then
echo "No se han encontrado perfiles en {SKILL_DIR}/profiles/. Copia el archivo profiles/example.json a profiles/.json y rellénalo, o ejecuta la habilidad «company-research» para crear uno."
exit 1
elif [ "$COUNT" -eq 1 ]; then
USER_SLUG=$PROFILES
echo "Se utiliza el único perfil disponible: ${USER_SLUG}"
else
echo "Se han encontrado varios perfiles:"
echo "$PROFILES" | sed 's/^/ - /'
echo "Vuelve a ejecutar con --user-company para seleccionar uno."
exit 1
fi
fi
test -f {SKILL_DIR}/profiles/${USER_SLUG}.json || {
echo "Perfil no encontrado: profiles/${USER_SLUG}.json"
exit 1
}
cat {SKILL_DIR}/profiles/${USER_SLUG}.json
El perfil contiene: company, product, icp_description, existing_customers. Estos datos se incorporan tal cual en cada solicitud de los subagentes posteriores.
Paso 2: Reconocimiento
Detectar la plataforma de eventos y la estrategia de extracción. Un comando:
node {SKILL_DIR}/scripts/recon.mjs {EVENT_URL} {OUTPUT_DIR}
Escribe el archivo {OUTPUT_DIR}/recon.json con la plataforma, la estrategia y (para Next.js) nextDataPaths. Consulta references/event-platforms.md para ver el catálogo de plataformas y la prioridad de detección.
Resultados esperados:
- Clase Stripe Sessions (Next.js):
platform: "next-data", 1-3 rutas - Sessionize:
plataforma: «sessionize» - Lu.ma / Eventbrite:
plataforma: «luma» | «eventbrite» - Cualquier otra cosa:
plataforma: «custom»,estrategia: «markdown»(solución alternativa con el máximo esfuerzo)
Paso 3: Extraer personas
node {SKILL_DIR}/scripts/extract_event.mjs {OUTPUT_DIR} --user-company {USER_SLUG}
Lee el archivo recon.json, lo envía al extractor específico de la plataforma y genera los archivos people.jsonl (un ponente por línea) y seed_companies.txt (empresas sin duplicados).
El indicador --user-company también elimina de la lista de ponentes a los propios empleados de la organización anfitriona (un evento organizado por Stripe elimina a los empleados de Stripe) y a los propios empleados del usuario, ya que no son clientes potenciales.
Comprueba que la salida sea correcta:
wc -l {OUTPUT_DIR}/people.jsonl {OUTPUT_DIR}/seed_companies.txt
head -3 {OUTPUT_DIR}/people.jsonl
Si people.jsonl está vacío o tiene menos de 10 líneas, significa que la herramienta de reconocimiento ha elegido una plataforma incorrecta; consulta references/event-platforms.md y vuelve a ejecutar la estrategia ajustada.
Paso 4: Agrupar por empresa
extract_event.mjs ya genera el archivo seed_companies.txt (una empresa por línea, sin duplicados y ordenado). Este paso es meramente informativo: comprueba que el recuento sea razonable antes de continuar:
wc -l {OUTPUT_DIR}/seed_companies.txt
Resultado esperado: aproximadamente entre 0,4 y 0,6 veces el número de ponentes (la mayoría de los eventos tienen una media de unos 2 ponentes por empresa; algunas empresas envían más de 5 y muchas envían solo 1).
Paso 5: Clasificación según el ICP
Proceso rápido: una llamada a la herramienta por empresa, sin investigación en profundidad. Asigna una puntuación a cada empresa de seed_companies.txt en función del ICP del usuario y escribe un breve esbozo de selección en companies/{slug}.md. Las empresas con icp_fit_score ≥ --icp-threshold (por defecto, 6) pasan a la investigación en profundidad del paso 7; el resto se quedan como esbozos de selección.
Patrón de distribución: dividir seed_companies.txt en lotes de ~10 y distribuir N subagentes en un ÚNICO lote de Agent (varias llamadas a la herramienta Agent en un solo mensaje). Cada subagente ejecuta el prompt de references/workflow.md → sección «ICP Triage». Límite máximo: 1 llamada a la herramienta por empresa (solo extract_page.mjs en la página de inicio), que se aplica mediante el patrón de comentario # browse call N/1.
# Crear archivos de lotes: cada línea del lote es «nombre|página-de-inicio-estimada|slug».
# extract_event.mjs solo emite NOMBRES de empresas (sin URL), por lo que creamos un slug y estimamos
# https://{slug-sin-espacios}.com como página de inicio canónica. El subagente de triaje
# puede escribir product_description: «Desconocido — contenido de la página de inicio inaccesible»
# y establecer la puntuación máxima en 3 si la URL estimada devuelve un error 404 — esa es la solución alternativa documentada en
# workflow.md (regla 3 de la indicación de triaje del ICP). Realizar una búsqueda real en la nube de navegación para
# descubrir la URL superaría el LÍMITE MÁXIMO DE UNA LLAMADA POR EMPRESA.
node -e '
const fs = require("fs");
const slugify = (s) => (s || "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
const seed = fs.readFileSync("{OUTPUT_DIR}/seed_companies.txt", "utf-8").split("\n").filter(Boolean);
const lines = seed.map(c => {
const slug = slugify(c);
const guessedHost = c.toLowerCase().replace(/[^a-z0-9]/g, "");
return `${c}|https://${guessedHost}.com|${slug}`;
});
fs.writeFileSync("{OUTPUT_DIR}/_seed_with_urls.txt", lines.join("\n") + "\n");
'
# Dividir en lotes de unas 10 empresas
split -l 10 {OUTPUT_DIR}/_seed_with_urls.txt {OUTPUT_DIR}/_batch_triage_
# Contar lotes → número de subagentes que enviar (máximo de 6 por mensaje; segunda oleada para el resto)
ls {OUTPUT_DIR}/_batch_triage_* | wc -l
A continuación, en un único mensaje, envía una llamada a un agente por lote (hasta 6 en paralelo; oleadas posteriores una vez que la primera haya finalizado). Cada agente recibe la indicación de references/workflow.md → «ICP Triage» con estas sustituciones antes de enviarla:
{SKILL_DIR}→ ruta literal completa de la habilidad (p. ej.,/Users/jay/skills/skills/event-prospecting){OUTPUT_DIR}→ ruta completa de salida{USER_COMPANY},{USER_PRODUCT},{ICP_DESCRIPTION}→ del perfil cargado{EVENT_NAME}→.titlederecon.json{COMPANY_LIST}→ contenido del archivo por lotes (p. ej.,cat {OUTPUT_DIR}/_batch_triage_aa){TOTAL}→ número de líneas en este lote (sustituir enla llamada # browse por N/{TOTAL})
Envío del agente (esquema, repetir por lote en un solo mensaje):
Agente(
descripción: «Lote de triaje ICP aa»,
mensaje de solicitud: ,
tipo de subagente: «uso general»
)
Agente(
descripción: «Lote de clasificación de ICP ab»,
mensaje de solicitud: ,
tipo de subagente: «uso general»
)
... hasta 6 por mensaje
Una vez que todos los subagentes hayan devuelto resultados, comprueba que cada empresa de seed_companies.txt tenga un archivo correspondiente en companies/{slug}.md:
ls {OUTPUT_DIR}/companies/*.md | wc -l
# Debería ser igual a `wc -l {OUTPUT_DIR}/seed_companies.txt`
Elimina los archivos por lotes: rm {OUTPUT_DIR}/_batch_triage_*.
Paso 6: Filtrar por umbral de ICP
Lee el frontmatter de cada archivo companies/*.md y conserva aquellos con icp_fit_score >= 6 (o el valor que tenga el parámetro --icp-threshold ). Escribe los slugs de las empresas seleccionadas en {OUTPUT_DIR}/icp_fits.txt:
THRESHOLD=6 # del parámetro --icp-threshold
for f in {OUTPUT_DIR}/companies/*.md; do
score=$(awk '/^icp_fit_score:/{print $2; exit}' "$f")
if [ -n "$score" ] && [ "$score" -ge "$THRESHOLD" ]; then
basename "$f" .md
fi
done > {OUTPUT_DIR}/icp_fits.txt
wc -l {OUTPUT_DIR}/icp_fits.txt
Resultado esperado: entre el 20 % y el 40 % de seed_companies.txt. Si la tasa de supervivencia es inferior al 10 %, es posible que el umbral sea demasiado alto o que la descripción del ICP sea demasiado restrictiva; mostrar una advertencia al usuario.
Paso 7: Investigación en profundidad
Plan completo → Investigación → Síntesis solo sobre las empresas que se ajustan al ICP. Límite máximo: 5 consultas de herramientas por empresa (extracto de la página de inicio + 2-3 búsquedas de subpreguntas + 1-2 recuperaciones complementarias). Los subagentes SOBRESCRIBEN el esbozo de clasificación existente companies/{slug}.md con la versión más completa de la investigación en profundidad (frontmatter triage_only: false).
Patrón de envío: dividir icp_fits.txt en lotes de ~5 (por defecto en modo profundo) y distribuir un agente por lote en un ÚNICO mensaje (hasta 6 agentes por mensaje). Cada agente recibe la indicación de references/workflow.md → «Investigación en profundidad» con estas sustituciones:
{SKILL_DIR},{OUTPUT_DIR},{USER_COMPANY},{USER_PRODUCT},{ICP_DESCRIPTION}{EVENT_NAME}(derecon.json.title),{EVENT_CONTEXT}(tema/tema, deducido manualmente a partir de la página de inicio del evento){COMPANY_LIST}→ contenido del archivo por lotes (cada línea:slug|sitio web)
# Crear pares {slug de empresa|sitio web} leyendo la información preliminar de cada esbozo de triaje
while read slug; do
website=$(awk '/^website:/{print $2; exit}' {OUTPUT_DIR}/companies/${slug}.md)
echo "${slug}|${website}"
done < {OUTPUT_DIR}/icp_fits.txt > {OUTPUT_DIR}/_deep_targets.txt
# Dividir en lotes de ~5 empresas (modo profundo)
split -l 5 {OUTPUT_DIR}/_deep_targets.txt {OUTPUT_DIR}/_batch_deep_
ls {OUTPUT_DIR}/_batch_deep_* | wc -l
Envío de agentes (esquema, repetir por lote en un solo mensaje):
Agente(
descripción: «Lote de investigación en profundidad aa»,
prompt: ,
tipo_de_subagente: «uso general»
)
Agente(
descripción: "Lote de investigación en profundidad ab",
prompt: ,
tipo_de_subagente: "uso general"
)
... hasta 6 por mensaje; segunda oleada tras el retorno de la primera
Una vez que todos los subagentes hayan devuelto un resultado, comprueba que los archivos de investigación en profundidad existen y que tienen triage_only: false:
grep -l "triage_only: false" {OUTPUT_DIR}/companies/*.md | wc -l
# Debería dar como resultado wc -l icp_fits.txt
Paso 8: Enriquecer a los ponentes
Por persona: recopilar la URL de LinkedIn, la actividad reciente (podcast / blog / charla / GitHub / X) y escribir people/{slug}.md. Límite máximo: 4 llamadas a herramientas por persona, tres vías:
búsqueda en la nube «{nombre} {empresa} linkedin»(siempre)búsqueda en la nube «{nombre} podcast O charla O blog 2026»(profundidad+)búsqueda en la nube «{nombre} github»(más profunda)búsqueda en la nube «{nombre} site:x.com O site:twitter.com»(más profunda, en la medida de lo posible)
Modo rápido: omite el paso 8 por completo. Modo profundo: vías 1-2. Modo más profundo: vías 1-4.
Paso 8a — Preguntar al usuario: alcance del enriquecimiento
Antes de enviar la solicitud, calcula los recuentos de los dos candidatos y pide al usuario que elija. El valor por defecto es solo ajuste ICP (más rápido, más económico, lo que la mayoría de los usuarios quieren); el enriquecimiento de cada hablante es opcional, ya que el coste varía linealmente con el número de personas enriquecidas.
TOTAL=$(wc -l < {OUTPUT_DIR}/people.jsonl)
ICP_FITS=$(node -e '
const fs = require("fs");
const fits = new Set(fs.readFileSync("{OUTPUT_DIR}/icp_fits.txt", "utf-8").split("\n").filter(Boolean));
const slug2name = {};
for (const slug of fits) {
const md = fs.readFileSync(`{OUTPUT_DIR}/companies/${slug}.md`, "utf-8");
const m = md.match(/^company_name:\s*(.+)$/m);
if (m) slug2name[slug] = m[1].trim();
}
const want = new Set(Object.values(slug2name).map(s => s.toLowerCase()));
const ppl = fs.readFileSync("{OUTPUT_DIR}/people.jsonl","utf-8").split("\n").filter(Boolean).map(JSON.parse);
console.log(ppl.filter(p => p.company && want.has(p.company.toLowerCase())).length);
')
# Carriles por persona: 2 (profundidad) o 4 (más profunda) — coincide con {DEPTH}
LANES=2 # o 4 para mayor profundidad
echo "El ICP se ajusta a: ${ICP_FITS} ponentes × ${LANES} = $((ICP_FITS * LANES)) llamadas"
echo "Total: ${TOTAL} ponentes × ${LANES} = $((TOTAL * LANES)) llamadas"
A continuación, pregunta mediante AskUserQuestion: una elección clara de dos opciones con el coste cuantificado de cada una:
AskUserQuestion(questions: [
{
question: "¿Qué ponentes se enriquecen?",
header: "Ámbito de enriquecimiento",
multiSelect: false,
options: [
{ label: "Solo ICP FITS", description: "${ICP_FITS} altavoces, ~$((ICP_FITS * LANES)) llamadas (recomendado)" },
{ label: "Todos los altavoces", description: "${TOTAL} altavoces, ~$((TOTAL * LANES)) llamadas" }
]
}
])
Guarda el ámbito elegido como ENRICH_SCOPE=icp_fits o ENRICH_SCOPE=all. Si el usuario selecciona «Todos los hablantes» y TOTAL × LANES > 600, muestra una advertencia y vuelve a preguntar: se trata de una ejecución de más de 10 minutos con cientos de llamadas a la herramienta.
Paso 8b — Filtrar y procesar por lotes
# Crea _people_to_enrich.jsonl en función de ENRICH_SCOPE
if [ "$ENRICH_SCOPE" = "all" ]; then
cp {OUTPUT_DIR}/people.jsonl {OUTPUT_DIR}/_people_to_enrich.jsonl
else
node -e '
const fs = require("fs");
const fits = new Set(fs.readFileSync("{OUTPUT_DIR}/icp_fits.txt", "utf-8").split("\n").filter(Boolean));
const slug2name = {};
for (const slug of fits) {
const md = fs.readFileSync(`{OUTPUT_DIR}/companies/${slug}.md`, "utf-8");
const m = md.match(/^company_name:\s*(.+)$/m);
if (m) slug2name[slug] = m[1].trim();
}
const wantNames = new Set(Object.values(slug2name).map(s => s.toLowerCase()));
const lines = fs.readFileSync("{OUTPUT_DIR}/people.jsonl", "utf-8").split("\n").filter(Boolean);
const keep = lines.filter(l => {
const p = JSON.parse(l);
return p.company && wantNames.has(p.company.toLowerCase());
});
fs.writeFileSync("{OUTPUT_DIR}/_people_to_enrich.jsonl", keep.join("\n") + "\n");
console.error(`Enriqueciendo ${keep.length} de ${lines.length} ponentes`);
'
fi
# Dividir en lotes de ~5 personas
split -l 5 {OUTPUT_DIR}/_people_to_enrich.jsonl {OUTPUT_DIR}/_batch_people_
A continuación, en un único mensaje, envía una llamada de agente por lote (hasta 6 por mensaje) con la indicación de references/workflow.md → «Enriquecimiento de personas». La indicación de cada subagente debe incluir:
{SKILL_DIR},{OUTPUT_DIR},{DEPTH}(deep|deeper){USER_COMPANY},{USER_PRODUCT},{ICP_DESCRIPTION}{EVENT_NAME}(derecon.json.title){LANES}→2para el modo «deep»,4para el modo «deeper» (se sustituye enla llamada #browse N/{LANES}){PEOPLE_BATCH}→ contenido de_batch_people_aa(cada línea es un registro JSON depeople.jsonl)
Envío de agente (esquema, repetir por lote en un solo mensaje):
Agente(
descripción: «Lote de enriquecimiento de personas aa»,
mensaje: ,
tipo_de_subagente: «uso general»
)
Agente(
descripción: «Lote de enriquecimiento de personas ab»,
solicitud: ,
tipo_de_subagente: «uso general»
)
... hasta 6 por mensaje
Una vez que todos los subagentes hayan devuelto un resultado, comprueba que los archivos de personas existen:
ls {OUTPUT_DIR}/people/*.md | wc -l
# Debería ser igual a wc -l _people_to_enrich.jsonl
Paso 9: Compilar el informe
Genera el índice HTML agrupado por empresa, las vistas alternativas y el CSV con un solo comando:
node {SKILL_DIR}/scripts/compile_report.mjs {OUTPUT_DIR} --open
Esto genera:
{OUTPUT_DIR}/index.html— personas agrupadas por empresa, ordenadas según la puntuación ICP de la empresa (se abre en el navegador){OUTPUT_DIR}/people.html— lista de ponentes filtrable (vista alternativa){OUTPUT_DIR}/companies.html: tabla de empresas clasificadas según el ICP con los asistentes{OUTPUT_DIR}/results.csv— hoja de cálculo lista para llamadas en frío
A continuación, presenta un resumen en el chat:
## Prospección del evento completada — {Nombre del evento}
- **Total de ponentes extraídos**: {número}
- **Empresas únicas**: {número}
- **Empresas que se ajustan al ICP (puntuación ≥ {umbral})**: {número}
- **Ponentes con datos enriquecidos**: {número}
- **Distribución de puntuaciones** (empresas):
- Coincidencia alta (8-10): {número}
- Coincidencia parcial (5-7): {número}
- Coincidencia débil (1-4): {número}
- **Informe abierto en el navegador**: {OUTPUT_DIR}/index.html
Mostrar las 5 primeras fichas de personas en una tabla Markdown ordenada por puntuación ICP de la empresa y, a continuación, ofrecer la opción de:
- Ajustar
--icp-thresholdy volver a ejecutar los pasos 6-9 - Exportar el CSV a un CRM
---
name: event-prospecting
description: Takes a conference or event speakers URL, extracts the people, filters their companies against the user's ICP, and deep-researches only the speakers at ICP-fit companies. Outputs a person-first HTML report with a 'why reach out' rationale per person.
license: MIT
---
# Event Prospecting
Take a conference URL → get a ranked list of people the AE should talk to, with a "why reach out" rationale per person.
**Required**: `BROWSERBASE_API_KEY` env var and the `browse` CLI installed (`npm install -g browse`). Use `browse cloud ...` for API calls and `browse open` / `browse get markdown` for JS-heavy speaker pages.
**Path rules**: Always use the full literal path in all Bash commands — NOT `~` or `$HOME` (both trigger "shell expansion syntax" approval prompts). Resolve the home directory once and use it everywhere. When constructing subagent prompts, replace `{SKILL_DIR}` with the full literal path (typically `/Users/jay/skills/skills/event-prospecting`).
**Output directory**: All event prospecting output goes to `~/Desktop/{event_slug}_prospects_{YYYY-MM-DD-HHMM}/`. Final deliverable is `index.html` (people grouped by company, ranked by company ICP), with `companies.html` and `people.html` (filterable) as alternate views, plus `results.csv` for cold-outbound import.
**CRITICAL — Tool restrictions (applies to main agent AND all subagents)**:
- All web searches: use `browse cloud search`. NEVER use WebSearch.
- All page content extraction: use `node {SKILL_DIR}/scripts/extract_page.mjs "<url>"`. This script fetches via `browse cloud fetch --output`, parses title + meta tags + visible body text, and automatically falls back to `browse get markdown` when fetch fails or returns thin JS-rendered content. NEVER hand-roll a `browse cloud fetch | sed` pipeline. NEVER use WebFetch.
- All research output: subagents write **one markdown file per company OR per person** to `{OUTPUT_DIR}/companies/{slug}.md` or `{OUTPUT_DIR}/people/{slug}.md` using bash heredoc. NEVER use the Write tool or `python3 -c`. See `references/example-research.md` for both file formats.
- Report compilation: use `node {SKILL_DIR}/scripts/compile_report.mjs {OUTPUT_DIR} --open`.
- **Subagents must use ONLY the Bash tool. No other tools allowed.**
- **HARD TOOL-CALL CAPS**: ICP triage = 1 call/company; deep research = 5 calls/company; person enrichment = 4 calls/person. See `references/workflow.md` for enforcement detail.
**CRITICAL — Anti-hallucination rules (applies to main agent AND all subagents)**:
- NEVER infer `product_description`, `industry`, or a person's `role_reason` from a site's fonts, framework, design system, or typography. These are cosmetic and say nothing about what the company sells or what the person does.
- NEVER let the user's own ICP leak into a target's description. If you don't know what the target does, write `Unknown` — do not pattern-match them onto the ICP.
- `product_description` MUST quote or paraphrase a specific phrase from `extract_page.mjs` output. If none of TITLE/META/OG/HEADINGS/BODY yield a recognizable product statement, write `Unknown — homepage content not accessible` and cap `icp_fit_score` at 3.
- A person's `hook` MUST quote or paraphrase a specific finding from a `browse cloud search` result (podcast title, blog headline, GitHub repo, talk abstract). If no public signal exists in the last 6 months, fall back to event-context (their talk title at this event).
**CRITICAL — Minimize permission prompts**:
- Subagents MUST batch ALL file writes into a SINGLE Bash call using chained heredocs. One Bash call = one permission prompt.
- Batch ALL searches and ALL fetches into single Bash calls using `&&` chaining.
## Pipeline Overview
Follow these 10 steps in order. Do not skip steps or reorder.
0. **Setup** — output dir + clean slate
1. **Load profile** — read `profiles/{user_slug}.json`
2. **Recon** — detect event platform
3. **Extract people** — `people.jsonl`
4. **Group by company** — `seed_companies.txt`
5. **ICP triage** — fast company-level scoring (1 call/company)
6. **Filter** — companies with `icp_fit_score >= --icp-threshold`
7. **Deep research** — full Plan→Research→Synthesize on ICP fits
8. **Enrich speakers** — ask user: ICP-fit only (default) or all speakers
9. **Compile report** — HTML + CSV, open in browser
The user invokes the skill with a URL like `/event-prospecting <URL>`. Parse `EVENT_URL` from that invocation message. Defaults: `DEPTH=deep`, `ICP_THRESHOLD=6`. The `USER_SLUG` (ICP profile) is auto-resolved in Step 1 from whatever profile files exist locally — there is no built-in default profile. Do NOT ask the user to confirm the URL — they already gave you it.
---
## Step 0: Setup Output Directory
Derive the output directory from the URL the user gave you. Do NOT hardcode any event name.
```bash
# EVENT_URL came from the invocation message (whatever the user typed after `/event-prospecting`)
EVENT_SLUG=$(node -e 'const h = new URL(process.argv[1]).hostname.replace(/^www\./,""); console.log(h.split(".")[0])' "$EVENT_URL")
TIMESTAMP=$(date +%Y-%m-%d-%H%M)
OUTPUT_DIR=/Users/jay/Desktop/${EVENT_SLUG}_prospects_${TIMESTAMP}
mkdir -p "$OUTPUT_DIR/companies" "$OUTPUT_DIR/people"
```
Use the full literal home path — never `~` or `$HOME`. Pass `{OUTPUT_DIR}` as the full literal path to all subagent prompts.
## Step 1: Load User Profile
The profile defines the ICP that ICP triage and deep research score against. Load from `{SKILL_DIR}/profiles/{user_slug}.json` (interchangeable across all GTM skills — same shape as company-research). `example.json` is a template, not a real profile — never use it.
**DO NOT look outside `{SKILL_DIR}/profiles/`** for profiles — never reach into other skills' directories. If a profile is needed elsewhere, the user copies it explicitly.
**Resolution order**:
1. If the user invoked with `--user-company <slug>`, use that slug.
2. Else, list `profiles/*.json` excluding `example.json`. If exactly one profile exists, use it (and tell the user which one). If multiple exist, ask the user (plain chat) which one.
3. If zero profiles exist, **fail loudly** and instruct the user to create one (copy `profiles/example.json` to `profiles/<your_slug>.json` and fill it in, or run the company-research skill which builds one automatically).
```bash
PROFILES=$(ls {SKILL_DIR}/profiles/*.json 2>/dev/null | xargs -n1 basename | sed 's/\.json$//' | grep -v '^example$')
COUNT=$(echo "$PROFILES" | grep -c .)
if [ -z "$USER_SLUG" ]; then
if [ "$COUNT" -eq 0 ]; then
echo "No profiles found in {SKILL_DIR}/profiles/. Copy profiles/example.json to profiles/<your_slug>.json and fill it in, or run the company-research skill to build one."
exit 1
elif [ "$COUNT" -eq 1 ]; then
USER_SLUG=$PROFILES
echo "Using the only profile available: ${USER_SLUG}"
else
echo "Multiple profiles found:"
echo "$PROFILES" | sed 's/^/ - /'
echo "Re-invoke with --user-company <slug> to pick one."
exit 1
fi
fi
test -f {SKILL_DIR}/profiles/${USER_SLUG}.json || {
echo "Profile not found: profiles/${USER_SLUG}.json"
exit 1
}
cat {SKILL_DIR}/profiles/${USER_SLUG}.json
```
The profile yields: `company`, `product`, `icp_description`, `existing_customers`. These get embedded verbatim in every subagent prompt downstream.
## Step 2: Recon
Detect the event platform and extraction strategy. One command:
```bash
node {SKILL_DIR}/scripts/recon.mjs {EVENT_URL} {OUTPUT_DIR}
```
Writes `{OUTPUT_DIR}/recon.json` with `platform`, `strategy`, and (for Next.js) `nextDataPaths`. See `references/event-platforms.md` for the platform catalog and detection priority.
Expected outcomes:
- Stripe Sessions class (Next.js): `platform: "next-data"`, 1-3 paths
- Sessionize: `platform: "sessionize"`
- Lu.ma / Eventbrite: `platform: "luma" | "eventbrite"`
- Anything else: `platform: "custom"`, `strategy: "markdown"` (best-effort fallback)
## Step 3: Extract People
```bash
node {SKILL_DIR}/scripts/extract_event.mjs {OUTPUT_DIR} --user-company {USER_SLUG}
```
Reads `recon.json`, dispatches to the platform-specific extractor, writes `people.jsonl` (one speaker per line) and `seed_companies.txt` (deduped companies).
The `--user-company` flag also drops the host-org's own employees (a Stripe-hosted event drops Stripe employees) and the user's own employees from the speaker list — those aren't prospects.
Sanity-check the output:
```bash
wc -l {OUTPUT_DIR}/people.jsonl {OUTPUT_DIR}/seed_companies.txt
head -3 {OUTPUT_DIR}/people.jsonl
```
If `people.jsonl` is empty or under ~10 lines, recon picked the wrong platform — see `references/event-platforms.md` and re-run with adjusted strategy.
## Step 4: Group by Company
`extract_event.mjs` emits `seed_companies.txt` already (one company per line, deduped, sorted). This step is informational — verify the count looks reasonable before fanning out:
```bash
wc -l {OUTPUT_DIR}/seed_companies.txt
```
Expected: roughly 0.4-0.6× the speaker count (most events have ~2 speakers per company on average, some companies send 5+, many send 1).
## Step 5: ICP Triage
**Fast pass — one tool call per company, no deep research.** Score every company in `seed_companies.txt` against the user's ICP and write a thin triage stub to `companies/{slug}.md`. Companies with `icp_fit_score >= --icp-threshold` (default 6) advance to Step 7's deep research; the rest stay as triage stubs.
**Dispatch pattern**: split `seed_companies.txt` into batches of ~10 and fan out N subagents in a SINGLE Agent batch (multiple Agent tool calls in one message). Each subagent runs the prompt from `references/workflow.md` → "ICP Triage" section. Hard cap: **1 tool call per company** (just `extract_page.mjs` on the homepage), enforced via the `# browse call N/1` comment pattern.
```bash
# Build batch files: each batch line is "name|guessed_homepage|slug".
# extract_event.mjs only emits company NAMES (no URLs), so we slugify and guess
# https://{slug-without-spaces}.com as the canonical homepage. The triage subagent
# is allowed to write product_description: "Unknown — homepage content not accessible"
# and cap score at 3 if the guessed URL 404s — that's the documented fallback in
# workflow.md (rule 3 of the ICP Triage prompt). Burning a real browse cloud search to
# discover the URL would bust the 1-call-per-company HARD CAP.
node -e '
const fs = require("fs");
const slugify = (s) => (s || "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
const seed = fs.readFileSync("{OUTPUT_DIR}/seed_companies.txt", "utf-8").split("\n").filter(Boolean);
const lines = seed.map(c => {
const slug = slugify(c);
const guessedHost = c.toLowerCase().replace(/[^a-z0-9]/g, "");
return `${c}|https://${guessedHost}.com|${slug}`;
});
fs.writeFileSync("{OUTPUT_DIR}/_seed_with_urls.txt", lines.join("\n") + "\n");
'
# Split into ~10-company batches
split -l 10 {OUTPUT_DIR}/_seed_with_urls.txt {OUTPUT_DIR}/_batch_triage_
# Count batches → number of subagents to dispatch (cap at 6 per message; second wave for the rest)
ls {OUTPUT_DIR}/_batch_triage_* | wc -l
```
Then in a single message, dispatch one Agent call per batch (up to 6 in parallel; subsequent waves after the first returns). Each Agent gets the prompt from `references/workflow.md` → "ICP Triage" with these substitutions before sending:
- `{SKILL_DIR}` → full literal skill path (e.g. `/Users/jay/skills/skills/event-prospecting`)
- `{OUTPUT_DIR}` → full literal output path
- `{USER_COMPANY}`, `{USER_PRODUCT}`, `{ICP_DESCRIPTION}` → from the loaded profile
- `{EVENT_NAME}` → `recon.json` `.title`
- `{COMPANY_LIST}` → contents of the batch file (e.g. `cat {OUTPUT_DIR}/_batch_triage_aa`)
- `{TOTAL}` → number of lines in this batch (substitute into `# browse call N/{TOTAL}`)
**Agent dispatch (skeleton, repeat per batch in one message)**:
```
Agent(
description: "ICP triage batch aa",
prompt: <ICP Triage prompt from workflow.md with all placeholders substituted>,
subagent_type: "general-purpose"
)
Agent(
description: "ICP triage batch ab",
prompt: <same prompt template, COMPANY_LIST swapped to batch ab>,
subagent_type: "general-purpose"
)
... up to 6 per message
```
After all subagents return, verify every company in `seed_companies.txt` has a corresponding `companies/{slug}.md`:
```bash
ls {OUTPUT_DIR}/companies/*.md | wc -l
# Should equal `wc -l {OUTPUT_DIR}/seed_companies.txt`
```
Clean up the batch files: `rm {OUTPUT_DIR}/_batch_triage_*`.
## Step 6: Filter by ICP Threshold
Read each `companies/*.md` frontmatter, keep those with `icp_fit_score >= 6` (or whatever `--icp-threshold` is). Write the surviving company slugs to `{OUTPUT_DIR}/icp_fits.txt`:
```bash
THRESHOLD=6 # from --icp-threshold flag
for f in {OUTPUT_DIR}/companies/*.md; do
score=$(awk '/^icp_fit_score:/{print $2; exit}' "$f")
if [ -n "$score" ] && [ "$score" -ge "$THRESHOLD" ]; then
basename "$f" .md
fi
done > {OUTPUT_DIR}/icp_fits.txt
wc -l {OUTPUT_DIR}/icp_fits.txt
```
Expected: 20-40% of `seed_companies.txt`. If the survival rate is < 10%, the threshold may be too high or the ICP description too narrow — surface a warning to the user.
## Step 7: Deep Research
Full Plan→Research→Synthesize on ICP-fit companies only. Hard cap: **5 tool calls per company** (homepage extract + 2-3 sub-question searches + 1-2 supplementary fetches). Subagents OVERWRITE the existing `companies/{slug}.md` triage stub with the richer deep-research version (frontmatter `triage_only: false`).
**Dispatch pattern**: split `icp_fits.txt` into batches of ~5 (deep mode default) and fan out one Agent per batch in a SINGLE message (up to 6 Agents per message). Each Agent gets the prompt from `references/workflow.md` → "Deep Research" with these substitutions:
- `{SKILL_DIR}`, `{OUTPUT_DIR}`, `{USER_COMPANY}`, `{USER_PRODUCT}`, `{ICP_DESCRIPTION}`
- `{EVENT_NAME}` (from `recon.json` `.title`), `{EVENT_CONTEXT}` (track / topic, manually inferred from the event homepage)
- `{COMPANY_LIST}` → contents of the batch file (each line `slug|website`)
```bash
# Build {company-slug|website} pairs by reading frontmatter from each triage stub
while read slug; do
website=$(awk '/^website:/{print $2; exit}' {OUTPUT_DIR}/companies/${slug}.md)
echo "${slug}|${website}"
done < {OUTPUT_DIR}/icp_fits.txt > {OUTPUT_DIR}/_deep_targets.txt
# Split into ~5-company batches (deep mode)
split -l 5 {OUTPUT_DIR}/_deep_targets.txt {OUTPUT_DIR}/_batch_deep_
ls {OUTPUT_DIR}/_batch_deep_* | wc -l
```
**Agent dispatch (skeleton, repeat per batch in one message)**:
```
Agent(
description: "Deep research batch aa",
prompt: <Deep Research prompt from workflow.md with all placeholders substituted; COMPANY_LIST = cat _batch_deep_aa>,
subagent_type: "general-purpose"
)
Agent(
description: "Deep research batch ab",
prompt: <same template, COMPANY_LIST = cat _batch_deep_ab>,
subagent_type: "general-purpose"
)
... up to 6 per message; second wave after the first returns
```
After all subagents return, verify the deep-research files exist and have `triage_only: false`:
```bash
grep -l "triage_only: false" {OUTPUT_DIR}/companies/*.md | wc -l
# Should equal wc -l icp_fits.txt
```
## Step 8: Enrich Speakers
Per person: harvest LinkedIn URL, recent activity (podcast / blog / talk / GitHub / X), and write `people/{slug}.md`. Hard cap: **4 tool calls per person**, three lanes:
1. `browse cloud search "{name} {company} linkedin"` (always)
2. `browse cloud search "{name} podcast OR talk OR blog 2026"` (deep+)
3. `browse cloud search "{name} github"` (deeper)
4. `browse cloud search "{name} site:x.com OR site:twitter.com"` (deeper, best-effort)
Quick mode: skip Step 8 entirely. Deep mode: lanes 1-2. Deeper mode: lanes 1-4.
### Step 8a — Ask the user: scope of enrichment
Before dispatching, compute the two candidate counts and ask the user to choose. The default is **ICP-fit only** (faster, cheaper, what most users want); enriching every speaker is opt-in because cost scales linearly with people enriched.
```bash
TOTAL=$(wc -l < {OUTPUT_DIR}/people.jsonl)
ICP_FITS=$(node -e '
const fs = require("fs");
const fits = new Set(fs.readFileSync("{OUTPUT_DIR}/icp_fits.txt", "utf-8").split("\n").filter(Boolean));
const slug2name = {};
for (const slug of fits) {
const md = fs.readFileSync(`{OUTPUT_DIR}/companies/${slug}.md`, "utf-8");
const m = md.match(/^company_name:\s*(.+)$/m);
if (m) slug2name[slug] = m[1].trim();
}
const want = new Set(Object.values(slug2name).map(s => s.toLowerCase()));
const ppl = fs.readFileSync("{OUTPUT_DIR}/people.jsonl","utf-8").split("\n").filter(Boolean).map(JSON.parse);
console.log(ppl.filter(p => p.company && want.has(p.company.toLowerCase())).length);
')
# Lanes per person: 2 (deep) or 4 (deeper) — match {DEPTH}
LANES=2 # or 4 for deeper
echo "ICP fits: ${ICP_FITS} speakers × ${LANES} = $((ICP_FITS * LANES)) calls"
echo "All: ${TOTAL} speakers × ${LANES} = $((TOTAL * LANES)) calls"
```
Then ask via `AskUserQuestion` — clean two-option choice with the quantified cost on each:
```
AskUserQuestion(questions: [
{
question: "Enrich which speakers?",
header: "Enrichment scope",
multiSelect: false,
options: [
{ label: "ICP fits only", description: "${ICP_FITS} speakers, ~$((ICP_FITS * LANES)) calls (recommended)" },
{ label: "All speakers", description: "${TOTAL} speakers, ~$((TOTAL * LANES)) calls" }
]
}
])
```
Save the chosen scope as `ENRICH_SCOPE=icp_fits` or `ENRICH_SCOPE=all`. If the user picks "All speakers" and `TOTAL × LANES > 600`, print a warning and ask once more — that's a 10+ minute run with hundreds of tool calls.
### Step 8b — Filter and batch
```bash
# Build _people_to_enrich.jsonl based on ENRICH_SCOPE
if [ "$ENRICH_SCOPE" = "all" ]; then
cp {OUTPUT_DIR}/people.jsonl {OUTPUT_DIR}/_people_to_enrich.jsonl
else
node -e '
const fs = require("fs");
const fits = new Set(fs.readFileSync("{OUTPUT_DIR}/icp_fits.txt", "utf-8").split("\n").filter(Boolean));
const slug2name = {};
for (const slug of fits) {
const md = fs.readFileSync(`{OUTPUT_DIR}/companies/${slug}.md`, "utf-8");
const m = md.match(/^company_name:\s*(.+)$/m);
if (m) slug2name[slug] = m[1].trim();
}
const wantNames = new Set(Object.values(slug2name).map(s => s.toLowerCase()));
const lines = fs.readFileSync("{OUTPUT_DIR}/people.jsonl", "utf-8").split("\n").filter(Boolean);
const keep = lines.filter(l => {
const p = JSON.parse(l);
return p.company && wantNames.has(p.company.toLowerCase());
});
fs.writeFileSync("{OUTPUT_DIR}/_people_to_enrich.jsonl", keep.join("\n") + "\n");
console.error(`Enriching ${keep.length} of ${lines.length} speakers`);
'
fi
# Split into ~5-person batches
split -l 5 {OUTPUT_DIR}/_people_to_enrich.jsonl {OUTPUT_DIR}/_batch_people_
```
Then in a single message, dispatch one Agent call per batch (up to 6 per message) with the prompt from `references/workflow.md` → "Person Enrichment". Each subagent's prompt should include:
- `{SKILL_DIR}`, `{OUTPUT_DIR}`, `{DEPTH}` (`deep` | `deeper`)
- `{USER_COMPANY}`, `{USER_PRODUCT}`, `{ICP_DESCRIPTION}`
- `{EVENT_NAME}` (from `recon.json` `.title`)
- `{LANES}` → `2` for deep mode, `4` for deeper mode (substituted into `# browse call N/{LANES}`)
- `{PEOPLE_BATCH}` → contents of `_batch_people_aa` (each line a JSON record from `people.jsonl`)
**Agent dispatch (skeleton, repeat per batch in one message)**:
```
Agent(
description: "Person enrichment batch aa",
prompt: <Person Enrichment prompt from workflow.md with all placeholders substituted; PEOPLE_BATCH = cat _batch_people_aa>,
subagent_type: "general-purpose"
)
Agent(
description: "Person enrichment batch ab",
prompt: <same template, PEOPLE_BATCH = cat _batch_people_ab>,
subagent_type: "general-purpose"
)
... up to 6 per message
```
After all subagents return, verify the people files exist:
```bash
ls {OUTPUT_DIR}/people/*.md | wc -l
# Should equal wc -l _people_to_enrich.jsonl
```
## Step 9: Compile Report
Generate the company-grouped HTML index, alternate views, and CSV in one command:
```bash
node {SKILL_DIR}/scripts/compile_report.mjs {OUTPUT_DIR} --open
```
This generates:
- `{OUTPUT_DIR}/index.html` — people grouped by company, ranked by company ICP score (opens in browser)
- `{OUTPUT_DIR}/people.html` — filterable speaker list (alternate view)
- `{OUTPUT_DIR}/companies.html` — ICP-ranked company table with attendees
- `{OUTPUT_DIR}/results.csv` — cold-outbound-ready spreadsheet
Then present a summary in chat:
```
## Event Prospecting Complete — {Event Name}
- **Total speakers extracted**: {count}
- **Unique companies**: {count}
- **ICP fits (score ≥ {threshold})**: {count}
- **Speakers enriched**: {count}
- **Score distribution** (companies):
- Strong fit (8-10): {count}
- Partial fit (5-7): {count}
- Weak fit (1-4): {count}
- **Report opened in browser**: {OUTPUT_DIR}/index.html
```
Show the **top 5 people cards** as a markdown table sorted by company ICP score, then offer to:
- Adjust `--icp-threshold` and re-run Steps 6-9
- Export the CSV to a CRM
Todos los archivos
14 archivosInstalar event-prospecting
Descarga y descomprime los archivos de habilidades en tu directorio .claude/skills/.
Descargar ZIPClona el repositorio y copia los archivos de la habilidad a tu proyecto.
git clone https://github.com/browserbase/skills/tree/main/skills/event-prospecting # Copy SKILL.md to your .claude/skills/ directory
Copiar





Hogar
