neuroverse

Capa de inteligencia multilingüe + memoria + seguridad + voz para agentes autónomos de IA

Documentación

version node python license MCP tests npm

NeuroVerse MCP Server Card

NeuroVerse MCP Server Score

🧠 NeuroVerse

📦 Instalar desde npm | 🐙 Repositorio de GitHub

Tu agente de IA solo habla inglés. NeuroVerse lo soluciona.
Tu agente de IA lo olvida todo. NeuroVerse lo recuerda.
Tu agente de IA podría hacer algo peligroso. NeuroVerse lo detiene.
Tu agente de IA está limitado a un solo modelo. NeuroVerse enruta al mejor.

Inteligencia multilingüe + memoria + seguridad + capa de voz para agentes de IA autónomos.


🚀 Novedades en v4.1

  • Razonamiento OpenRouter: Se integró el modelo stepfun/step-3.5-flash:free para tareas analíticas de alto rendimiento. Usa la nueva herramienta neuroverse_reason para pensamiento profundo.
  • Tokens de razonamiento: Seguimiento en tiempo real de los tokens de razonamiento para cada solicitud.
  • Capa de voz (v2.0): Soporte integrado para Whisper STT y Coqui TTS.

🚀 ¿Qué es NeuroVerse?

Cada vez que inicias un nuevo chat con Cursor, VS Code Copilot o cualquier agente de IA compatible con MCP, este comienza desde cero — sin memoria, sin seguridad, sin comprensión de tu idioma. NeuroVerse es un servidor MCP que les da a tus agentes:

CaracterísticaDescripción
🌐Inteligencia multilingüeComprende idiomas indios mixtos — tamil, hindi, telugu, kannada, malayalam, bengalí + inglés. ¿Cambio de código? No hay problema.
🎙️Capa de vozSTT mediante Whisper y TTS mediante Coqui. Transcribe audio del usuario y sintetiza respuestas del agente.
🧠Extracción de intenciónExtracción de intención estructurada con LLM primero y respaldo determinista basado en reglas. Nunca pierde un comando.
💾Memoria por nivelesCorto plazo (sesión), episódica (reciente), semántica (hechos a largo plazo) — todo con puntuación de importancia.
🛡️Seguridad de 3 capas (Kavach)Lista negra de palabras clave → Clasificador de riesgo de intención → Juez LLM. Bloquea DROP DATABASE antes de que sea demasiado tarde.
🤖Enrutador multi-modelo (Marga)OpenAI · Anthropic · Sarvam AI · Ollama · OpenRouter — enruta cada tarea al mejor modelo automáticamente.
🔗Agente a agente (Setu)Registro de agentes REST+JSON con respaldo automático. Agentes llamando a agentes llamando a agentes.
Todo asíncronoFastAPI + asyncpg + httpx. Verificaciones de seguridad en menos de un milisegundo. Cero bloqueos.

⚡ NeuroVerse es una capa de inteligencia modular — no un monolito. Conecta lo que necesites. Ignora lo que no.


Tabla de contenidos


🚀 Inicio rápido

1. Instalación

Opción A: npm (recomendado) — úsalo en cualquier lugar

npm install neuroverse

Opción B: Desde el código fuente (Python)

git clone https://github.com/joshua400/neuroverse.git
cd neuroverse
python -m pip install -e ".[dev]"

💡 Consejo: Si instalaste mediante npm, la ruta es node_modules/neuroverse/dist/index.js. Si es desde el código fuente, usa la ruta absoluta a tu directorio clonado.

2. Agrega NeuroVerse a tu configuración de MCP

NeuroVerse es un servidor MCP estándar (stdio). Agrégalo a la configuración de tu host:

Cursor / VS Code Copilot / Claude Desktop (npm)

{
  "mcpServers": {
    "neuroverse": {
      "command": "npx",
      "args": ["neuroverse"]
    }
  }
}

Desde el código fuente (Python)

{
  "mcpServers": {
    "neuroverse": {
      "command": "python",
      "args": ["mcp/server.py"],
      "cwd": "/path/to/neuroverse"
    }
  }
}

3. Dile a tu agente que use NeuroVerse

Agrega esto al archivo de reglas de tu agente (.md, .cursorrules, prompt del sistema, etc.):

