Hoy os toca lo que ya sabéis hacer. La diferencia es qué puede salir mal cuando lo que despliegas decide.
90 de 180 minutos son práctica. Y hoy la práctica es vuestro oficio, así que probablemente iremos más rápido de lo previsto.
Lo que dijisteis en el kick-off, y qué se ha movido. Empezamos por aquí porque es lo único honesto que cierra un programa.
Vuestros números del primer día. No una media del sector.
Falta de un portal donde podamos ver con claridad lo que tiene en servicio un cliente. Esto me lleva a preguntar al resto de mis compañeros.
Vuestro dolor número uno. Dos de vosotros lo escribisteis casi igual.
Clientes, sedes, subredes, dispositivos y servicios. Con búsqueda semántica. Exactamente el portal que pedíais.
Lee correo y mensajería, clasifica, abre ticket, consulta el portal y escala a una persona cuando no lo tiene claro.
Es una prueba de concepto en un servidor de verdad, no un servicio que ya le facturáis a un cliente. Decirlo así evita que se venda solo.
Capacidad adquirida (lo que ahora sabéis hacer) y rendimiento en operación (lo que ahorra de verdad). Lo segundo pide uso real durante meses.
Tres cosas medidas esta semana sobre vuestro propio código. Las tres son invisibles en local, y ninguna se ve leyendo el código.
El daño de una caída es que deja de servir. Molesto, acotado, y se nota enseguida.
Contesta a un cliente, abre un ticket, escribe en el inventario. El daño no es dejar de hacer: es hacer lo que no era.
Una factura plana. La presupuestas una vez al año y te olvidas.
Y se puede quedar sin saldo un martes a las tres de la tarde. Lo vimos esta semana, y lo enseño en dos slides.
La tercera diferencia es la peor: un servicio falla de forma evidente; un agente falla de forma convincente. La respuesta está bien escrita y está mal.
Portal sin migrar. /clientes/ devuelve 500 en los tres casos. Lo que cambia es lo que contesta el /health. Los tres, medidos hoy.
return {"status": "ok"} -> 200. No comprueba nada. Un monitor de uptime habría dicho que todo iba bien durante horas.
SELECT 1 contra la base -> 200 {"base":"ok"}. La base está viva y contesta. Lo que falta es el esquema.
Preguntar por una tabla que el portal necesita -> 503 {"base":"sin migrar"}. Y con la base apagada, 503 {"base":"caida"}.
Comprobar que la dependencia responde no es comprobar que puedes servir. El paso 2 es el que se escribe en el 90 % de los sitios, y es el que hay que mirar con lupa.
Seis avisos seguidos sin procesar. El error no venía del agente ni del modelo: venía de la factura.
"You requested up to 65536 tokens, but can only afford 31725"
Sin declararlo, se aplica el máximo del modelo. Y el proveedor exige saldo para cubrir ese máximo en cada llamada, no lo que de verdad gastas.
Declarar el tope. Baja el saldo exigido por llamada unas 16 veces.
El límite de la clave es distinto del saldo de la cuenta. Hoy mismo, esta clave: limit 10 $ · usage 10,08 $ · remaining 0. Devuelve 403 antes de llamar al modelo.
Y no se arregla con buena voluntad: se arregla con una variable bien escrita. Medido hoy.
Abierto además a escritura, porque el agente actualiza el portal por esos mismos endpoints.
El valor que espera el código es activa. Con cualquier otro, el portal se queda abierto y solo escribe un aviso en el log. No falla cerrado.
Salvo tres rutas declaradas: /health, /portal/acceso y /portal/escalacion.
El monitor tiene que poder preguntar; la puerta no se puede cerrar por dentro; y la escalación se abre desde un móvil, fuera de vuestra red.
Cada uno su instancia, con el runbook en la mano. Cuarenta y cinco minutos. Aquí es donde se cae una sesión, así que este runbook está ensayado.
Imagen pgvector/pgvector:pg16. La de Postgres normal no trae la extensión vector y la migración de búsqueda semántica falla contra ella.
Puerto 8000. El comando de arranque se cambia: alembic upgrade head antes de uvicorn. Son 6 migraciones.
Sin puerto: no tiene interfaz, se le mira por los logs. Una sola réplica, o dos agentes contestan dos veces al mismo cliente.
Volumen persistente, o hay que reescanear el QR en cada redespliegue. Nunca público: quien alcance ese puerto manda mensajes en vuestro nombre.
Dos ficheros distintos: el portal usa Dockerfile y el agente usa Dockerfile.agente. El build tarda 34 segundos en el servidor.
Van idénticas en portal y en agente. Una deriva entre los dos da síntomas muy difíciles de diagnosticar.
Sin ponerla, el valor por defecto del código es el modelo más caro. Fijadla.
Las únicas conversaciones de las que el agente acepta avisos. Sin ella el canal no se monta, a propósito.
Vacía, el aviso se queda bloqueado y no lo recibe ninguna persona.
El mismo valor en los dos servicios: uno firma y el otro comprueba. Si no coinciden, el portal rechaza los enlaces que manda el agente.
Prueba que hay un proceso vivo. Y nada más que eso. No prueba que la base esté migrada.
Esta es la que de verdad prueba que migró. Si da 500, revisad el comando de arranque del portal.
Con el portal cerrado necesita credencial. Sin ella, 401 y es correcto.
Un ciclo sano registra N pasos, desenlace_registrado=True. Si el servicio sale de inmediato, leedle los logs antes de tocar nada: si falta una credencial, el arranque dice cuál y para. Eso es el control funcionando.
Tres cosas, y ninguna es un cuadro de mandos bonito: un health que diga la verdad, logs que se puedan leer, y un backup restaurado.
Medido hoy con OpenWA caído y el portal levantado:
Y aquí hace bien: el portal sí puede servir el inventario sin mensajería.
No se rompe: se arrastra. No todo lo que va mal es un 503.
Si la respuesta es sí, no va en el health. Cada dependencia que metéis ahí es una falsa alarma esperando.
El portal y el agente no tienen ninguno. Y el agente espera al portal con service_started: arrancado no es sano.
Esta frase es vuestra, no nuestra. Se la decís a vuestros clientes. Hoy se la aplicamos a esto.
Sobre el servicio de base de datos. Antes del primer incidente, no después.
En una base de pruebas, y comprobar que sirve. Si no se ha restaurado, no sabéis si tenéis backup: sabéis que tenéis ficheros.
El inventario de clientes y el histórico de conversaciones de soporte. El código está en el repositorio; esto no.
Vive en un volumen, no en la base. Si no se respalda, se pierde la vinculación y toca reescanear.
Hay unos objetivos escritos. Se miden. Y se compara con lo que estimamos. Si la estimación estaba mal, se dice y ya está.
Objetivo declarado antes de medir: p95 por debajo de 500 ms y menos del 1 % de errores.
Con 10 en paralelo: 191/s. Con 50: 192/s. Con 100: 193/s. El caudal no sube. Lo único que sube es la espera.
Meter más tráfico en un enlace lleno no da más caudal: da más cola. Aquí pasa exactamente lo mismo, y por la misma razón.
Si hiciera falta más caudal, se replica el portal. Subir la concurrencia contra una sola instancia solo empeora la latencia de todos.
Su latencia la manda el proveedor del modelo: en la S4 medimos 7,2 s por clasificación. Se mide aparte, con objetivo aparte.
python scripts/prueba_carga.py. Da veredicto y termina con error si no se cumple el objetivo: se puede meter en un pipeline.
Medido contenedor a contenedor en el servidor, hoy.
El único bloque donde la IA escribe sobre el sistema en vez de operarlo. Corto a propósito: es lo más fácil de vender y lo más fácil de sobrevender.
Un runbook a partir del código real, un inventario de endpoints, un resumen de qué hace cada módulo. Lee la fuente y la cuenta.
Con los logs delante, redacta el parte y el porqué mucho más rápido que vosotros. Y sin que dé pereza hacerlo.
Esa razón no está en el código. Se la inventa, y suena perfectamente razonable. Es el fallo más caro de detectar.
Si el dato no está en el portal, lo rellena. Y ese documento va a acabar delante de un cliente vuestro.
La regla de las cinco sesiones, otra vez: si la afirmación no se puede comprobar contra algo, no se publica.
La mitad comercial del encargo. Coste por instancia, qué hacer cuando un proveedor falla, qué licencias os atan, y la hoja de ruta.
Es literal de la sesión pasada. Y tiene respuesta, que además es barata.
El código no habla con un fabricante: habla con una pasarela que enruta. Cambiar de modelo es cambiar una variable de entorno.
Si uno se cae o sube el precio, se cambia la variable y se reinicia. Es la misma lógica que tener dos operadores.
Hoy el cambio es manual. Automatizarlo es trabajo, y es una línea del roadmap, no algo que ya esté.
Una clave por instancia, con su tope. Un cliente no puede gastarse el saldo de otro. Lo aprendimos por las malas esta semana.
Clasificar cuesta 23 veces menos que resolver, y la diferencia es la que importa cuando le pongáis precio a esto. Hasta esta mañana yo os habría enseñado solo la cifra pequeña — y habría estado diciendo la verdad y engañándoos a la vez.
Para uso interno da casi igual. Para revender, no.
Es una conexión no oficial y su licencia tiene condiciones. Hay que leerla antes de facturarla, no después. Os dejo dónde mirar.
En la S4, a uno de vosotros le banearon dos números, uno de forma irrecuperable. Número dedicado y desechable, siempre.
Cuesta dinero y pide dar de alta el número, pero no la banean. Si esto se vende a un cliente, es el camino.
El conector existe y la guía está escrita. Falta el registro de la aplicación, y esos permisos los tenéis vosotros.
Sin esto no se puede enseñar a un cliente. Es configuración y unas pocas líneas, no un proyecto.
El portal vacío no ahorra nada. Con vuestros clientes dentro, ataca directamente el dolor número uno del kick-off.
Uno solo. Correo corporativo es el candidato natural, en cuanto esté el registro de la aplicación.
Aquí es donde se sabrá si esto ahorra tiempo de verdad. No antes, y conviene no fingir que sí antes.
Una instancia por cliente, con su clave y su tope. Failover automático de proveedor. Y la licencia resuelta.
Desplegada, supervisada y con una prueba de carga que da veredicto.
Contra vuestro propio baseline, separando lo que sabéis hacer de lo que ya ahorra.
El registro de la aplicación de correo, el alta del número, y meter el inventario real. Sin eso, esto sigue siendo una prueba de concepto.
Para lo que salga: dudas, un despliegue que se atasque, o la siguiente pieza.
Y la frase que resume las cinco sesiones: lo que no está medido, no está hecho.
Cinco sesiones. Y lo que de verdad
se lleva uno es la costumbre de medir.