Saltar al contenido
Kevo Rojas

Mi asistente de IA en Meta Quest 3: cómo funciona y el prompt para replicarlo

KR
Kevo Rojas
9 oct 2026 · 11 min de lectura
Video del tutorial

Edison es un asistente de IA que vive en mis Meta Quest 3: le hablo y responde con voz y paneles en mi cuarto. Cómo funciona y el prompt para armar el tuyo.

En resumen: Edison es un asistente de IA en Meta Quest 3: una página web que abro en el navegador del visor, conectada a un servidor en mi computadora. Le hablo, me responde con voz y aparecen paneles flotando en mi cuarto. La voz se procesa en local, lo simple lo responde un modelo chico con Ollama y lo pesado va a la nube. Al final está el prompt para que tu agente de código te arme una primera versión.

En TikTok me preguntaron cómo lo hice. La respuesta corta es este artículo: qué es Edison, cómo funciona por dentro y un prompt para replicarlo.

Qué es Edison

Edison es un asistente de voz que armé para mis Meta Quest 3, en realidad mixta. Me pongo el visor, abro una página en el navegador, entro en modo inmersivo y sigo viendo mi cuarto, con paneles flotando encima. Le hablo y me contesta con voz.

El nombre viene de One Piece: Edison es uno de los satélites de Vegapunk, el que piensa.

Es un proyecto personal. No es un producto ni una app que se pueda descargar, y todavía tiene cosas que fallan. Lo armé en abril de 2026, y lo que cuento aquí es cómo estaba en ese momento.

Los videos

El video de arriba es la parte 1: la idea, cómo lo armé y la primera prueba con el visor puesto.

La parte 2 muestra lo que ya hace y lo que todavía falla: tareas, agenda y clima por voz, y un pedido que no salió como esperaba. Está aquí: https://youtu.be/eAniLy-YehY

Cómo funciona

Son dos piezas: el visor y mi computadora, en la misma red wifi.

Meta Quest 3 (navegador, WebXR)
        │  WebSocket seguro (wss), red local
        ▼
Servidor en mi computadora (FastAPI)
  1. whisper.cpp ── tu voz a texto          (local)
  2. router ─┬── charla y pedidos simples ── Ollama, modelo chico (local)
             └── razonar, planificar, código ── modelo en la nube
  3. Kokoro ── la respuesta a voz           (local)
        │
        ▼
Audio de vuelta al visor + paneles flotantes
  • El visor no tiene ninguna app instalada. Es una página con Three.js y WebXR que se abre desde el navegador de las Quest. Para depurar, la misma página funciona en el navegador de la computadora.
  • Todo va por HTTPS en la red local, con un certificado generado con mkcert. No es un detalle: sin HTTPS, las Quest no dan acceso a WebXR ni al micrófono. Nada queda expuesto a internet.
  • La voz se procesa en mi computadora. whisper.cpp pasa el audio a texto y Kokoro convierte la respuesta en voz.
  • Un router decide qué modelo responde. La charla y los pedidos simples van a un modelo chico que corre local con Ollama, y responde en alrededor de un segundo. Lo que necesita razonar, planificar o escribir código va a un modelo en la nube; en mi caso, Claude Code. Si el modelo local falla, la respuesta cae a la nube.

Por eso no digo que sea «100 % local»: la voz sí, y lo simple también, pero lo pesado no corre en mi computadora.

Este es el prompt para replicarlo

Una aclaración antes: no es el prompt con el que armé Edison. Lo construí en varias sesiones, iterando y corrigiendo. Lo que sigue es un prompt que resume la arquitectura y lo que aprendí en el camino, ordenado por fases, para que un agente de código te arme una primera versión funcional.

Qué necesitas

  • Unas Meta Quest 3 y una computadora en la misma red wifi.
  • Una computadora que aguante whisper.cpp, Kokoro y un modelo chico en Ollama. Yo lo corrí en una Mac con Apple Silicon y 16 GB de RAM; en Windows o Linux no lo probé.
  • Un agente de código: Claude Code u otro que pueda crear archivos y ejecutar comandos en tu computadora.
  • Opcional: acceso a un modelo en la nube para las consultas complejas.

Cómo usarlo

  1. Completa los placeholders antes de pegarlo. Son los textos entre llaves dobles:
