“Spotify redujo 90% los tokens de Claude Code”

No fue una optimización aplicada a toda la ingeniería de Spotify ni una mejora interna de Claude: fue un experimento con Portal by Spotify que delegó las tareas intensivas en entrada y salida a un modelo más económico.

La idea detrás del resultado sí es importante: un agente de programación no necesita utilizar su modelo más capaz para cada archivo que lee ni para cada bloque de código repetitivo que genera.

Qué hizo realmente Spotify

Dimitri Mazmanov, Principal Product Manager de Spotify, describió un flujo personal en el que Claude Code conserva las tareas que requieren razonamiento, mientras que Gemini 2.5 Flash funciona como modelo auxiliar para procesar grandes cantidades de texto y generar código predecible.

En las pruebas publicadas por Spotify Engineering, el sistema se evaluó sobre un monorepo Java mediante cuatro escenarios. Las tres pruebas cuantificadas de lectura consiguieron reducciones del 82%, 94% y 94% en los tokens que entraban al contexto de Claude. La media para esas lecturas masivas fue cercana al 90%.

No significa que cualquier sesión de Claude Code vaya a consumir 90% menos. Tampoco significa que el trabajo desaparezca: los archivos siguen siendo procesados y, por tanto, siguen consumiendo tokens en el modelo auxiliar. El ahorro ocurre en la parte más cara del flujo, porque Claude recibe un resumen pequeño en lugar del contenido completo.

El problema: usar el modelo más caro para mover texto

Un agente de código combina varios tipos de trabajo:

Archivos grandes pasan por un modelo auxiliar que comprime los tokens antes de enviar un contexto reducido al modelo de razonamiento
Figura 1. El modelo auxiliar procesa el volumen de archivos y entrega un contexto reducido al modelo avanzado.

  • Explorar archivos para localizar una función.
  • Leer implementaciones completas para responder una pregunta concreta.
  • Comparar patrones repetidos entre pruebas.
  • Generar configuración, stubs o boilerplate.
  • Depurar condiciones de carrera.
  • Tomar decisiones de arquitectura.

Las primeras cuatro actividades pueden consumir mucho contexto sin requerir el mismo nivel de razonamiento que las últimas dos. Leer 7,000 líneas para identificar qué métodos acceden a la base de datos es principalmente una operación de búsqueda, extracción y compresión. Detectar un error sutil de concurrencia exige otro nivel de análisis.

Si ambas tareas se ejecutan con el mismo modelo, se paga capacidad de razonamiento avanzada incluso cuando el cuello de botella real es la cantidad de texto.

La solución de Spotify separa estas responsabilidades en tres rutas: las lecturas masivas van a un modelo rápido que devuelve un resumen compacto; el boilerplate va a un modelo rápido que escribe el resultado en disco; y el debugging o la arquitectura permanecen en Claude.

Claude continúa coordinando el trabajo, pero deja de absorber todo el material intermedio.

Dos workers especializados

La implementación utiliza AiKA Modes, agentes declarativos ejecutados mediante Portal by Spotify. Cada modo define sus instrucciones, modelo, temperatura y herramientas disponibles. La documentación de AiKA Modes confirma que un modo puede seleccionar un modelo diferente, incorporar herramientas MCP y publicarse para reutilizarse dentro de una organización.

El experimento configura dos modos.

bulk-reader: leer mucho y devolver poco

bulk-reader recibe uno o varios archivos junto con una pregunta concreta. Utiliza Gemini 2.5 Flash para leer el corpus y devuelve únicamente una respuesta estructurada y breve.

Por ejemplo, en lugar de introducir dos servicios completos en el contexto de Claude para preguntar qué métodos consultan una base de datos, el worker procesa los archivos y responde con los nombres y ubicaciones relevantes. Claude recibe el resultado útil, no miles de líneas de entrada.

Cada invocación es efímera. Si hay una segunda pregunta, los archivos vuelven a enviarse al worker. Parece repetitivo, pero esa repetición ocurre fuera del contexto costoso que se intenta proteger.

code-writer: escribir sin devolver el archivo a Claude

code-writer se ocupa de pruebas repetitivas, archivos de configuración, stubs y otros resultados que pueden derivarse de un patrón existente. Recibe una especificación y un archivo de referencia, genera el contenido y puede escribirlo directamente en disco.

