Módulo 6: Finops For Tokens

6. Manos a la obra: un cambio de volumen que dispara el presupuesto

Descripción

Las lecciones 4 y 5 dejaron un gate completo: bedrock-budget.rego exige el tag correcto, y el step nuevo de cost-check exige un costo proyectado dentro de presupuesto. Esta lección prueba la segunda mitad de esa promesa con evidencia real: un supuesto de volumen mensual deliberadamente desproporcionado, propuesto como si fuera un cambio real en GENAI-COST-PROFILE.md, detenido por el step de la lección 4 antes de llegar a ningún apply — nunca después de que una factura ya sorprenda a alguien. Vas a verlo pasar una vez, con el volumen actual, y fallar una vez, con el volumen desproporcionado, ambas con evidencia real de act.

Conexión con el módulo

Esta es la misma disciplina que finops-and-cost-guardrails-guide Módulo 3, lección 7 ya aplicó a su propio gate artesanal: un workflow de prueba dedicado, corrido dos veces, con Job succeeded y Job failed reales — nunca una promesa de diseño sin evidencia. La diferencia aquí es de mecanismo, no de disciplina: en vez de dos pares de archivos JSON preparados, esta lección cambia un único número —--monthly-requests— entre las dos corridas.


Analogía: el simulacro de incendio, hecho a propósito para confirmar que la alarma funciona

Un edificio con detectores de humo no espera a un incendio real para saber si la alarma suena — hace simulacros programados, con humo controlado, para confirmar que el sistema completo reacciona antes de que ocurra el evento real. Esta lección es exactamente ese simulacro: nadie espera a que Andes Cargo reciba, de verdad, cien mil manifiestos en texto libre en un solo mes para descubrir si el presupuesto de tokens corta a tiempo. En vez de eso, esta lección provoca el escenario a propósito, en un entorno controlado y aislado (un workflow de workflow_dispatch, nunca conectado a un Pull Request real), exactamente para confirmar que la alarma —el step de la lección 4— sí suena antes de que la factura exista.


Paso 1 — La tensión real: dos documentos que tienen que cambiar juntos

La lección 4 ya advirtió esto: --monthly-requests 5000 en ci.yml y la fila "Stress" de GENAI-COST-PROFILE.md (sección 4) tienen que mantenerse sincronizados a mano, porque ningún mecanismo automático los ata entre sí. Imagina el escenario real que dispara esta lección: alguien en Andes Cargo, viendo que un socio logístico grande anunció que va a enviar manifiestos en texto libre de forma permanente (el mismo escenario que ADR-001 ya nombró como el disparador para reconsiderar el parser determinista), propone actualizar GENAI-COST-PROFILE.md con un supuesto de volumen nuevo, mucho mayor:

  | Scenario | Escalated manifests/month | Rationale |
  |---|---:|---|
  | **Realistic** | 40 (10% of the 400/month total) | A conservative starting estimate... |
- | **Stress** | 5,000 | Deliberately pessimistic: an order-of-magnitude larger... |
+ | **Stress** | 100,000 | A large partner permanently switches to free-text format,
+ | | | at a scale nobody validated against the deterministic parser's coverage |

Este cambio, por sí solo, es solo texto en un documento — no dispara nada automáticamente. El step de CI de la lección 4 también tiene que actualizarse, en el mismo Pull Request, para que el volumen que el gate verifica coincida con el volumen que el documento declara.


Paso 2 — Un workflow de prueba dedicado, la misma técnica de cicd-and-gitops-on-aws-guide/finops-and-cost-guardrails-guide

Exactamente la misma razón que finops-and-cost-guardrails-guide Módulo 3, lección 7 ya explicó para cost-gate-demo.yml: este paso de "cambiar un número y ver qué pasa" nunca debería vivir en ci.yml real —ningún Pull Request genuino debería, jamás, sustituir el volumen real por un número de prueba—. Por eso esta demostración vive en su propio archivo, disparado solo a mano:

# .github/workflows/token-budget-demo.yml
name: token-budget-demo

on: workflow_dispatch

jobs:
  token-budget-check-demo:
    runs-on: ubuntu-latest
    steps:
      - name: Check out andes-cargo-infra
        uses: actions/checkout@v4

      - name: Enforce the token budget (scripts/bedrock_cost_estimate.py)
        run: |
          python3 scripts/bedrock_cost_estimate.py \
            --model amazon.nova-lite-v1:0 \
            --input-tokens 800 \
            --output-tokens 150 \
            --monthly-requests 5000 \
            --monthly-budget 5.00