PlaceholderQué ponerEjemplo
{{NOMBRE_ASISTENTE}}Cómo se llama tu asistenteEdison
{{SO_COMPUTADORA}}Tu sistema operativo y hardwaremacOS con Apple Silicon
{{VOZ_TTS}}Una de las voces de Kokoro en tu idioma(ver la lista de voces de Kokoro)
{{IDIOMA}}El idioma en que le vas a hablarespañol
{{MODELO_LOCAL}}El modelo chico de Ollamagemma3:1b, el que usé yo
{{LLM_NUBE}}El modelo para lo complejoClaude Code, o la API que prefieras
  1. Pégalo en una carpeta vacía con tu agente de código abierto ahí.
  2. Ve fase por fase. El prompt le pide que no avance hasta cumplir los criterios de cada fase y que al terminar te diga qué probar. Esa parte la haces tú, con el visor puesto: el agente no puede probar WebXR en las Quest.
  3. Si algo falla en el visor, pásale el error de las devtools remotas (chrome://inspect con las Quest conectadas). La última sección del prompt ya le avisa de los problemas que encontré.
(Aclaración: este no es literalmente el prompt con el que armé Edison; lo construí en varias sesiones, iterando. Es un resumen de la arquitectura y de lo que aprendí, pensado para que tu agente de código te arme una primera versión.)

Quiero construir un asistente de IA por voz llamado {{NOMBRE_ASISTENTE}} que viva en mis Meta Quest 3 en realidad mixta. Le hablo, me responde con voz y aparecen paneles flotantes en mi cuarto. Trabaja por fases: no avances a la siguiente hasta cumplir los criterios de aceptación de la actual, y al terminar cada fase dime exactamente qué debo probar yo con el visor puesto (tú no puedes probar WebXR en el hardware).

ARQUITECTURA
- Frontend: una página web con Three.js + WebXR (sesión "immersive-ar" con passthrough) que se abre desde el navegador de las Quest. Sin app nativa, sin Unity, sin frameworks XR encima.
- Backend: FastAPI (Python 3.11+) corriendo en mi computadora ({{SO_COMPUTADORA}}), en la misma red wifi que el visor.
- STT: whisper.cpp compilado localmente, con aceleración de mi hardware. Entrada: WAV 16 kHz mono.
- TTS: Kokoro, local, voz {{VOZ_TTS}} en {{IDIOMA}}. Salida: WAV 24 kHz.
- LLM con router: {{MODELO_LOCAL}} vía Ollama (API compatible con OpenAI) para charla y cosas simples; {{LLM_NUBE}} para lo que requiera razonar, planificar o escribir código.
- Transporte: WebSocket (wss) entre visor y backend; POST /voice como alternativa.
- Configuración con pydantic-settings y .env. Nada de claves en el repo. Código en inglés.

REQUISITOS QUE NO SON NEGOCIABLES
- HTTPS obligatorio: WebXR y el micrófono no funcionan en las Quest sin HTTPS. Usa mkcert y genera un certificado que incluya localhost, 127.0.0.1 y la IP de mi computadora en la red local. Pon la IP en una variable de configuración y crea un script para regenerar el certificado si la IP cambia.
- Nada expuesto a internet: sin túneles públicos. CORS limitado a la red local.
- Un script start que levante backend y frontend, y un script setup que compile whisper.cpp, descargue modelos y cree el entorno virtual.
- Un modo escritorio: la misma página debe funcionar en el navegador de la computadora con mouse y teclado, para depurar sin el visor. Agrega atajos de teclado de depuración.
- Mide y registra la latencia de cada etapa (STT, LLM, TTS) en cada turno. Exponla en GET /health junto con el estado de cada componente.
- Organiza el frontend en módulos desde el principio (escena, audio, paneles, red); no lo metas todo en un único index.html.

FASE 1: pipeline de voz en la computadora
- Servicios stt, llm y tts separados. POST /voice: audio entra, audio sale. GET /health.
- Script de prueba por terminal con dos modos: texto (escribo y me responde con audio) y voz (grabo con el micrófono de la computadora).
- System prompt corto: respuestas de máximo 2 o 3 oraciones, texto plano sin markdown ni emojis (la salida se escucha, no se lee).
Criterios: hablo por la terminal y escucho la respuesta; /health muestra los tres componentes en verde; el log muestra la latencia por etapa.

FASE 2 (MVP): hablarle desde las Quest
- Página HTTPS con botón "Entrar en MR" que inicia la sesión immersive-ar.
- Captura de micrófono en el navegador (pulsar para hablar), envío por WebSocket como frames binarios, mensaje de texto para marcar el fin, respuesta en audio y mensajes de estado. Protocolo con prefijos simples (por ejemplo STT:, LLM:, DONE:, ERROR:). Reconexión automática con ping/pong.
- Un panel flotante del asistente con estado (escuchando, transcribiendo, pensando, hablando) y la última respuesta. Los paneles son planos con un canvas como textura.
- Un avatar simple (por ejemplo, un icosaedro con shader) que cambie según el estado y reaccione a la amplitud del audio de la respuesta usando un AnalyserNode.
Criterios: con el visor puesto entro en MR, veo el panel en mi cuarto, le hablo, escucho la respuesta y el panel muestra lo que entendió y lo que respondió. Si el WebSocket se cae, se reconecta solo.

FASE 3: router local/nube
- Función de ruteo con modos configurables: off, local-first, local-only y cloud-only. Por defecto: local-first.
- Heurística de "complejo": consulta larga, palabras de razonamiento (arquitectura, refactor, debug, planifica) o preguntas sobre mis cosas personales (proyectos, tareas, estado). Clasifica por intención, no solo por nombre exacto: whisper deforma nombres propios.
- El modelo local recibe un system prompt propio, corto y muy directivo, con frases literales obligatorias para lo que no sabe. Los modelos de 1B inventan datos con prompts largos.
- Cadena de fallback que nunca devuelve error al usuario: local -> nube -> segunda opción en la nube. Registra qué backend respondió de verdad y por qué. Endpoint GET /llm/status.
- Si la memoria del sistema supera un umbral, no uses el modelo local en ese turno. Usa keep_alive corto en Ollama para liberar RAM.
Criterios: una charla simple responde en local en alrededor de un segundo con el modelo ya cargado; una consulta compleja va a la nube; si apago Ollama, sigue respondiendo; /llm/status muestra la última decisión.

FASE 4: paneles extra y herramientas por voz
- Capa de herramientas que intercepta el texto transcripto ANTES del LLM con patrones: "muéstrame el clima", "mis tareas", "cierra todo". Si coincide, abre el panel y responde con una confirmación corta, sin pasar por el LLM. Evento CONTENT: por WebSocket.
- Sistema genérico de paneles de contenido: imagen, markdown, clima (puede ser simulado al principio), lista de tareas y registro de conversación.
- Interacción: arrastrar, redimensionar y cerrar paneles; scroll con el thumbstick del control y con pinch; guardar la disposición en localStorage.
Criterios: digo "muéstrame el clima" y aparece el panel en menos de 2 segundos; muevo un panel, recargo y sigue donde lo dejé; puedo hacer scroll en MR sin mouse.

FASE 5 (opcional): palabra de activación y delegación
- Palabra de activación con detección de voz en el navegador.
- Delegar tareas largas a {{LLM_NUBE}} o a un agente de código en segundo plano, y que el asistente me avise por voz cuando termine.

PROBLEMAS CONOCIDOS EN LAS QUEST: resuélvelos desde el principio
- Al entrar en sesión inmersiva, el navegador puede suspender el AudioContext y el micrófono deja de captar. Después de iniciar la sesión, llama a resume(), mantén un buffer silencioso en loop para que no se vuelva a suspender y, si el stream del micrófono murió, pide getUserMedia de nuevo.
- Al redimensionar un canvas usado como textura, recrea la CanvasTexture.
- No uses createConicGradient (no está en todos los navegadores de Quest). Los iframes con CSS3DRenderer no se ven en modo inmersivo: prevé un fallback.
- Para depurar en el visor, usa las devtools remotas (chrome://inspect con el visor conectado) y deja logs con prefijo, por ejemplo [audio].

Qué esperar

Es un punto de partida, no Edison terminado. El prompt deja fuera cosas que son propias de mi forma de trabajar, como el panel que muestra mis sesiones de agentes o la personalidad de Edison, y deja la fase 5 como opcional. Lo más probable es que tengas que corregir cosas en el camino, sobre todo en lo que solo se ve con el visor puesto.

¿Lo armaste?

Si lo armas, cuéntame cómo te fue: qué nombre le pusiste, en qué fase se trabó o qué le agregaste. Me encantaría verlo. Me encuentras en:

Recibe los tutoriales nuevos por correo

Te aviso cuando publico un tutorial o un video. Sin spam; puedes cancelar cuando quieras.