Módulo 2: Agentic Research con Explore Subagent

Búsqueda Semántica vs Grep — Encontrar por Significado

Búsqueda Semántica vs Grep — Encontrar por Significado

Descripción de la cápsula

Hasta ahora has usado Explore como herramienta de investigación read-only. Pero hay una capacidad que lo separa radicalmente de cualquier herramienta de búsqueda tradicional: la búsqueda semántica. Mientras grep busca texto exacto, Explore entiende significado. Y esa diferencia cambia completamente cómo encuentras código en un codebase.

En esta cápsula vas a experimentar la diferencia de primera mano. Vas a buscar lo mismo con grep y con Explore, comparar resultados, y entender cuándo usar cada uno. No se trata de reemplazar grep — se trata de tener dos herramientas complementarias y saber cuándo cada una es superior.

La conexión con el proyecto es directa: en la cápsula 05 vas a responder preguntas sobre un codebase usando Explore. Muchas de esas preguntas requieren búsqueda semántica — "¿dónde se validan los inputs?" no es algo que grep resuelva bien. Esta cápsula te da la habilidad de encontrar código por lo que hace, no solo por cómo se llama.


El Problema con la Búsqueda por Texto

Por qué grep no es suficiente

grep es una herramienta extraordinaria. Lleva décadas siendo el estándar para buscar texto en archivos. Pero tiene una limitación fundamental: busca strings, no conceptos.

# Buscas dónde se validan los inputs del usuario
grep -r "validate" src/

# Resultados:
# src/utils/helpers.py:    # validate email format
# src/models/user.py:      def validate_name(self):
# src/tests/test_validation.py: class TestValidate:

Encontraste 3 resultados. Pero ¿y si la validación real está en funciones que se llaman check_params, sanitize_input, ensure_valid, o verify_data? grep no las encuentra porque busca la palabra "validate", no el concepto de validación.

El gap entre texto y significado

# Estas funciones TODAS hacen validación de inputs
# Pero ninguna contiene la palabra "validate"

def check_params(request_data: dict) -> bool:
    """Verifica que los parámetros requeridos estén presentes."""
    required = ["name", "email", "age"]
    return all(key in request_data for key in required)

def sanitize_input(raw_text: str) -> str:
    """Limpia texto de caracteres peligrosos."""
    import html
    return html.escape(raw_text.strip())

def ensure_valid_age(age: int) -> int:
    """Confirma que la edad está en rango razonable."""
    if not 0 < age < 150:
        raise ValueError(f"Edad fuera de rango: {age}")
    return age

def verify_email_format(email: str) -> bool:
    """Comprueba que el email tiene formato correcto."""
    import re
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return bool(re.match(pattern, email))

Si buscas grep -r "validate", ninguna de estas funciones aparece. Pero todas son exactamente lo que necesitas. Este es el gap entre búsqueda por texto y búsqueda por significado.


Búsqueda Semántica con Explore

Cómo funciona

Cuando le pides a Explore algo como "¿dónde se validan los inputs del usuario?", no busca la palabra "validar." Entiende que estás preguntando por código que verifica, limpia, confirma, o rechaza datos de entrada. Busca por concepto, no por string.

Demo directa: la misma pregunta, dos herramientas

# Con grep:
$ grep -rn "validat" src/
src/utils/helpers.py:45:    # validate email format
src/models/user.py:23:      def validate_name(self):

# 2 resultados. Incompleto.
# Con Explore en Claude Code:
> "Usa Explore para encontrar dónde se validan los inputs
   del usuario en este proyecto"

# Explore encuentra:
# 1. src/utils/helpers.py:45 - validate_email() — validación de formato
# 2. src/models/user.py:23 - validate_name() — validación de nombre
# 3. src/middleware/sanitizer.py:12 - sanitize_input() — limpieza de inputs
# 4. src/api/validators.py:8 - check_params() — verificación de parámetros
# 5. src/services/user_service.py:67 - ensure_valid_age() — rango de edad
# 6. src/middleware/auth.py:34 - verify_token() — validación de auth token
#
# Explore además reporta:
# "La validación de inputs ocurre en 3 capas:
#  1. Middleware (sanitizer.py) - limpieza general
#  2. API validators (validators.py) - parámetros requeridos
#  3. Model level (user.py, user_service.py) - reglas de negocio"

# 6 resultados + análisis de capas. Completo.

La diferencia no es marginal — es fundamental. Explore encontró el triple de resultados Y proporcionó contexto arquitectural.