Ningún token de Infracost, ningún segundo checkout con ref: explícito —los dos requisitos que finops-and-cost-guardrails-guide Módulo 3, lección 6 ya documentó como no disponibles bajo act local—. Solo un checkout simple y una llamada directa al script de la lección 4, sin modificarlo ni una línea. Lo único que cambia entre las dos corridas de esta lección es el valor de --monthly-requests dentro de este archivo — el mismo tipo de "editar el archivo, correr, revertir" que ya viste en cicd-and-gitops-on-aws-guide Módulo 6, lección 7.


Paso 3 — Primera corrida: el volumen actual (5.000), debe pasar

act workflow_dispatch -j token-budget-check-demo -W .github/workflows/token-budget-demo.yml

Qué esperar (literal — ejecutado para escribir esta lección, con Docker real):

[token-budget-demo/token-budget-check-demo] ⭐ Run Set up job
[token-budget-demo/token-budget-check-demo]   ✅  Success - Set up job
[token-budget-demo/token-budget-check-demo] ⭐ Run Main Check out andes-cargo-infra
[token-budget-demo/token-budget-check-demo]   ✅  Success - Main Check out andes-cargo-infra [11.726486417s]
[token-budget-demo/token-budget-check-demo] ⭐ Run Main Enforce the token budget (scripts/bedrock_cost_estimate.py)
[token-budget-demo/token-budget-check-demo]   | Model                          amazon.nova-lite-v1:0
[token-budget-demo/token-budget-check-demo]   | TOTAL MONTHLY COST                           $0.42
[token-budget-demo/token-budget-check-demo]   ✅  Success - Main Enforce the token budget (scripts/bedrock_cost_estimate.py) [150.438625ms]
[token-budget-demo/token-budget-check-demo] ⭐ Run Complete job
[token-budget-demo/token-budget-check-demo]   ✅  Success - Complete job
[token-budget-demo/token-budget-check-demo] 🏁  Job succeeded

Job succeeded, $0,42 muy por debajo de $5,00 — el mismo resultado que la lección 4 ya confirmó a mano, ahora corrido dentro de un contenedor Docker efímero, con Python instalado desde cero en cada corrida, exactamente la misma confirmación doble que cada gate de este ecosistema ya demostró.


Paso 4 — Segunda corrida: el volumen desproporcionado (100.000), debe fallar

Cambia el único número del archivo, exactamente como el Paso 1 propuso:

sed -i.bak 's/--monthly-requests 5000/--monthly-requests 100000/' .github/workflows/token-budget-demo.yml
grep "monthly-requests" .github/workflows/token-budget-demo.yml
act workflow_dispatch -j token-budget-check-demo -W .github/workflows/token-budget-demo.yml

Qué esperar (literal — ejecutado para escribir esta lección, la misma corrida, contra el archivo ya editado):

[token-budget-demo/token-budget-check-demo] ⭐ Run Set up job
[token-budget-demo/token-budget-check-demo]   ✅  Success - Set up job
[token-budget-demo/token-budget-check-demo] ⭐ Run Main Check out andes-cargo-infra
[token-budget-demo/token-budget-check-demo]   ✅  Success - Main Check out andes-cargo-infra [10.297275542s]
[token-budget-demo/token-budget-check-demo] ⭐ Run Main Enforce the token budget (scripts/bedrock_cost_estimate.py)
[token-budget-demo/token-budget-check-demo]   ❗  ::error::token-budget-check failed: projected monthly cost $8.40 exceeds the $5.00 budget declared for this volume assumption (100,000 requests/month).
[token-budget-demo/token-budget-check-demo]   | Model                          amazon.nova-lite-v1:0
[token-budget-demo/token-budget-check-demo]   | TOTAL MONTHLY COST                           $8.40
[token-budget-demo/token-budget-check-demo]   ❌  Failure - Main Enforce the token budget (scripts/bedrock_cost_estimate.py) [217.134542ms]
[token-budget-demo/token-budget-check-demo] exitcode '1': failure
[token-budget-demo/token-budget-check-demo] ⭐ Run Complete job
[token-budget-demo/token-budget-check-demo]   ✅  Success - Complete job
[token-budget-demo/token-budget-check-demo] 🏁  Job failed

