La idea en una frase
Una cuenta cada vez, en anillo, y siempre la siguiente que sirva
Antes había dos cuentas que se intercambiaban el papel (ADR 0110): un ciclo de dos. El enjambre lo generaliza a N. Añadir la tercera, la cuarta o la décima es una línea en el .env, y ninguna parte del código sabe cuántas hay. En producción hay tres.
Con el gasto medido en noviembre (unos 40 puntos de semana al día, y cada cuenta da unos 14 al día), tres cuentas cubren la semana justo y cuatro dan margen.
Dos motores: el enjambre o OpenRouter
El enjambre es uno de los dos motores del agente, y se elige por persona (decidido el 10/11/2026). Antes de mirar ninguna cuenta, se decide el carril de la corrida. Solo en el carril claude entra en juego el anillo.
Desliza para ver el diagrama entero →
engine_for elige el motor. Solo si sale claude se llama al código de cuentas: el anillo, en llm_mode.| Por defecto | claude. Una persona nueva arranca en el enjambre. |
| Quién lo cambia | El superadmin, desde la consola, por empresa y por persona, en caliente. Gana lo más concreto: persona, luego empresa, luego el por defecto. Se guarda en runtime_flags (engine.default, engine.business.<id>, engine.membership.<id>), con 15 s de caché, como usage/switches.py. |
| Sin respaldo cruzado | El enjambre agotado no pasa a OpenRouter: su escalera termina como se ve en «Si se acaban todas». OpenRouter caído o sin saldo tampoco pasa al enjambre. |
| Qué se apunta | Las corridas de OpenRouter quedan en el consumo como openrouter y sin cuenta de Claude: no gastan cupo del anillo. |
El detalle del motor está en el ADR 0143 y en docs/changes/active/2026-11-motor-del-agente-por-persona.md. Los dos motores están en producción.
El carril claude, en vivo
Abajo, una semana entera del enjambre pasando en un minuto.
- 1en usorenueva jue 11:0062 %
- 2listarenueva lun 09:00 · con uso extra8 %
- 3listarenueva sáb 18:00 · la usa alguien más30 %
- 4listarenueva vie 18:00 · con uso extra35 %
- 5listarenueva mar 10:0050 %
Lo que va pasando
Simulación con datos inventados: una semana en un minuto. Cada cuenta renueva su semana a una hora distinta, y la 3 la usa también alguien de fuera. «Semana sin cupo» enseña la escalera de pago entera.
Ya pagado. Se gasta primero.
Uso extra o clave de API: factura por token.
La cuenta actual.
Hasta su hora de renovación.
Aviso al equipo.
El ciclo
Cómo pasa de una cuenta a otra
Todas las corridas del carril claude (chat, rutinas, avisos, memoria) usan la cuenta actual. Solo cuando topa con su límite, o empieza a pagar uso extra, se busca otra, empezando por la siguiente del anillo.
Desliza para ver el diagrama entero →
| Situación | Qué hace |
|---|---|
| La actual topa con su límite | La apunta como agotada hasta su hora de renovación, que viene en el propio aviso de límite, y busca a partir de la siguiente. Vale igual para la ventana de 5 horas que para la semana. |
| La actual empieza a pagar uso extra | Si otra del anillo sirve, pasa a ella antes de pagar nada. El uso extra se deja para cuando no queda ninguna. |
| La siguiente está agotada | La salta y mira la de después. |
| Llega al final del anillo | Sigue por la primera. |
| Ninguna sirve | Pasa a la escalera de pago (siguiente sección) y manda un correo. |
| Otra se renueva mientras la actual va bien | Queda lista, sin cambiar nada: espera su turno. |
| El mensaje que topó | Se reintenta una vez en la cuenta nueva si murió al empezar. Si ya había hecho algo, no se repite. |
| Un token deja de entrar | Esa cuenta se aparta hasta que cambie su token, se manda un correo y el ciclo sigue sin ella. |
| Las que esperan | Una llamada mínima cada hora a cada una, para saber su % y cuándo se renueva. Si la encuentra agotada, la apunta una sola vez en la línea de tiempo y el anillo la salta. |
| La del perfil, al 99 % | Si una cuenta del anillo es la sesión del perfil (la palabra perfil en la lista), el monitor de cada 10 minutos la da por agotada al 99 % de su semana, sin esperar a que falle un mensaje. Las cuentas de token cambian al topar. |
Si se acaban todas
La escalera de pago, y la vuelta
Primero se gastan todos los planes, que ya están pagados. Si se agotan todos y ninguno se ha renovado todavía, se usa el uso extra de cualquier cuenta que lo tenga y, después, la clave de API. En cuanto una cuenta se renueva, se vuelve a su plan.
Desliza para ver el diagrama entero →
| Escalón | Qué se paga | Cuándo se sale |
|---|---|---|
| 1 y 2 Planes | Nada más: ya están pagados. | Todas agotadas y ninguna renovada. |
| 3 Uso extra | A precio de API, en la factura de esa cuenta. | Ninguna lo tiene activado, o todas llegaron a su tope del mes. El tope se apunta por cuenta y por mes. |
| 4 Clave de API | Por token, con su tope de gasto. | Sin saldo. No se vuelve a probar en 24 h. |
| La vuelta | Nada: se vuelve a un plan. | Desde la API, a la hora de renovación más cercana se vuelve a probar el plan. Desde el uso extra, el siguiente mensaje pasa a la primera cuenta que vuelva a servir. |
Dos reglas
Lo que hace que el ciclo funcione con N cuentas
Las dos parecen detalles, pero sin ellas el anillo se vacía antes de tiempo o se salta cuentas llenas.
Regla 1 · Una cuenta fija, no una por mensaje
Vale para todas las personas del carril claude. La alternativa era repartir: un mensaje por la 1, el siguiente por la 2, el siguiente por la 3. Parece más justo y sale peor. Aquí van doce mensajes seguidos de una misma conversación, por los dos caminos.
| Fija | Alternando | |
|---|---|---|
| Caché | Leer la historia cuesta 0,1 por token. | Reescribirla cuesta 1,25 por token, unas 12 veces más. Las cuentas se vacían antes. |
| Renovaciones | Se agotan de una en una, con las renovaciones repartidas por la semana. | Se agotan todas casi a la vez: cuando una no da más, las demás tampoco. |
Regla 2 · Si muchas conversaciones topan a la vez, se cambia una sola vez
Spen corre en cinco procesos a la vez (el backend y cuatro workers). Cuando la cuenta actual se agota, todas las conversaciones que estaban en marcha lo descubren casi en el mismo segundo, y cada una intenta cambiar de cuenta. Con dos cuentas da igual, porque «la otra» siempre es la misma. Con N, no.
Ejemplo: a las 14:00:00 se agota la cuenta 1 y cinco conversaciones (A a E) topan con el límite a la vez. Las cuentas 2 a 5 están llenas.
- A
- B
- C
- D
- E
- A
- B
- C
- D
- E
En la base es una sola orden atómica: cambiar la actual solo si todavía es la que se agotó.
Trazabilidad, consola y avisos
Qué cuenta pagó cada cosa, dónde se ve y quién se entera
Antes lo gastado se apuntaba por hueco («plan» o «backup»), y el hueco principal tuvo tres cuentas distintas en dos semanas. Ahora cada llamada se apunta contra la cuenta real, que se reconoce por la huella de su token, nunca por el token.
| Qué se apunta | Dónde | Para qué |
|---|---|---|
| Cada cuenta: cuál es la actual, si está agotada y hasta cuándo, si está apartada o su token no entra, y su última lectura (ventanas de 5 h y de la semana) | runtime_flagsuna clave por cuenta, de la casa | El estado del anillo, compartido por el backend y los workers. La consola lo lee de la base en cada visita. |
| Cada suceso: cambio de cuenta (de cuál a cuál y por qué), agotada, paso al uso extra o a la API, sin salida, token roto, vuelta a la suscripción, apartada y devuelta | claude_account_eventstabla de la casa | La línea de tiempo de la consola: cuándo entró y salió cada una, y por qué. |
| Cada llamada al modelo | usage_entries.claude_accountla clave de la cuenta; via dice plan (o backup si era otra del anillo), extra o api, y openrouter en el otro motor, donde la cuenta va vacía | Cuánto gastó Spen con cada cuenta, por persona, empresa y tipo de trabajo. |
| Uso ajeno | Se calcula en la lectura de cada hora: la semana de una cuenta que espera sube 3 puntos o más sin que Spen haya apuntado nada con ella | Saber si alguien más usa la cuenta: un correo por cuenta y semana, y los puntos, en la consola. |
En la consola de superadmin
Está en Proveedores (/consola/proveedores), con una versión corta en el Resumen: el anillo pequeño, por dónde se paga y la semana de la cuenta en uso. La consola lee el anillo de la base en cada visita, así que enseña lo mismo que usa el worker en ese momento.
Capturas de la consola de verdad, con datos inventados: un anillo de siete cuentas, la 1 en uso y la 2 agotada.
Desliza para ver la captura entera →
Desliza para ver la captura entera →
Desliza para ver la captura entera →
Desliza para ver la captura entera →
| Botón | Qué hace |
|---|---|
| Leer las cuentas ahora | Lanza la lectura de cada hora en el momento, sin esperar a la siguiente. |
| Hacer actual en el menú de cada cuenta | Pasa a esa cuenta en el momento. No deja si su token no inicia sesión. Si se estaba pagando por la clave de API, se vuelve a su plan. |
| Apartar y devolver | Saca una cuenta del anillo sin tocar el .env; si era la actual, pasa a la siguiente. Al devolverla espera su turno: no vuelve a ser la actual. |
Cada botón queda apuntado con quién lo pulsó, y el cambio, en la línea de tiempo.
Los correos
Llegan en texto plano a cada dirección de SUPPORT_EMAIL (una o varias, separadas por comas; a cada una le llega el suyo). Antes estos avisos iban por WhatsApp a ADMIN_WHATSAPP_ALERTS, que en Spen está vacío, y no le llegaban a nadie. Los cambios normales entre cuentas no mandan correo: quedan en la consola.
| Cuándo | Qué dice | Cuántas veces |
|---|---|---|
| queda poco | El cupo que queda en todo el anillo da para menos de 24 h al ritmo de las últimas horas, y no llega a la próxima renovación. | Una vez por incidente |
| todas agotadas | Se pasa al uso extra de la cuenta N, que se paga aparte. | Una vez |
| sin uso extra | Se pasa a la clave de API. | Una vez |
| sin salida | Ni uso extra ni API: los mensajes fallan. | Al empezar y cada 3 h mientras dure |
| token roto | La cuenta N no inicia sesión: hay que sacar su token otra vez. | Una vez por token |
| uso ajeno | El % de la cuenta N sube sin que Spen la use. | Una vez por cuenta y semana |
| recuperado | Se vuelve al plan de una cuenta después de haber pagado por uso. | Una vez |
Así llega el que da tiempo a reaccionar (las cifras son inventadas):
SUPPORT_EMAILAl ritmo de las últimas horas (unos 1,66 puntos por hora), el cupo que queda en el anillo da para unas 18 h. La próxima renovación es el 19/11 11:00 UTC, dentro de 30 h.
Para estirarlo: añadir una cuenta al anillo, o pasar a otro motor a quien más gasta desde la consola.
Las cuentas:
- cuenta 1: agotada hasta el 19/11 11:00 UTC, 100 % de la semana, renueva el 19/11 11:00 UTC
- cuenta 2: agotada hasta el 23/11 09:00 UTC, 100 % de la semana, renueva el 23/11 09:00 UTC
- cuenta 3: en uso, 70 % de la semana, renueva el 21/11 18:00 UTC
Consola: spen.ai/consola/proveedores
En marcha
Añadir o quitar una cuenta, y lo que ya se ha comprobado
Añadir la cuenta N+1
Cuentas en el anillo: 4
Una sola línea en el .env, aquí partida para leerla. Una línea más y, al arrancar, una cuenta más en el anillo, al final.
- Sacar su token.
claude setup-tokencon esa cuenta, una vez. Vale un año. - Añadirlo al final de
CLAUDE_ACCOUNT_TOKENSen el.envde la caja.El orden de la lista es el orden del anillo. La palabraperfilen la lista es la sesión del perfil del CLI, en lugar de un token. - Recrear los contenedores en un hueco sin mensajes.Es el único paso con espera, y va como cualquier despliegue: con un sí explícito y una copia de la base antes.
- Al arrancar, entra al final del anillo.Se la reconoce por los 12 primeros caracteres de la huella de su token, nunca por el token. Su semana se lee en la lectura de cada hora, o al pulsar «Leer las cuentas ahora».
- Para quitar una, se borra su línea.Sale del anillo y de la consola. Sus sucesos y su consumo se quedan en la base, con su clave.
- Si un token deja de entrar, se cambia en su sitio.Mismo puesto en la lista, token nuevo. La consola la sigue llamando por su número; su clave cambia, porque sale de la huella del token.
Lo que ya se ha comprobado
| Qué | Cómo | |
|---|---|---|
| El anillo con N cuentas, el cambio único entre procesos y la escalera entera | Pruebas del backend contra Postgres (test_claude_ring, test_claude_ring_db) | ✓ |
| Los siete correos: uno por incidente, con los números en castellano | test_claude_notices | ✓ |
| La consola: lo que enseña, los tres botones, y que nunca sale un token ni la clave de API entera | test_claude_ring_console y las pruebas del dibujo del anillo | ✓ |
| En producción con tres cuentas, desde el 12/11 a las 03:44 UTC | El 12/11 a las 17:05 una cuenta se agotó y se pasó a la siguiente que servía, saltando la agotada | ✓ |
| El aviso de uso ajeno | Saltó el 12/11 con una cuenta que subía sin que Spen la usara, y la base lo confirmó: Spen no la había usado | ✓ |
| La consola nueva, la de las capturas | En producción | ✓ |
Decisiones
| 1 | hecho Los correos van a SUPPORT_EMAIL, una o varias direcciones separadas por comas; a cada una le llega el suyo. |
| 2 | hecho «Queda poco» avisa con menos de 24 h de cupo (CLAUDE_LOW_RUNWAY_HOURS). |
| 3 | hecho La consola lleva botones para leer las cuentas ya, hacer actual una y apartarla o devolverla. |
| 4 | por ahora no El anillo no admite claves de API como miembros: la vía de pago por uso es el motor openrouter. |
| 5 | abierto La clave de API de producción no tiene saldo desde el 13/11 a las 09:48 UTC. Mientras no se le cargue, el fondo de la escalera es el uso extra, y si ninguna cuenta lo tiene, los mensajes fallan hasta la primera renovación: pasó el 13/11 entre las 09:48 y las 11:00 UTC. |
| 6 | abierto Que las cuentas de token cambien también al 99 % de su semana, como la del perfil, con el porcentaje que trae cada corrida, en lugar de esperar a que un mensaje tope. |