Ejemplo progresivo: de simple a complejo

Nivel básico — Buscar una funcionalidad:

# Prompt a Claude Code:
> "Usa Explore para encontrar dónde se manejan los pagos
   en este proyecto"

# Explore busca por significado "manejo de pagos":
# - src/services/payment_service.py — lógica principal de pagos
# - src/api/routes/checkout.py — endpoints de checkout
# - src/models/transaction.py — modelo de transacción
# - src/integrations/stripe_client.py — integración con Stripe
# - src/utils/currency.py — conversión de moneda

Nivel intermedio — Buscar un patrón:

# Prompt a Claude Code:
> "Usa Explore para encontrar dónde se implementa
   el patrón retry en este proyecto"

# Explore entiende "patrón retry" como concepto:
# - src/utils/retry.py — decorador @retry con backoff exponencial
# - src/integrations/api_client.py:89 — retry manual con loop y sleep
# - src/services/email_service.py:34 — reintento de envío con contador
# - src/config/settings.py:78 — MAX_RETRIES, RETRY_DELAY configurados
#
# Nota: "Hay 2 implementaciones de retry: una centralizada
#  (retry.py) y una ad-hoc (api_client.py). La ad-hoc no
#  usa el decorador centralizado."

Nivel avanzado — Buscar un concepto abstracto:

# Prompt a Claude Code:
> "Usa Explore para encontrar posibles vulnerabilidades
   de seguridad en el manejo de datos del usuario"

# Explore analiza semánticamente:
# - src/api/routes/users.py:45 — password se loggea en modo debug
# - src/middleware/cors.py:12 — CORS permite origin "*" (wildcard)
# - src/utils/crypto.py:23 — usa MD5 para hash (deprecated, inseguro)
# - src/services/user_service.py:89 — SQL concatenado sin parametrizar
# - src/config/settings.py:5 — SECRET_KEY hardcodeada en el archivo

Comparación: grep vs Búsqueda Semántica

Criteriogrep / ripgrepExplore (semántico)
Busca porTexto exacto / regexSignificado / concepto
VelocidadMilisegundosSegundos (requiere LLM)
ResultadosLíneas con matchArchivos + contexto + análisis
False positivesMuchos (comentarios, strings, nombres similares)Pocos (entiende contexto)
False negativesMuchos (sinónimos, abstracciones)Pocos (entiende sinónimos)
Cuándo usarSabes el nombre exactoSabes qué hace pero no cómo se llama
CostoGratis, localTokens de API
MultilenguajeNo entiende idiomaEntiende preguntas en cualquier idioma

¿Cuándo usar cada uno?

Usa grep cuando:

  • Conoces el nombre exacto: grep -r "PaymentService" src/
  • Buscas un string literal: grep -r "TODO:" src/
  • Buscas un import específico: grep -r "from stripe" src/
  • Necesitas velocidad máxima (millones de archivos)
  • Buscas un error exacto: grep -r "Error: connection refused" logs/

Usa Explore cuando:

  • Sabes qué hace el código pero no cómo se llama: "¿dónde se maneja autenticación?"
  • Buscas un concepto abstracto: "¿dónde hay posibles memory leaks?"
  • Necesitas contexto además de ubicación: "¿cómo funciona el sistema de cache?"
  • Buscas código que implementa un patrón: "¿dónde se usa el patrón observer?"
  • Necesitas entender relaciones: "¿qué componentes dependen del módulo de auth?"

Trade-off clave: grep es gratis y rápido pero limitado a texto. Explore cuesta tokens y tarda más pero entiende significado. En la práctica profesional, usas ambos: grep para búsquedas exactas rápidas, Explore para investigación profunda.


Técnicas Avanzadas de Búsqueda Semántica

Técnica 1: Búsqueda por comportamiento

En lugar de buscar por nombre, busca por lo que el código hace:

# En vez de: grep -r "cache" src/
# Pregunta:
> "Usa Explore para encontrar código que almacena resultados
   para evitar cálculos repetidos"

# Encuentra: funciones con memoize, @lru_cache, dict lookups
# que actúan como cache, Redis calls, y variables de instancia
# que guardan resultados previos — muchas sin la palabra "cache"

Técnica 2: Búsqueda por impacto

Busca código que afecta un recurso específico:

# En vez de: grep -r "database\|db\|sql" src/
# Pregunta:
> "Usa Explore para encontrar todo código que lee o escribe
   en la base de datos"