## NeuroVerse Integration
- Use `neuroverse_process` to handle any user request — it auto-detects language, extracts intent, checks safety, and executes.
- Use `neuroverse_reason` for complex tasks requiring analytical reasoning (powered by OpenRouter).
- Use `neuroverse_store` / `neuroverse_recall` for persistent context across sessions.
- Use `neuroverse_execute` for any potentially dangerous action — it will block destructive operations.

Eso es todo. Dos comandos que tu agente necesita conocer:

ComandoCuándoQué sucede
neuroverse_process(text, user_id)Cualquier solicitud del usuarioDetecta el idioma, extrae la intención, verifica seguridad, ejecuta
neuroverse_store(user_id, intent, ...)Al final del trabajoGuarda el contexto para la próxima sesión

En la próxima sesión, tu agente continúa exactamente donde lo dejó — como si nunca lo hubiera olvidado.

Requisitos

  • Edición npm: Node.js 18+ (cero dependencias de base de datos — usa archivos JSON)
  • Edición Python: Python 3.10+ + PostgreSQL (para memoria persistente)

🤔 ¿Por qué NeuroVerse?

Sin NeuroVerseCon NeuroVerse
El agente solo entiende inglésEl agente entiende tamil, hindi, telugu, kannada + cambio de código en inglés
"anna file ah csv convert pannu" → ❌ error"anna file ah csv convert pannu" → ✅ convierte el archivo a CSV
Cada sesión comienza desde ceroEl agente recuerda lo que hizo — entre sesiones, entre agentes
DROP DATABASE → 💀 tus datos se pierdenDROP DATABASE → 🛡️ bloqueado en < 1 ms, cero tokens
Limitado a un solo proveedor de LLMEnruta al mejor modelo para cada tarea automáticamente
Dos agentes = caosEl agente A transfiere al agente B sin problemas

Eficiencia de tokens

La capa de seguridad de NeuroVerse funciona a costo cero de tokens — solo regex puro y coincidencia de reglas, sin desperdiciar llamadas LLM:

Enfoque de seguridadCosto por verificaciónLatencia
Seguridad basada en LLM500–2000 tokens1–5 segundos
Basada en embeddings100–500 tokens200–500 ms
NeuroVerse Kavach0 tokens< 1 ms

Con más de 100 llamadas a herramientas por sesión, eso son 50 000–200 000 tokens ahorrados en comparación con la seguridad basada en LLM.


⚙️ Cómo funciona

User Input (any language)
        │
   ┌────┴────┐
   │  Vani   │ ← Language detection + keyword normalisation
   │ (भाषा)  │   Tamil/Hindi/Telugu → normalised internal format
   └────┬────┘
        │
   ┌────┴────┐
   │  Bodhi  │ ← LLM intent extraction + rule-based fallback
   │ (बोधि)  │   Returns structured JSON with confidence
   └────┬────┘
        │
   ┌────┴────┐
   │ Kavach  │ ← 3-layer safety: blocklist → risk → LLM judge
   │ (कवच)   │   Blocks dangerous actions at zero token cost
   └────┬────┘
        │
   ┌────┴────┐
   │  Marga  │ ← Routes to best model (OpenAI/Anthropic/Sarvam/Ollama)
   │ (मार्ग)  │   Based on task type: multilingual/reasoning/local
   └────┬────┘
        │
   ┌────┴────┐
   │ Smriti  │ ← Stores/recalls from tiered memory
   │ (स्मृति) │   Short-term + Episodic + Semantic (PostgreSQL)
   └────┬────┘
        │
   Tool Execution + Response

🌐 Inteligencia multilingüe — Vani

El problema: Cada servidor MCP habla solo inglés. El 70 % de la India cambia de código a diario.

"anna indha file ah csv convert pannu"
         ↓
"anna this file ah csv convert do"     ← keyword normalisation (not full translation)
         ↓
Intent: convert_format { output_format: "csv" }

Pipeline híbrido (regla + LLM)

Input → Language Detect (langdetect) → Code-Switch Split → Keyword Normalise → Output

Idea clave: No traduzcas por completo. Solo normaliza las palabras clave críticas del dominio. El resto permanece intacto — preservando contexto, tono y matices.

Idiomas compatibles