Job failed, exitcode '1', $8,40 por encima de $5,00. El único step del workflow que hace trabajo real —Enforce the token budget— terminó en falla, y ese código de salida se propagó hasta el job completo. En un Pull Request real, con este mismo step conectado a cost-check como muestra la lección 4, este resultado detiene el merge — el supuesto de volumen desproporcionado nunca llega a apply, exactamente la promesa de la lección 1 de este módulo: el gate corta antes del apply, no después de la factura.


Antes y después, uno al lado del otro

Corrida 1 (Paso 3)Corrida 2 (Paso 4)
--monthly-requests declarado5,000100,000
TOTAL MONTHLY COST$0.42$8.40
Resultado del step✅ Success❌ Failure
Resultado del job🏁 Job succeeded🏁 Job failed
¿Este cambio llegaría a apply en un pipeline real?No

La única diferencia entre ambas corridas es el número que declara el volumen — el mismo script, el mismo presupuesto, el mismo workflow. El gate no conoce la intención de quien propuso el cambio, solo el número que declaró: exactamente el mismo principio que finops-and-cost-guardrails-guide Módulo 3, lección 7 ya estableció para su propio gate de dólares.


Volviendo el laboratorio a su estado saludable

rm .github/workflows/token-budget-demo.yml.bak
sed -i 's/--monthly-requests 100000/--monthly-requests 5000/' .github/workflows/token-budget-demo.yml
grep "monthly-requests" .github/workflows/token-budget-demo.yml
git status

Qué esperar (literal):

--monthly-requests 5000 \
On branch main
nothing to commit, working tree clean

nothing to commit confirma que el archivo volvió, byte a byte, al estado saludable — el mismo hábito de higiene que cicd-and-gitops-on-aws-guide Módulo 6, lección 7 y el Módulo 5, lección 3 de esta guía ya practicaron.


Errores comunes

Dejar --monthly-requests en 100000 "para la próxima vez", y arrastrar la falla a lecciones posteriores (de higiene del proyecto). Qué pasa: alguien termina el Paso 4, ve el Job failed esperado, y sigue adelante sin revertir el archivo. Cómo detectarlo: act workflow_dispatch -j token-budget-check-demo sigue fallando en corridas posteriores que deberían pasar. Cómo corregirlo: siempre revierte el volumen al estado saludable (5000) antes de cerrar esta lección — el mismo hábito exacto que la lección 3 de este módulo ya practicó con bedrock.tf.

Cambiar solo GENAI-COST-PROFILE.md, o solo token-budget-demo.yml/ci.yml, sin el otro, y no notar la divergencia (el escenario exacto que esta lección existe para prevenir). Qué pasa: alguien actualiza únicamente el documento, o únicamente el YAML, pensando que basta con uno de los dos. Cómo detectarlo: si el gate sigue pasando (o sigue fallando) con un resultado que no coincide con lo que el documento declara. Cómo corregirlo: los dos tienen que cambiar juntos, en el mismo Pull Request — la disciplina exacta que el Paso 1 de esta lección demuestra con el diff propuesto sobre GENAI-COST-PROFILE.md, seguido del cambio correspondiente en el step del gate.

Confundir token-budget-demo.yml con el ci.yml real, y dejarlo disparando en cada Pull Request. Qué pasa: alguien cambia el disparador de token-budget-demo.yml de workflow_dispatch a pull_request, pensando que así "prueba el gate en cada cambio real". Cómo detectarlo: el workflow de demostración empieza a correr automáticamente, con un volumen hardcodeado que no refleja ningún Pull Request real. Cómo corregirlo: token-budget-demo.yml existe exclusivamente para validar la lógica del step, con un valor controlado — ci.yml (lección 4), con el step real dentro de cost-check, es el único workflow que debería disparar con cada Pull Request, siempre contra el volumen genuinamente declarado en GENAI-COST-PROFILE.md.


Ejercicios

Ejercicio 1 — Calcula el volumen exacto de invocaciones/mes en el que el costo proyectado cruza, por primera vez, los $5,00 de presupuesto, con el mismo tamaño de tokens de esta lección (800 entrada / 150 salida). Verifica tu cálculo corriendo el script con ese volumen exacto.

Ver solución