# Encuentra: queries directas, ORM calls, migrations,
# seeders, y funciones que indirectamente causan queries
# a través de lazy loading

Técnica 3: Búsqueda negativa

Busca la ausencia de algo:

# No puedes hacer esto con grep
# Pregunta:
> "Usa Explore para encontrar endpoints que NO tienen
   autenticación"

# Encuentra: rutas públicas que deberían ser privadas,
# endpoints que faltan middleware de auth, rutas de admin
# sin verificación de permisos

Técnica 4: Búsqueda comparativa

Busca inconsistencias:

# Pregunta:
> "Usa Explore para encontrar funciones que manejan errores
   de forma diferente al patrón dominante del proyecto"

# Encuentra: funciones que usan print() en vez de logger,
# que silencian excepciones con bare except,
# o que retornan None en vez de raise

Combinando grep y Explore

El workflow profesional

Los mejores resultados vienen de combinar ambas herramientas:

# Paso 1: Explore para investigación amplia
> "Usa Explore para entender cómo funciona el sistema
   de notificaciones"

# Explore reporta:
# "El sistema de notificaciones usa un patrón pub/sub.
#  Los publishers están en src/events/, los subscribers
#  en src/handlers/, y la configuración en src/config/
#  notifications.yaml. La clase principal es EventBus
#  en src/core/event_bus.py"

# Paso 2: grep para detalles específicos
$ grep -rn "EventBus" src/
# src/core/event_bus.py:5: class EventBus:
# src/api/routes/orders.py:12: from core.event_bus import EventBus
# src/services/payment_service.py:8: from core.event_bus import EventBus
# ... (lista exacta de todos los archivos que lo usan)

# Paso 3: Explore para análisis profundo
> "Usa Explore para analizar si hay eventos que se
   publican pero nadie escucha (dead events)"

La secuencia es: Explore (visión amplia) → grep (detalles exactos) → Explore (análisis profundo).

Ejemplo completo: investigar sistema de auth

# 1. Visión general con Explore
> "Usa Explore para explicar cómo funciona la
   autenticación en este proyecto"

# Explore reporta: JWT con refresh tokens, middleware
# en src/middleware/auth.py, user model en src/models/,
# login endpoint en src/api/routes/auth.py

# 2. Grep para encontrar todas las rutas protegidas
$ grep -rn "@require_auth\|@login_required" src/api/
# Lista exacta de 23 endpoints protegidos

# 3. Explore para encontrar gaps
> "Usa Explore para encontrar endpoints en src/api/routes/
   que acceden a datos de usuario pero no tienen decorador
   de autenticación"

# Explore encuentra 2 endpoints sin protección que deberían
# tenerla — esto es un finding de seguridad real

Conexión con Proyecto

En el Proyecto del Módulo (cápsula 05) vas a responder preguntas específicas sobre un codebase usando Explore. Muchas de esas preguntas son semánticas por naturaleza:

  • "¿Cómo fluye un request de login desde el endpoint hasta la database?" — requiere búsqueda por comportamiento
  • "¿Dónde se validan los inputs del usuario?" — requiere búsqueda por concepto
  • "¿Qué dependencias tiene el módulo de pagos?" — requiere búsqueda por relación

Sin búsqueda semántica, estas preguntas requieren grep + lectura manual de decenas de archivos. Con Explore, obtienes respuestas directas con contexto.


Troubleshooting

Problema 1: Explore no encuentra lo que busco

Causa: El prompt es demasiado vago o usa terminología diferente a la del codebase.

Solución: Sé más específico y prueba sinónimos:

# Vago:
> "Usa Explore para encontrar la seguridad"

# Específico:
> "Usa Explore para encontrar dónde se verifican
   permisos de usuario antes de acceder a recursos"

Problema 2: Explore retorna demasiados resultados

Causa: La pregunta es demasiado amplia.

Solución: Acota por directorio o módulo:

# Demasiado amplio:
> "Usa Explore para encontrar manejo de errores"

# Acotado:
> "Usa Explore para encontrar manejo de errores
   en src/api/routes/ — específicamente errores HTTP"

Problema 3: grep es más rápido para mi caso

Causa: Estás buscando un string exacto que conoces.

Solución: Usa grep. No todo requiere búsqueda semántica:

# Para esto, grep es superior:
grep -rn "from fastapi import" src/
# Resultado instantáneo, exacto, completo