IdiomaPalabras clave mapeadasEjemplo
🇮🇳 Tamilpannu → hacer, maathru → cambiar, anuppu → enviar"file ah csv convert pannu"
🇮🇳 Hindikaro → hacer, banao → crear, bhejo → enviar"report banao sales ka"
🇮🇳 Telugucheyyi → hacer, pampu → enviar, chupinchu → mostrar"data chupinchu"
🇮🇳 KannadaSoporte próximamente en v2
🇬🇧 InglésPaso directo"convert json to csv"

Detección de cambio de código

{
  "languages": ["ta", "en"],
  "confidence": 0.92,
  "is_code_switched": true,
  "original_text": "anna indha file ah csv convert pannu",
  "normalized_text": "anna this file ah csv convert do"
}

🧠 Extracción de intención — Bodhi

LLM primero. Respaldo basado en reglas. Nunca falla.

LLM succeeds (confidence ≥ 0.5)?
   ├─ Yes → use LLM result
   └─ No  → rule-based parser (deterministic)

Estrategia LLM

# Prompt to LLM:
"Extract structured intent from the following input.
 Return ONLY valid JSON: {intent, parameters, confidence}"

Respaldo basado en reglas (7 patrones)

PatrónIntenciónPalabras clave de activación
Conversión de formatoconvert_formatconvertir, csv, json, excel, pdf
Resumensummarizeresumir, resumen, breve, tldr
Generación de informesgenerate_reportinforme, generar informe
Eliminacióndelete_dataeliminar, borrar, quitar, limpiar
Consulta de datosquery_dataconsultar, buscar, encontrar, obtener, traer
Comunicaciónsend_messageenviar, compartir, correo, notificar
Explicaciónexplainexplicar, describir, qué es, cómo

Salida

{
  "intent": "convert_format",
  "parameters": { "input_format": "json", "output_format": "csv" },
  "confidence": 0.87,
  "source": "rule"
}

La diferencia clave: el código decide — no el LLM. Si el LLM falla, alucina o devuelve basura, el motor de reglas toma el control. Determinista. Confiable.


💾 Memoria por niveles — Smriti

El problema: Los registros en bruto son inútiles. Almacenarlo todo desperdicia recursos. Sin puntuación de relevancia.

El enfoque de NeuroVerse: Puntuar → Filtrar → Comprimir → Almacenar.

Tres niveles

NivelAlmacenamientoDuraciónUso
Corto plazoDiccionario en procesoSesión actualContexto activo, limitado a 50 por usuario
EpisódicaPostgreSQLAcciones recientesLo que el agente hizo recientemente
SemánticaPostgreSQLHechos a largo plazoConocimiento persistente sobre usuarios, proyectos, entidades

Puntuación de importancia

if importance_score >= 0.4:
    persist_to_database()   # worth remembering
else:
    skip()                  # noise

Solo sobreviven los recuerdos importantes. Sin inflación. Sin recuperación irrelevante.

Compresión de contexto

❌ Bad:  "The user asked about sales data three times in the last hour and seemed frustrated..."
✅ Good: { "intent": "sales_query", "frequency": 3, "sentiment": "frustrated" }

Cargas útiles JSON estructuradas, NO volcados de texto en bruto. Comprimidas. Indexables. Consultables.

Esquema de memoria (PostgreSQL)

CREATE TABLE memory_records (
    id          TEXT PRIMARY KEY,
    user_id     TEXT NOT NULL,
    tier        TEXT NOT NULL,          -- short_term | episodic | semantic
    intent      TEXT NOT NULL,
    language    TEXT DEFAULT 'en',
    data        JSONB DEFAULT '{}',     -- compressed structured payload
    importance  REAL DEFAULT 0.5,
    created_at  TIMESTAMPTZ DEFAULT NOW(),
    updated_at  TIMESTAMPTZ DEFAULT NOW()
);
-- Indexed: user_id, intent, tier

🛡️ Capa de seguridad — Kavach

"El escudo que nunca duerme."

Tres capas — Defensa en profundidad

Agent calls tool  →  MCP Server receives request
                            │
                ┌───────────┴───────────┐
                │   Layer 1: Blocklist  │  ← regex + keywords, < 0.1ms
                └───────────┬───────────┘
                            │ pass
                ┌───────────┴───────────┐
                │  Layer 2: Risk Score  │  ← intent → risk classification
                └───────────┬───────────┘
                            │ pass
                ┌───────────┴───────────┐
                │  Layer 3: LLM Judge   │  ← optional model-based check
                └───────────┬───────────┘
                            │ pass
                     Execute handler

