medi · propuesta · ago 2026
Propuesta · producto

Medi viste la marca y estrena cerebro.

Medi ya trabaja: agenda disponibilidad, cuenta citas, responde con contexto de ruta. Pero viste el kit de fábrica — un degradado violeta que no existe en la paleta — y piensa con un runtime artesanal cosido a un solo proveedor. Esta propuesta le da las dos cosas que le faltan: el lenguaje aurora clínica con una firma de motion propia (el ECG que se dibuja mientras piensa), y un cerebro durable sobre eve + OpenRouter con la seguridad como doctrina — doctor primero, cada mutación con confirmación, y el scope viviendo siempre en el servidor.

Pieza
Integral · visual + arquitectura
Superficie
Consultorio + admin · un agente
Roles
Doctor primero · matriz lista
Estado
Para decidir

01Lo que hay hoy

inventario honesto

Medi no parte de cero — y eso es la mejor noticia de esta pieza. Hoy conviven un panel funcional con problemas de traje, y un backend correcto en sus decisiones de seguridad pero artesanal en su runtime.

El panel · apps/consultorio

Funciona bien, viste mal

  • Docked / flotante / fullscreen móvil con ⌘J, resize, focus trap y scroll-lock — la ingeniería del panel se queda.
  • El avatar mezcla brand-600 → violet-600: el violeta no existe en la paleta Amedi. Es el hex ajeno clásico.
  • Cards de sugerencia shadcn de fábrica, animaciones animate-in genéricas, typing dots iguales a cualquier chat.
  • Nada en el panel dice «Amedi»: ni la noche, ni la aurora, ni el ECG del isotipo de salud.
El backend · apps/api/src/ai

Seguro en el diseño, artesanal en el runtime

  • ~40 acciones en un registry ya gateado por rol (schedule, doctor, admin, user) — esta capa es oro y sobrevive entera.
  • Mutaciones con flujo de confirmación explícito (PendingActionsBar) — la doctrina correcta, se conserva.
  • Provider factory + gemini.provider + mock: un solo modelo, cero fallback. Este cableado sale entero — no se migra, se retira.
  • prompt.builder + conversation.manager hechos a mano: memoria efímera, sin durabilidad, sin schedules.
La tesis

No es un rewrite: es un trasplante de traje y de cerebro sobre el mismo esqueleto. El panel conserva su ingeniería (portal, posturas, atajos); el backend conserva sus acciones y su gate de confirmación. Cambia lo que se ve (aurora clínica) y lo que piensa (eve + OpenRouter).

02El panel, rediseñado

aurora clínica

La dirección elegida: corona noche con la aurora respirando — la misma escena del login del admin y de aurora auth — y el cuerpo de la conversación en blanco clínico, porque las respuestas largas se leen sobre claro. El violeta muere: el avatar de Medi es el isotipo real de Amedi (la cruz con la venda, vector del manual) en pequeño, y el ECG queda reservado para el loader — la línea que late cuando piensa.

Empty state · la corona aurorapropuesta

Anatomía de la corona: la barra (el isotipo pequeño como avatar + nombre, sin pill de ruta — Medi es uno solo, esté donde esté) y el saludo comparten la escena noche con dos glows que respiran a 7s/9s. El ECG plano bajo el saludo es la línea en reposo — cuando Medi piensa, esa misma línea late. El pie fija la expectativa honesta: Medi propone, tú confirmas.

Conversación · acción con gate de confirmaciónpropuesta

La card de acción es el contrato de seguridad hecho componente: resumen factual con cifras tabulares (día, horario, modalidad), la etiqueta «requiere tu confirmación» en petroleo, y el botón que nombra el resultado — «Abrir el cupo», nunca «Aceptar». En conversación la corona se pliega a barra: la noche queda como techo fino y la lectura sucede sobre blanco. Los mensajes de Medi van sin burbuja — texto sobre lienzo con el avatar mínimo — y los del doctor en burbuja --paper alineada a la derecha.

Las tres posturas · misma ingeniería de hoy

Acoplado — columna a la derecha, el consultorio reflowea con la variable --medi-panel-width que ya existe. El rail noche del sidebar y la corona de Medi comparten escena: la aurora une los dos extremos de la pantalla.

Flotante · desktop