Problema 4: No sé si usar grep o Explore

Causa: No has definido si buscas texto o concepto.

Solución: Hazte esta pregunta: "¿Sé el nombre exacto de lo que busco?"

  • Sí → grep
  • No, pero sé qué hace → Explore

Problema 5: Explore interpreta mi pregunta incorrectamente

Causa: Ambigüedad en el prompt.

Solución: Agrega contexto:

# Ambiguo:
> "Usa Explore para encontrar el modelo"

# Con contexto:
> "Usa Explore para encontrar el modelo de datos
   (ORM/database model) para usuarios, no el modelo
   de machine learning"

Ejercicios

Ejercicio 1: Identificar la herramienta correcta (Fácil)

Para cada búsqueda, decide si usarías grep o Explore y explica por qué:

  1. Encontrar todos los archivos que importan requests
  2. Encontrar dónde se implementa rate limiting
  3. Encontrar la definición de la clase UserService
  4. Encontrar posibles SQL injections
  5. Encontrar todos los TODO en el proyecto
Ver solución
  1. grep — busca string exacto from requests import / import requests
  2. Explore — "rate limiting" puede implementarse como decorador, middleware, o counter sin usar esa frase
  3. grep — busca string exacto class UserService
  4. Explore — SQL injection se manifiesta como string concatenation en queries, f-strings con SQL, etc. — no hay string único que buscar
  5. grep — busca string exacto TODO

Regla general: si puedes escribir el regex, usa grep. Si necesitas describir el concepto, usa Explore.

Ejercicio 2: Reformular para búsqueda semántica (Fácil)

Convierte estas búsquedas grep en preguntas semánticas para Explore:

  1. grep -r "try.*except" src/
  2. grep -r "sleep\|time.sleep" src/
  3. grep -r "os.environ\|getenv" src/
Ver solución
  1. grep "try.*except" → "Usa Explore para encontrar funciones que manejan errores y excepciones, incluyendo las que usan condicionales para detectar errores sin try/except"
  2. grep "sleep" → "Usa Explore para encontrar código que introduce delays, esperas, o throttling, incluyendo asyncio.sleep, polling loops, y rate limiters"
  3. grep "os.environ" → "Usa Explore para encontrar dónde se leen configuraciones del entorno, incluyendo variables de entorno, archivos .env, config files, y secrets managers"

Nota: la versión semántica encuentra más porque incluye sinónimos y variantes que grep no captura.

Ejercicio 3: Búsqueda combinada (Medio)

Tienes un proyecto Django y necesitas entender el sistema de permisos. Diseña una secuencia de 3 pasos combinando grep y Explore:

Ver solución
# Paso 1: Explore para visión general
> "Usa Explore para explicar cómo funciona el sistema
   de permisos en este proyecto Django. ¿Usa el sistema
   built-in de Django, un paquete como django-guardian,
   o implementación custom?"

# Paso 2: grep para mapear uso exacto
$ grep -rn "@permission_required\|has_perm\|user_passes_test" src/
$ grep -rn "PermissionMixin\|BasePermission" src/

# Paso 3: Explore para encontrar gaps
> "Usa Explore para encontrar vistas en src/views/
   que acceden a datos sensibles pero no verifican
   permisos de ninguna forma"

La lógica: Explore da el panorama, grep da los números exactos, Explore encuentra lo que falta.

Ejercicio 4: Búsqueda negativa (Medio)

Escribe 3 preguntas para Explore que busquen la ausencia de algo (cosas que deberían existir pero no existen):

Ver solución
  1. "Usa Explore para encontrar funciones públicas en src/api/ que no tienen docstrings"
  2. "Usa Explore para encontrar modelos de base de datos que no tienen validación en sus campos"
  3. "Usa Explore para encontrar endpoints que aceptan input del usuario pero no lo sanitizan antes de procesarlo"

Por qué esto importa: la búsqueda negativa es imposible con grep (no puedes buscar algo que no está). Es una de las capacidades más valiosas de la búsqueda semántica para auditoría de código y detección de vulnerabilidades.

Ejercicio 5: Caso real — Onboarding con búsqueda mixta (Difícil)

Estás haciendo onboarding a un proyecto Python de 15K líneas. Diseña un plan de investigación de 10 búsquedas (mix de grep y Explore) para entender:

  • Cómo funciona la autenticación
  • Dónde están los puntos de entrada
  • Qué base de datos usa y cómo se accede