Capa 1 — Lista negra basada en reglas (costo cero)

Se ejecuta dentro del servidor MCP. Regex puro. Sin red. Sin tokens.

Palabras clave bloqueadas:

delete_all_data, drop_database, drop_table, system_shutdown,
format_disk, rm -rf, truncate, shutdown, reboot, erase_all, destroy

Patrones bloqueados (regex):

DROP (DATABASE|TABLE|SCHEMA)
DELETE FROM *
TRUNCATE TABLE
FORMAT [drive]:
rm (-rf|--force)

Capa 2 — Clasificación de riesgo de intención

Nivel de riesgoIntencionesAcción
🟢 BAJOconvert_format, summarize, generate_report, query_data, explain✅ Permitir
🟡 MEDIOsend_message, unknown⚠️ Bloquear si el modo estricto está activo
🔴 ALTOdelete_data❌ Bloquear siempre
⛔ CRÍTICOdrop_database, system_shutdown❌ Bloquear siempre

Capa 3 — Juez de seguridad LLM (opcional)

Si las capas 1–2 pasan, opcionalmente pregúntale a un LLM: "¿Es esto seguro?"

// LLM returns:
{ "safe": false, "reason": "This action would delete all user data." }

Veredicto de seguridad

{
  "allowed": false,
  "risk_level": "critical",
  "reason": "Blocked keyword detected: 'drop_database'",
  "blocked_by": "rule"
}

Costo de tokens: cero

Most AI safety:  Agent → "rm -rf /" → Safety LLM → 2,000 tokens burned
NeuroVerse:      Agent → "rm -rf /" → regex match → BLOCKED (0 tokens, < 1ms)

Modo estricto

# .env
SAFETY_STRICT_MODE=true    # Also blocks MEDIUM risk (unknown/send)
SAFETY_STRICT_MODE=false   # Only blocks HIGH and CRITICAL

🤖 Enrutador multi-modelo — Marga

El problema: Dependencia del proveedor. Un solo modelo para todo. Pagar de más.

El enfoque de NeuroVerse: Enrutar cada tarea al mejor modelo. Automáticamente.

Lógica de enrutamiento

def route_task(task):
    if task.type == "multilingual":
        return sarvam_model        # Best for Indian languages
    elif task.type == "reasoning":
        return claude_or_openai    # Best for complex analysis
    elif task.type == "local":
        return ollama              # Free, on-device, private
    else:
        return best_available      # Fallback chain

Proveedores compatibles

ProveedorModelo predeterminadoMejor paraCosto
🇮🇳 Sarvam AIsarvam-2b-v0.5Idiomas indios, multilingüeBajo
🧩 OpenRouterstepfun/step-3.5-flash:freeRazonamiento de alto rendimientoGratis
🧠 Anthropicclaude-sonnet-4-20250514Razonamiento, análisisMedio
🤖 OpenAIgpt-4oTareas generales, códigoMedio
🦙 Ollamallama3Local, privado, sin conexiónGratis

Beneficios

Sin MargaCon Marga
CostoPagar GPT-4 por todoUsar Ollama para tareas simples
VelocidadMisma latencia para todas las tareasModelos locales para tareas rápidas
PrivacidadTodo va a la nubeLos datos sensibles permanecen locales
Dependencia del proveedorAtrapado con un proveedorCambia cuando quieras

Cadena de respaldo

Si tu proveedor preferido está caído o no configurado:

OpenRouter → Anthropic → OpenAI → Sarvam → Ollama (local, always available)

🔗 Agente a agente — Setu

Agentes llamando a agentes llamando a agentes.

Registro de agentes

register_agent({
    "agent_name": "report_agent",
    "endpoint": "http://localhost:8001/generate",
    "capabilities": ["generate_report", "sales_analysis"]
})

Enrutamiento

{
  "target_agent": "report_agent",
  "task": "generate_sales_report",
  "payload": { "quarter": "Q1", "year": 2026 }
}

Respaldo

Si el agente de destino no está disponible:

{
  "success": false,
  "error": "Agent unreachable: ConnectError",
  "fallback": true
}

El llamador puede recurrir a la ejecución local. Sin fallos duros.


🧩 Herramientas MCP

NeuroVerse expone 6 herramientas mediante el Protocolo de Contexto de Modelo:

#Herramienta (npm)Herramienta (Python)Descripción
1neuroverse_processindia_mcp_process_multilingual_inputPipeline completo: detectar → normalizar → intención → seguridad → ejecutar
2neuroverse_storeindia_mcp_store_memoryAlmacenar un registro de memoria en el sistema por niveles
3neuroverse_recallindia_mcp_recall_memoryRecuperar memorias por usuario, intención o nivel
4neuroverse_executeindia_mcp_safe_executeEjecución segura de extremo a extremo (conveniencia)
5neuroverse_routeindia_mcp_route_agentEnrutar una tarea a un agente downstream registrado
6neuroverse_modelindia_mcp_model_routeConsultar el enrutador multimodelo (opcionalmente invocar)
7neuroverse_transcribeindia_mcp_transcribe_audioTranscribir audio a texto mediante Whisper STT
8neuroverse_synthesizeindia_mcp_synthesize_speechSintetizar voz a partir de texto mediante Coqui TTS
9neuroverse_reasonN/ARazonamiento de alto rendimiento mediante OpenRouter

Ejemplo del Mundo Real

── Session 1 (Agent Alpha, 2pm) ───────────────────────────
india_mcp_process_multilingual_input({
    text: "anna indha sales data ah csv convert pannu",
    user_id: "alpha",
    execute: true
})
→ Language: Tamil+English (code-switched)
→ Intent: convert_format { output_format: "csv" }
→ Safety: ✅ allowed (LOW risk)
→ Execution: ✅ success

india_mcp_store_memory({
    user_id: "alpha",
    intent: "convert_format",
    tier: "episodic",
    data: { "file": "sales_q1.json", "output": "csv" },
    importance_score: 0.8
})

── Session 2 (Agent Beta, next day) ───────────────────────
india_mcp_recall_memory({
    user_id: "alpha",
    intent: "convert_format",
    limit: 5
})
→ "Agent Alpha converted sales_q1.json to CSV yesterday"
→ Beta picks up exactly where Alpha left off

🌐 API REST

NeuroVerse también incluye una capa REST con FastAPI — para clientes que no usan MCP:

python app/main.py
# → http://localhost:8000/docs (Swagger UI)
EndpointMétodoDescripción
/healthGETVerificación de estado
/api/processPOSTPipeline multilingüe completo
/api/memory/storePOSTAlmacenar memoria
/api/memory/recallPOSTRecuperar memorias

⚙️ Configuración

Todos los ajustes mediante variables de entorno (.env):

# Database (PostgreSQL required for persistent memory)
DATABASE_URL=postgresql+asyncpg://user:password@localhost:5432/neuroverse

# AI Model API Keys (configure the ones you have)
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
SARVAM_API_KEY=...

# Ollama (local, free)
OLLAMA_BASE_URL=http://localhost:11434

# Safety
SAFETY_STRICT_MODE=true     # Block MEDIUM risk actions too

# MCP Transport
MCP_TRANSPORT=stdio          # or streamable_http
MCP_PORT=8000

🧪 Pruebas

python -m pytest tests/ -v
tests/test_intent.py     — 10 passed  (rule-based + async + mock LLM + fallback)
tests/test_language.py   — 10 passed  (keyword normalisation + detection + code-switch)
tests/test_pipeline.py   —  8 passed  (full e2e: English, Tamil, Hindi, dangerous, edges)
tests/test_safety.py     — 12 passed  (blocklist, regex, risk classification, pipeline)

============================= 40 passed in 0.87s ==============================

Qué se Prueba

CategoríaPruebasCobertura
Detección de idioma10Tamil, hindi, inglés, entrada vacía, indicador de cambio de código
Extracción de intención10Los 7 patrones de reglas, simulación de LLM, fallo de LLM, vacío
Motor de seguridad12Palabras clave, regex, niveles de riesgo, pipeline completo, modo estricto
Pipeline completo8E2E en inglés, tamil, hindi, comandos peligrosos, casos límite

🏗️ Arquitectura

Edición npm (Node.js / TypeScript)