Flotante — lámina --r-lg con la sombra grande, para consultar sin ceder el ancho de la vista.

Móvil · fullscreen ~390px

Móvil — fullscreen con la corona intacta; el scroll-lock y el focus trap actuales no se tocan.

03Pruébalo: dos tools en vivo

demos interactivos

Las dos capacidades que Medi ya tiene, contadas con el lenguaje nuevo. Son simulaciones guionadas — mismo flujo, mismos estados, cero backend. Toca la sugerencia y mira el panel pensar, proponer y ejecutar. La visual de la derecha reacciona igual que lo haría la agenda real.

Demo 1 · bloquear la agendainteractivo
Medi

Hola, Dra. Rivas — dime qué hacemos con tu agenda.

Responde a Medi… ⌘J

Simulación — no toca ninguna agenda real.

Tu semana 4 – 8 ago · tardes
lun 4mar 5mié 6jue 7vie 8 2 pmR.G.M.P. 3 pmA.T.L.D. 4 pmJ.M.C.S. 5 pmE.F.
libre con cita bloqueado

El tool agenda.bloquear es nivel 2: Medi puede proponerlo, pero el bloqueo solo sucede cuando la doctora toca «Bloquear los viernes». Al confirmar, la columna del viernes se apaga en cascada — la agenda reacciona en el mismo gesto.

Demo 2 · leer el díainteractivo
Medi

Buenos días — ¿revisamos tu miércoles?

Responde a Medi… ⌘J

Simulación — datos de ejemplo.

Miércoles 5 consultorio Las Mercedes
8:00
Rosa García control postoperatorio8:00–8:40
9:00
Miguel Paz primera consulta9:00–9:40
10:00
Ana Torres telemedicina10:00–10:30
10:30
30 min libres — ¿un cupo extra?
11:00
Luis Díaz resultados de laboratorio11:00–11:40

El tool dia.resumen es nivel 1: lectura pura, sin confirmación. Medi narra el día y la línea de tiempo pinta cada cita en cascada — y señala el hueco de 10:30 como oportunidad, no como reproche.

La firma de motion · tres gestos, tokens de la casa

El ECG que piensa

Reemplaza los typing dots: la línea de vida se dibuja en 1.5s con --ease-out y se repite mientras Medi razona. Es el isotipo de salud convertido en estado del sistema.

La aurora que late

Los glows de la corona respiran a 7s/9s en reposo y aceleran a ~3s durante el streaming — el panel «respira más rápido» cuando trabaja. Escala y opacidad, nunca color nuevo.

La cascada

Sugerencias y cards entran con --duration-slow + --ease-out, escalonadas 80ms. Las celdas del calendario al confirmar usan --ease-spring — el único rebote permitido.

Reduced motion

Con prefers-reduced-motion todo esto colapsa a estados finales: el ECG aparece dibujado, la aurora queda quieta, cascada y streaming se muestran completos al instante. Ya es ley en el panel actual y la pieza lo respeta — pruébalo activando la preferencia del sistema.

04El cerebro: eve + OpenRouter

arquitectura

eve es un framework de agentes durables donde el agente es un directorio: instrucciones, tools, conexiones y schedules son archivos versionados en el repo. Lo que hoy son cuatro clases artesanales de NestJS pasa a ser contenido declarativo — revisable en PR, testeable por archivo. OpenRouter entra como gateway de modelos: un solo SDK, modelo pinneado por config y fallback automático si el proveedor primario se cae.

El agente como directorio · qué reemplaza a qué

Qué no cambia: el controller de /ai/chat sigue siendo NestJS con los mismos guards JWT; el panel sigue hablando el mismo contrato de streaming. eve corre detrás del API — nunca expuesto directo al navegador.

Un solo agente, todas las puertas

Esta es la naturaleza de eve: Medi deja de ser un asistente cosido a cada ruta y pasa a ser un agente independiente y aislado que sirve consultorio y admin por igual. Los knowledge packs por ruta mueren — lo que decide qué puede hacer Medi no es la página donde está, sino el rol del context sellado (doctor ve sus tools, admin los suyos). La ruta viaja apenas como hint opcional para sugerir mejor, nunca como cerebro. Un solo directorio, una sola memoria durable, permisos por rol.