Este detalle evita dos consumos:

  1. Claude no necesita leer todos los ejemplos utilizados como referencia.
  2. El código generado no tiene que regresar completo al contexto de Claude.

El archivo de referencia es obligatorio porque limita la generación al estilo real del proyecto. Sin esa referencia, el modelo económico produciría código genérico que podría no respetar nombres, estructura o convenciones locales.

El router no es solo un prompt

La primera versión consistía en reglas escritas en CLAUDE.md. Claude debía interpretar esas instrucciones y decidir por sí mismo cuándo delegar. El problema era que las reglas eran recomendaciones: el modelo podía ignorarlas y cada repositorio necesitaba mantener su propia copia.

La versión actual utiliza un plugin llamado shunt. Su arquitectura tiene tres capas.

1. Hooks que hacen cumplir la decisión

Antes de cada llamada a una herramienta, el plugin inspecciona la operación mediante hooks PreToolUse. La documentación oficial de Claude Code explica que estos hooks se ejecutan antes de una herramienta y pueden permitir, modificar o bloquear el flujo según su configuración.

shunt registra dos controles:

  • check-file-size intercepta lecturas completas. Si un archivo supera 350 líneas de forma predeterminada, bloquea la operación y dirige a Claude hacia bulk-reader.
  • check-bash-read detecta intentos equivalentes mediante cat, head, tail, less o more.

Las lecturas específicas con desplazamiento o límite sí pasan. Si Claude ya sabe qué fragmento necesita editar, no tiene sentido enviar esa sección a otro modelo.

El umbral puede cambiarse mediante SHUNT_MIN_LINES. Su función no es encontrar un número universal, sino evitar que la latencia de delegar cueste más que el ahorro obtenido con archivos pequeños.

2. Scripts que aíslan la integración

Dos scripts construyen las solicitudes, invocan Portal, gestionan errores y limpian la salida. Claude llama una interfaz estable con argumentos definidos en lugar de improvisar comandos complejos durante cada sesión.

bulk-read delimita los archivos con etiquetas XML para conservar sus fronteras. code-write elimina bloques Markdown de la respuesta y, cuando recibe un destino, guarda el código directamente.

3. Skills que enseñan cuándo delegar

Las skills describen a Claude qué tareas pertenecen a cada worker y cómo llamar los scripts. No son el mecanismo de cumplimiento: facilitan la decisión, mientras que los hooks impiden que una lectura masiva continúe por la ruta cara.

Esta combinación es más fiable que confiar únicamente en instrucciones. La skill orienta; el hook aplica una política determinista.

Qué muestran realmente los benchmarks

El repositorio de shunt publicado en GitHub contiene los escenarios y resultados resumidos:

EscenarioSin shuntCon shuntAhorro en Claude
Archivo Java de 4,014 líneas33,684 tokens5,737 tokens82%
Código y prueba, 7,408 líneas75,990 tokens4,148 tokens94%
Varios archivos, 1,281 líneas16,221 tokens821 tokens94%
Generación de pruebas desde una referencia40,614 tokens más la salida833 líneas escritas en discoNo comparable directamente

La media del 90% corresponde a los tres casos de bulk-reader. El escenario de generación no tiene un porcentaje equivalente porque el flujo optimizado escribe el resultado directamente en disco y Claude nunca recibe esas 833 líneas.

También es importante observar qué mide la tabla: tokens consumidos por Claude, no el total agregado de todos los modelos. Para calcular ahorro económico real habría que sumar el consumo de Gemini, las tarifas de cada proveedor y cualquier costo de Portal. El artículo original demuestra una reducción de contexto en el modelo principal, no publica una auditoría completa de costos.

Lo que el router no debe delegar

El propio experimento identifica límites claros.

Ediciones que requieren contexto exacto

Los resúmenes del worker no conservaron ubicaciones suficientemente fiables para editar código. Claude todavía necesita leer directamente el fragmento específico antes de modificarlo. Por eso el hook permite lecturas con offset y limit.

Debugging y decisiones de arquitectura

Durante las pruebas, el modelo auxiliar encontró patrones superficiales, pero no detectó un problema sutil de seguridad entre hilos. Claude lo reconoció cuando recibió el contexto adecuado.

La configuración excluye deliberadamente debugging, decisiones arquitectónicas y código crítico para la seguridad. El router busca eficiencia, no reemplazar razonamiento especializado con el modelo más barato disponible.