npm/
├── src/
│   ├── core/
│   │   ├── language.ts       # Vani  — Language detection (zero deps)
│   │   ├── intent.ts         # Bodhi — Intent extraction (LLM + fallback)
│   │   ├── memory.ts         # Smriti — Tiered memory (JSON files)
│   │   ├── safety.ts         # Kavach — 3-layer safety engine
│   │   └── router.ts         # Marga — Multi-model AI router
│   ├── services/
│   │   ├── executor.ts       # Tool registry + retry engine
│   │   └── agent-router.ts   # Setu — Agent-to-Agent routing
│   ├── types.ts              # TypeScript interfaces & enums
│   ├── constants.ts          # Shared constants
│   └── index.ts              # MCP Server — 6 tools (McpServer + Zod)
├── package.json              # npm publish config
├── tsconfig.json
└── LICENSE                   # Apache-2.0

Edición Python

app/
├── core/
│   ├── language.py           # Vani  — Language detection (langdetect)
│   ├── intent.py             # Bodhi — Intent extraction (LLM + fallback)
│   ├── memory.py             # Smriti — Tiered memory (PostgreSQL)
│   ├── safety.py             # Kavach — 3-layer safety engine
│   └── router.py             # Marga — Multi-model AI router
├── models/schemas.py         # 12 Pydantic v2 models
├── services/
│   ├── executor.py           # Tool registry + retry engine
│   └── agent_router.py       # Setu — Agent-to-Agent routing
├── config.py                 # Settings from environment
└── main.py                   # FastAPI REST entry point
mcp/server.py                 # MCP Server (FastMCP) — 6 tools
tests/                        # 40 tests (pytest)

Dependencias — Mínimas

npm (3 paquetes):

PaquetePropósito
@modelcontextprotocol/sdkProtocolo MCP
zodValidación de esquemas
axiosSolicitudes HTTP

Python (7 paquetes):

PaquetePropósito
mcp[cli]SDK del Protocolo de Contexto de Modelo
fastapi + uvicornCapa de API REST
pydanticValidación de entrada (v2)
langdetectIdentificación estadística de idiomas
asyncpg + sqlalchemy[asyncio]Controlador asíncrono de PostgreSQL
httpxHTTP asíncrono para APIs de modelos

🚀 Hoja de Ruta

FaseEstadoQué
v1.0✅ HechoAnálisis multilingüe + extracción de intención + 5 herramientas
v1.0✅ HechoSistema de memoria por niveles (PostgreSQL)
v1.0✅ HechoMotor de seguridad de 3 capas (Kavach)
v1.0✅ HechoEnrutador multimodelo (Marga) + Enrutamiento de agentes (Setu)
v2.0✅ HechoCapa de voz (Whisper/Coqui) + Multilingüe extendido
v3.0✅ HechoCaché Redis + Recuperación semántica basada en embeddings
v4.0✅ HechoAprendizaje por refuerzo (RLHF) + Indexación contextual Arachne
v4.1✅ HechoIntegración de la Capa de Razonamiento OpenRouter
v5.0🔮 FuturoMercado de agentes y complementos de sistemas externos

🔐 Seguridad

MedidaImplementación
Gestión de claves APISolo variables de entorno — nunca en el código
Saneamiento de entradasPydantic v2 con restricciones de campo en todas las entradas
Límite de velocidadPlanificado para v2.0
Path traversalN/A — las herramientas no acceden al sistema de archivos
Inyección SQLConsultas parametrizadas mediante SQLAlchemy
Almacenamiento cifradoDelegado a TLS de PostgreSQL

🤝 Contribuciones

¡Las contribuciones son bienvenidas! Así es como empezar:

  1. Haz un fork del repositorio
  2. Crea una rama de funcionalidad (git checkout -b feature/amazing-feature)
  3. Haz commit de tus cambios (git commit -m 'feat: add amazing feature')
  4. Sube la rama (git push origin feature/amazing-feature)
  5. Abre una Pull Request

Configuración de Desarrollo

# npm edition
git clone https://github.com/joshua400/neuroverse.git
cd neuroverse/npm
npm install
npm run build

# Python edition
cd neuroverse
python -m pip install -e ".[dev]"
python -m pytest tests/ -v    # All 40 should pass

📜 Licencia

Apache-2.0


"Construí NeuroVerse porque me rompió el corazón ver a los agentes olvidarlo todo en cada sesión — y no entender ni una palabra de tamil."

Joshua Ragiland M
✉️ joshuaragiland@gmail.com
🌐 Sitio Web del Portafolio

Construido con 🧠 por Joshua — para los agentes del mañana.