Un mensaje, de punta a punta
1PanelAPI

«Bloquea mis viernes por la tarde» viaja con el JWT de la doctora. El guard resuelve el perfil y su rol — nada del cliente decide permisos.

2APIeve

El API invoca al agente con el mensaje y un context sellado: doctorId, rol, locale, ruta. El agente solo ve los tools que el rol permite.

3eveOpenRouter

Razona con el modelo pinneado (fallback automático si el primario cae). Sale el mínimo necesario: instrucciones, mensaje, schemas de tools. Nunca la base de datos.

4eveTool

agenda.ver (nivel 1) se ejecuta directo: consulta Prisma scopeada por el doctorId del JWT — el modelo jamás pasa ids de otros doctores.

5evePanel

agenda.bloquear (nivel 2) no se ejecuta: vuelve como acción pendiente y se pinta la card de confirmación. El gate de hoy, intacto.

6PanelAPI

La doctora toca «Bloquear los viernes». La confirmación viaja con su JWT y el id de la acción — no con los argumentos del modelo: el servidor re-valida todo.

7ToolPanel

El tool muta vía Prisma, deja rastro en el audit log (actor, tool, args, resultado) y el panel celebra: card en verde éxito y la agenda actualizada.

OpenRouter · política de modelos

Un gateway, cero lock-in

  • OpenRouter es el único provider. El cableado Gemini se retira completo — no queda como fallback: el fallback vive entre modelos dentro de OpenRouter.
  • Se cablea en agent.ts vía defineAgent como LanguageModel del AI SDK (@openrouter/ai-sdk-provider) — modelo pinneado por env (MEDI_MODEL), fallback declarado, y defineDynamic para A/B de modelos por sesión.
  • Allowlist de proveedores con retención cero de datos: solo providers que no entrenan ni almacenan con nuestros prompts.
  • Presupuesto y rate limit por doctor/día — un tope conocido, no una sorpresa en la factura.
  • Cambiar de modelo = cambiar config, no código. A/B de modelos por flag.
Lo que eve regala

Durabilidad y proactividad

  • Memoria durable: las sesiones del runtime sobreviven deploys y reinicios, con compaction automática al acercarse a la ventana — hoy la conversación vive en un manager en memoria.
  • El gate es nativo: cada tool declara su política de aprobación (always/once/never de eve/tools/approval) y la llamada gateada pausa y reanuda durable — los niveles 2 y 3 no se construyen, se declaran.
  • Evals de primera clase: la prueba de tool-calling en español que elige el modelo se escribe en evals/, junto al agente, y corre en CI.
  • Schedules: el resumen de «tu día» cada mañana como archivo YAML, opt-in del doctor — la sugerencia proactiva del panel deja de ser un placeholder.
  • Skills nativas: procedimientos en skills/ que el modelo carga bajo demanda (load_skill) cuando el pedido lo amerita — el playbook de planear la agenda (ver → proponer → confirmar, jamás borrar cupos con citas) viaja solo cuando se necesita, no en cada turno. Una skill agrega instrucciones, nunca permisos: los tools visibles los decide el rol.
  • Tools = archivos: cada tool se revisa en PR y se testea aislado, igual que las actions de hoy pero sin el boilerplate del registry.
  • El chat streaming del panel no cambia de contrato: la migración es invisible para el frontend.

05Seguridad y permisos

doctrina, no apéndice

Medi lo van a usar doctores sobre datos de salud. La regla madre es una sola: el modelo propone, el servidor decide. Todo lo demás — niveles, matriz, anti-fuga — son consecuencias de esa regla.

nivel 1
Leer

Consultas sin efectos: agenda.ver, dia.resumen, pagos.resumen. Se ejecutan directo, siempre scopeadas al doctor del JWT. Devuelven agregados y slots — nunca historias clínicas.

nivel 2
Mutar, con gate

Crean o cambian agenda: agenda.crear, agenda.bloquear, agenda.semana. Vuelven como card de confirmación con resumen factual; solo el toque del doctor las ejecuta.

nivel 3
Destruir, reforzado

agenda.borrar y lo que elimine datos: card en rojo derivado, el resumen expandido por defecto y el botón nombra la pérdida — «Borrar 8 cupos del viernes». Si hay citas de pacientes dentro, Medi se niega y ofrece reagendar.