Operaciones pequeñas

Cada delegación añade un viaje de red. Spotify reporta respuestas de aproximadamente 10 a 30 segundos y un límite de 30 segundos por invocación en Portal. Para archivos pequeños, esa latencia puede superar cualquier ventaja.

Generaciones demasiado grandes

La integración transporta la entrada mediante argumentos de línea de comandos y está limitada por el tamaño máximo admitido por el sistema operativo. El README de shunt advierte además que las generaciones extensas deben dividirse para no exceder el tiempo máximo de Portal.

Cómo aplicar la misma idea sin Portal

Portal y AiKA resuelven la configuración, ejecución y distribución de los workers, pero el patrón puede implementarse con otras herramientas. Los componentes esenciales son los siguientes.

1. Clasificar las tareas por capacidad necesaria

Antes de elegir modelos, define categorías explícitas:

Ruta económicaRuta avanzada
Resumir archivos grandesDepurar fallos no evidentes
Extraer símbolos o dependenciasDiseñar arquitectura
Generar boilerplate desde una referenciaRevisar código sensible
Actualizar documentación repetitivaResolver requisitos ambiguos
Clasificar resultados de herramientasAprobar cambios destructivos

El ahorro nace de una clasificación restrictiva. Si la ruta económica acepta “cualquier tarea sencilla”, terminará recibiendo problemas que parecían triviales pero requerían contexto o criterio.

2. Interceptar antes de consumir contexto

El router debe actuar antes de que el agente principal lea el archivo. Decidir después no recupera los tokens ya enviados.

En Claude Code esto puede implementarse con PreToolUse. En otro agente puede ser un middleware alrededor de sus herramientas, una regla en el servidor MCP o una capa propia que evalúe tamaño, tipo de operación y riesgo.

Una política mínima podría ser:

si lectura_completa y lineas > umbral:
usar worker de lectura
si generación_predecible y existe referencia:
usar worker de escritura
si debugging, arquitectura o seguridad:
conservar modelo avanzado

3. Diseñar contratos de salida compactos

Enviar una tarea a un modelo barato no ayuda si este devuelve una explicación extensa. El worker debe responder con un contrato limitado: símbolos, rutas, rangos aproximados, evidencias y una conclusión corta.

Para generación, conviene solicitar únicamente código y escribirlo fuera del contexto del orquestador. Después, el agente principal puede revisar un diff o ejecutar pruebas en lugar de leer toda la salida de nuevo.

4. Escalar cuando exista incertidumbre

El worker necesita una forma explícita de rechazar una tarea. Si faltan datos, detecta ambigüedad o encuentra código crítico, debe devolver un estado de escalamiento y no inventar una respuesta para cumplir el formato.

La ruta avanzada debería recibir la pregunta original, el resumen del worker y solo los fragmentos relevantes. Así se conserva el ahorro sin ocultar la incertidumbre.

5. Medir el costo total

No basta con contar tokens de Claude. Un benchmark útil debe registrar:

  • Tokens de entrada y salida de cada modelo.
  • Precio efectivo por modelo y proveedor.
  • Latencia agregada por delegación.
  • Porcentaje de tareas que requieren repetición o escalamiento.
  • Errores introducidos por resúmenes incompletos.
  • Tiempo de revisión humana.

Una reducción de tokens puede dejar de ser ahorro si duplica la latencia, provoca reintentos o exige que el modelo principal vuelva a leer los archivos completos.

La lección para equipos que usan agentes de código

La optimización no consiste simplemente en reemplazar Claude por Gemini Flash. Consiste en impedir que el modelo de mayor capacidad reciba información que no necesita.

El router de shunt consigue esto con cuatro decisiones acertadas:

  1. Detecta las operaciones costosas antes de ejecutarlas.
  2. Delega únicamente trabajo intensivo en entrada o salida.
  3. Mantiene el razonamiento y las decisiones sensibles en Claude.
  4. Devuelve resúmenes compactos o escribe los resultados directamente en disco.

La documentación de costos de Claude Code propone una optimización relacionada: preprocesar salidas grandes mediante hooks para que el modelo reciba solo los datos relevantes. Spotify lleva ese principio un paso más allá al convertir el preprocesamiento en una capa de routing entre modelos.