Ver solución
# Autenticación (4 búsquedas):
1. Explore: "¿Cómo funciona la autenticación en este proyecto?
   ¿JWT, sessions, OAuth, API keys?"
2. grep: grep -rn "SECRET_KEY\|JWT\|token" src/config/
3. Explore: "¿Qué endpoints requieren autenticación y cuáles son públicos?"
4. grep: grep -rn "@auth\|@login\|@require" src/api/

# Puntos de entrada (3 búsquedas):
5. grep: grep -rn "if __name__\|app.run\|uvicorn" src/
6. Explore: "¿Cuáles son todos los entry points de esta aplicación?
   Incluye CLI, web, workers, y scheduled tasks"
7. grep: grep -rn "@app.route\|@router" src/

# Base de datos (3 búsquedas):
8. Explore: "¿Qué base de datos usa este proyecto y cómo se conecta?
   ¿Usa ORM o queries raw?"
9. grep: grep -rn "DATABASE\|SQLALCHEMY\|psycopg\|pymongo" src/
10. Explore: "¿Hay queries SQL raw en el proyecto? Si es así,
    ¿alguna es vulnerable a SQL injection?"

Patrón: cada área usa Explore para visión general y grep para datos exactos. Esto produce un mapa completo en minutos, no horas.

Ejercicio 6: Construir tu cheatsheet (Difícil)

Crea una tabla de referencia rápida con 10 escenarios comunes de búsqueda, indicando para cada uno: herramienta recomendada, prompt/comando exacto, y qué tipo de resultado esperas.

Ver solución
EscenarioHerramientaComando/PromptResultado esperado
Encontrar definición de clasegrepgrep -rn "class ClassName" src/Línea exacta + archivo
Entender flujo de datosExplore"¿Cómo fluyen los datos desde input hasta la DB?"Diagrama de flujo textual
Encontrar imports de un módulogrepgrep -rn "from module import" src/Lista de archivos
Encontrar vulnerabilidadesExplore"¿Hay vulnerabilidades de seguridad en src/api/?"Lista con contexto
Encontrar TODOsgrepgrep -rn "TODO|FIXME|HACK" src/Lista con líneas
Entender error handlingExplore"¿Cómo maneja errores este proyecto? ¿Hay un patrón consistente?"Análisis de patrones
Encontrar tests de una funcióngrepgrep -rn "test_función_name" tests/Archivos de test
Encontrar código muertoExplore"¿Hay funciones definidas pero nunca llamadas?"Lista de dead code
Encontrar config valuesgrepgrep -rn "KEY_NAME" src/config/Valores exactos
Entender dependenciasExplore"¿De qué depende el módulo X? ¿Qué depende de X?"Grafo de dependencias

Principio: grep para lo que sabes nombrar, Explore para lo que sabes describir.


Resumen

En esta cápsula aprendiste:

  • grep busca texto, Explore busca significado — es la diferencia fundamental entre ambas herramientas
  • Explore encuentra sinónimos y variantes que grep no puede: check_params, sanitize_input, ensure_valid son todas "validación" para Explore
  • Búsqueda semántica tiene 4 técnicas avanzadas: por comportamiento, por impacto, negativa, y comparativa
  • La búsqueda negativa es exclusiva de Explore — no puedes buscar la ausencia de algo con grep
  • El workflow profesional combina ambas: Explore (visión amplia) → grep (detalles exactos) → Explore (análisis profundo)
  • La regla de decisión es simple: ¿sabes el nombre exacto? grep. ¿Sabes qué hace pero no cómo se llama? Explore

Próxima cápsula: Patrones de Exploración — Top-Down, Dependency-Following, Feature-Tracing. Vas a aprender tres estrategias sistemáticas para investigar codebases con Explore, cada una optimizada para un tipo diferente de pregunta.


Recursos Adicionales

  1. Documentación de Claude Code - Subagents - Referencia oficial sobre cómo funcionan los subagents incluyendo Explore
  2. ripgrep (rg) - Documentación - La alternativa moderna a grep, más rápida y con mejor UX
  3. The Art of Searching Code - Sourcegraph Blog - Perspectivas sobre búsqueda de código a escala
  4. Semantic Code Search - Papers with Code - Research sobre búsqueda semántica de código
  5. grep vs ripgrep vs ag - Benchmarks - Comparación de herramientas de búsqueda por texto
  6. How LLMs Understand Code - Anthropic Research - Cómo los modelos de lenguaje comprenden código fuente