La matriz tools × rol · doctor hoy, el resto ya diseñado
ToolNivelDoctor · mvpSecretaria · previstaAdmin · prevista
dia.resumen1 · lee✓ directo del doctor que asiste
agenda.ver1 · lee✓ directo del doctor que asiste
pagos.resumen1 · lee✓ directo— sin montos
agenda.crear / agenda.semana2 · muta✓ con confirmación✓ confirma el doctor
agenda.bloquear2 · muta✓ con confirmación✓ confirma el doctor
agenda.borrar3 · destruye✓ reforzado
plataforma.conteos1 · lee✓ agregados, sin PHI

La lectura clave de la matriz: la secretaria nunca ejecuta una mutación sola — Medi le prepara la acción y la confirmación viaja al doctor (el mismo patrón de la sala de espera). El admin ve números de plataforma, jamás datos clínicos de un paciente en un chat. Crecer de rol = activar columnas ya diseñadas, no rediseñar.

Anti-fuga · cinco reglas

El scope vive en el servidor

  • Cada tool recibe doctorId del JWT del request — jamás de los argumentos que genera el modelo.
  • El modelo nunca toca Prisma: los tools devuelven agregados y slots tipados, la base no entra al contexto.
  • Hacia OpenRouter viaja lo mínimo: agenda y conteos en el MVP. Sin historias clínicas en el prompt mientras no haya una decisión explícita de PHI.
  • Audit log por tool call: actor, tool, argumentos, resultado, timestamp — la agenda de un doctor es dato sensible.
  • Kill switch conocido: MEDI_ENABLED ya existe y se conserva; apagar Medi nunca rompe el consultorio.
La UI también es seguridad

Confianza que se ve

  • La card de acción muestra exactamente lo que va a pasar, con cifras tabulares — el resumen es el contrato.
  • El botón nombra el resultado («Bloquear los viernes», «Borrar 8 cupos») — nunca un «Aceptar» ambiguo.
  • El pie del panel dice la verdad siempre visible: «Medi puede equivocarse — las acciones siempre te piden confirmación».
  • Deshacer donde se pueda: el bloqueo recién aplicado ofrece «Deshacer» durante unos segundos antes de asentarse.

06La receta, por fases

nada breaking

Tres fases independientes — cada una entrega valor sola y ninguna rompe la anterior. El traje no espera al cerebro.

1

El traje

Restyle del panel en components/ai-panel/: muere el violeta, entra la corona aurora, el ECG pensante y la cascada. Solo frontend — el backend actual sigue sirviendo igual. Es la fase que el doctor nota al día siguiente.

2

El cerebro

El agente eve nace en apps/api/agents/medi/ detrás de MEDI_RUNTIME=eve. Mismas rutas, mismo contrato de streaming; las actions se portan a tools con sus niveles. Conmutable por flag — A/B contra el legacy, rollback en un env var.

3

La poda

Con eve estable: sale el cableado Gemini entero (factory, provider, mock) junto a prompt builder y conversation manager; la memoria pasa a ser durable y se enciende el primer schedule (resumen matinal, opt-in). La poda es amplia por diseño — del módulo ai/ sobreviven guards, controller y la lógica de las actions hecha tools.

Decisión pendiente

El modelo primario en OpenRouter y su fallback se eligen en fase 2 con una prueba real sobre los tools de agenda (tool-calling fiable en español > benchmark genérico). La pieza no pinnea un modelo: pinnea la política — retención cero, fallback declarado, presupuesto por doctor.

El mismo Medi que ya trabaja — con la marca puesta y un cerebro que no se apaga.

El panel conserva toda su ingeniería y gana la aurora, el ECG y la cascada. El backend conserva sus acciones y su gate — y gana durabilidad, multi-modelo y proactividad. La seguridad no se negocia en ninguna fase: el modelo propone, el servidor decide, el doctor confirma.

Se decide acá

Dirección aurora clínica del panel y la arquitectura eve + OpenRouter con su matriz de permisos.

Fase 1

El traje: restyle del panel, solo frontend — visible en días.

Fase 2

El cerebro: agente eve tras flag conmutable, mismas rutas.

Fase 3

La poda del runtime artesanal y el primer schedule proactivo.