El costo por invocación es (800 × $0,06 + 150 × $0,24) / 1.000.000 = $0,000084. Para cruzar $5,00: 5,00 / 0,000084 ≈ 59.524 invocaciones/mes. Corriendo python3 bedrock_cost_estimate.py --model amazon.nova-lite-v1:0 --input-tokens 800 --output-tokens 150 --monthly-requests 59524 confirma un total de $5,00 (el límite exacto, que todavía pasa porque la comparación es >, no >= — Módulo 6, lección 4); 59525 ya lo superaría por una fracción de centavo.

Ejercicio 2 — Explica por qué esta lección eligió 100.000 invocaciones/mes, y no un número más cercano al punto de cruce del Ejercicio 1, para el escenario de FAIL. ¿Qué ventaja pedagógica tiene un número muy por encima del punto de cruce, frente a uno apenas por encima?

Ver solución

Un número muy por encima del punto de cruce (100.000 frente a ~59.524) deja el resultado sin ambigüedad — $8,40 frente a $5,00 es una diferencia clara, fácil de leer de un vistazo, sin necesitar verificar decimales de cerca. Un número apenas por encima del cruce (por ejemplo, 59.525) también fallaría, correctamente, pero el mensaje de error mostraría una diferencia de fracciones de centavo, más difícil de distinguir de un error de redondeo que de una violación real y significativa del presupuesto. 100.000 también tiene una segunda ventaja narrativa: es 25 veces el escenario de estrés original (5.000) y 2.500 veces el escenario realista (40) — un salto de escala que corresponde, de forma creíble, al escenario de negocio real que el Paso 1 describe (un socio grande migrando de forma permanente a texto libre).

Ejercicio 3 — Diseña, en prosa, un tercer escenario de token-budget-demo.yml donde el volumen SUBE pero el gate sigue pasando. ¿Qué condición tendría que cumplirse para que eso ocurra, dado el mismo presupuesto de $5,00?

Ver solución

Cualquier volumen entre 5.000 (el estado saludable actual) y 59.524 (el punto de cruce calculado en el Ejercicio 1) subiría el volumen declarado sin disparar el FAIL — por ejemplo, --monthly-requests 20000 produciría un costo de $0,06 × 4 = ... (escalando linealmente, Módulo 2, lección 7, Ejercicio 1) $1,68, todavía por debajo de $5,00. La condición general: mientras el costo proyectado, a este tamaño de tokens y este modelo, se mantenga por debajo de $5,00, el gate pasa sin importar que el volumen haya subido respecto al estado anterior — el gate nunca reacciona al cambio en sí, solo al valor absoluto proyectado, la misma propiedad que check-cost-threshold.sh (que sí compara un delta) deliberadamente NO comparte con este step (que compara un total absoluto, no una diferencia).


Resumen y siguiente paso

Esta lección construyó token-budget-demo.yml, un workflow de prueba dedicado, disparado solo con workflow_dispatch, que corre el step de la lección 4 —sin ninguna modificación— contra dos valores de --monthly-requests. La primera corrida, con el volumen actual (5.000), produjo Job succeeded, $0,42. La segunda, con un volumen deliberadamente desproporcionado (100.000, un socio grande migrando de forma permanente a texto libre), produjo Job failed, exitcode '1', $8,40 — evidencia real, ejecutada con act contra Docker, de que el presupuesto corta antes del apply, no después de la factura.

Antes de avanzar deberías poder: explicar por qué esta demostración vive en un workflow separado, nunca dentro de ci.yml; calcular el punto de cruce exacto del presupuesto para cualquier tamaño de token y modelo; y describir qué pasaría con un Pull Request real que propusiera este mismo cambio de volumen sin el step de la lección 4 en cost-check.

La lección 7 se aleja del código por un momento y desarrolla, con números reales verificados en este mismo momento, cuándo Provisioned Throughput —y no on-demand— sería la decisión correcta para Andes Cargo.

Recursos

  1. finops-and-cost-guardrails-guide, Módulo 3, lección 7 (07-hands-on-proving-the-gate.md) — el precedente exacto de un workflow de prueba dedicado con dos corridas reales, PASS y FAIL.
  2. GitHub Actions — workflow_dispatch — referencia oficial del disparador manual usado en token-budget-demo.yml.
  3. ADR-001-llm-as-escalation-path.md (Módulo 1, lección 8 de esta guía) — la fuente del escenario de negocio (un socio grande migrando a texto libre) que motiva el volumen desproporcionado de esta lección.
  4. Este módulo, lección 4 — el origen del step y del presupuesto de $5,00 que esta lección prueba en ambas direcciones.