Módulo 1: Genai In Production Vs A Notebook

8. Proyecto: el mapa de la carga de IA de Andes Cargo

Descripción

Las siete lecciones anteriores dejaron, dispersas, todas las piezas de una decisión de arquitectura: process-shipment-manifest no puede leer texto libre (lección 3); un guardián con IA nunca es más barato ni más simple que uno sin IA, así que se usa solo cuando hace falta (lecciones 2, 6); la frontera con AI Engineering define qué NO construye esta guía (lección 4); el inventario real confirma dónde vive hoy cada pieza (lección 5); y el intento honesto contra Bedrock confirma exactamente qué esta guía puede y no puede ejecutar (lección 7). Este proyecto final convierte esas siete piezas dispersas en un solo documento con formato de ADR (Architecture Decision Record): ADR-001-llm-as-escalation-path.md, el documento que va a gobernar, con criterio explícito, los siete módulos que siguen.

Conexión con el módulo

Este es el cierre del Módulo 1, y el único documento que esta guía entera necesita para justificar, con evidencia, por qué construye las cosas en el orden en que las construye — el mismo tipo de documento que cloud-security-and-guardrails-guide (RISK-MAP.md) y finops-and-cost-guardrails-guide (COST-PROFILE.md) ya dejaron en la raíz de andes-cargo-infra/. Cada módulo de M2 a M8 se abre citando la fila de este ADR que le corresponde.


Paso 1 — Por qué un ADR, y no solo una decisión mencionada en prosa

Ya viste, en cloud-security-and-guardrails-guide M1.8, por qué un ADR vale más que una tabla suelta: documenta el contexto y la justificación de una decisión, no solo su resultado. Esta guía tiene una razón adicional, propia, para necesitar uno: es la única guía del ecosistema que declara, desde su primera lección, que va a dejar una pieza central —la invocación real de un modelo— sin poder ejecutarse. Un ADR es exactamente el formato correcto para que esa limitación no se lea como un defecto escondido, sino como una decisión de diseño documentada, con su razón, en el mismo lugar donde se documenta cualquier otra decisión de esta guía.


Paso 2 — El documento completo

En la raíz de andes-cargo-infra/, crea ADR-001-llm-as-escalation-path.md:

# ADR-001 — The LLM Is an Escalation Path, Not the Default

**Status:** Accepted · **Date:** this module's close · **Supersedes:** none
**Governs:** Modules 2 through 8 of `genai-on-aws-production-guide`
**Source:** Module 1, lessons 2, 3, 5, 6, and 7 (this same guide)

## Context

`process-shipment-manifest`, inherited from `aws-core-services-guide` and wired into the
event-driven system by `aws-serverless-and-containers-guide`, parses `key=value` manifests with a
deterministic, free, always-consistent parser. Some logistics partners send free-text manifests
instead -- the body of an email, a note copied from their own system -- that the deterministic
parser cannot read. Today, those manifests fail with no automated recovery path.

Amazon Bedrock can read free text and extract structured fields. It is also fundamentally
different from every other piece of infrastructure this ecosystem has built so far: it is not
deterministic (the same input can produce a slightly different output across calls), it is billed
per token instead of per hour provisioned, and it requires a managed guardrail plus a
defense-in-depth check that no prior module of this ecosystem needed. Module 1, lesson 2
established that a correct response in Bedrock's playground confirms none of this by itself.

The inherited infrastructure, confirmed live in Module 1, lesson 5: three active Lambda functions
(`process-shipment-manifest`, `validate-shipment-manifest`, `notify-shipment-partner`), five IAM
roles, one EventBridge rule on the default bus, and zero rules on the custom bus
`andes-cargo-events` -- which already publishes `ShipmentProcessed`/`ShipmentDelayed` events that
nothing consumes yet. Module 1, lesson 7 confirmed, by direct attempt in this sandbox, that no
free-tier LocalStack plan can invoke Bedrock for real -- the service is documented as
`"Included in Plans: Ultimate"` only, one tier above the free plan this entire ecosystem runs on.

## Decision

**The deterministic parser remains the default path for every manifest, with zero change to its
cost, speed, or reliability. The LLM is invoked only as an escalation path, triggered exclusively
by a `ManifestParseFailed` event that `process-shipment-manifest` publishes when, and only when,
its own `key=value` parsing already failed.** A new function, `extract-shipment-manifest-fields`,
listens for that specific event and attempts extraction via a Bedrock model -- the cheapest model
family that a real evaluation shows is reliable enough for this specific, narrow task (Amazon Nova
or a compact Mistral model are the starting candidates named in lesson 6; the final choice, with
real cost numbers, is Module 2's decision, not this one). Only on a successful extraction does
`extract-shipment-manifest-fields` write to `Shipments`, using the exact same schema the
deterministic path already uses.

This decision is deliberately conservative: it adds a new capability without touching a single
line of the code path that already works for the majority of Andes Cargo's manifests, and it
gives this guide a reliability metric -- the **escalation rate**
(`ManifestParseFailed` events / total manifests processed) -- that is calculable with zero real
invocations of any model, entirely from events this ecosystem's free-tier lab can already produce.

## The map: how Modules 2 through 8 implement this decision

| Order | Module | Implements this ADR by |
|--:|---|---|
| 1 | M2 — The Bedrock cost model | Prices the escalation path per token before a single resource is declared, so cost is a known input, not a surprise |
| 2 | M3 — IaC for an AI endpoint | Declares only the escalation path's infrastructure (`bedrock.tf`); `process-shipment-manifest` is not touched |
| 3 | M4 — Bedrock guardrails and defense in depth | Guards specifically the one path that touches a non-deterministic model; the default path needs no such guard |
| 4 | M5 — Securing the AI workload | Extends the inherited security gate to the escalation path's new Terraform, least privilege scoped to one model ARN |
| 5 | M6 — FinOps for tokens | Extends the inherited cost gate with a budget specific to the escalation path's usage-based cost |
| 6 | M7 — Observability, latency and evals | Measures the escalation rate itself as the primary SLI -- the number that proves this ADR's decision is holding |
| 7 | M8 — Capstone | Proves, end to end, that a well-formed manifest never triggers the escalation path at all |

## Consequences

Every module from M2 to M8 builds around the escalation path, never around replacing the default
path. The deterministic parser's cost, latency, and reliability guarantees -- the ones the first
seven guides of this ecosystem already established -- remain unchanged for the majority of
Andes Cargo's traffic. The escalation rate becomes the single most important reliability number
this guide can report without ever invoking a real model, and it is the first number Module 7
computes for real. If that rate ever climbs unexpectedly (for example, if a large logistics
partner permanently switches away from `key=value` format), it is the signal -- with evidence, not
intuition -- that extending the deterministic parser's coverage is worth more engineering time than
scaling the LLM path further; that trade-off is named here, not resolved here.

## Alternatives considered

**Route every manifest through the LLM, and use it to validate the deterministic parser's output.**
Rejected: this would make the most expensive, least predictable path in the entire system the
default for the majority case that the free, deterministic parser already solves perfectly --
exactly the antipattern Module 1, lesson 3 named directly.

**Replace `process-shipment-manifest`'s parser with an LLM-first design from the start.** Rejected:
it would discard the reliability guarantee (same input, same output, always) that every other
guide in this ecosystem depends on for its own "Qué esperar (literal)" blocks, in exchange for
capability the majority of manifests never needed in the first place.

**Build GPU-backed self-hosted inference instead of a managed model via Bedrock.** Rejected, and
out of scope for this guide entirely: no $0 path exists for dedicated GPU capacity in any LocalStack
plan, and Andes Cargo's manifest volume does not justify the cost of provisioned GPU infrastructure.
Named, not built, in Module 8, lesson 7 of this guide, in contrast with `kubernetes-and-eks-in-
production-guide`.

Paso 3 — Verificando el documento

grep -c '^| [1-7] ' ADR-001-llm-as-escalation-path.md
grep -o '^| [1-7] | M[2-8]' ADR-001-llm-as-escalation-path.md | wc -l

Qué esperar (literal — el contenido lo escribiste tú, la forma es determinista):

7
7

Siete filas en la tabla "The map", siete módulos distintos (M2 a M8) referenciados exactamente una vez cada uno — ningún módulo de esta guía quedó fuera del ADR, y ninguno aparece duplicado o repetido.


Cómo leer este documento, seis meses después

Frente a este ADR, un lector nuevo —un entrevistador técnico, un compañero de equipo que se une al proyecto tarde— debería poder contestar, sin preguntarle a nadie: ¿cuál es la decisión? (la primera frase de la sección Decision: el parser determinista es el default, el LLM es escalamiento); ¿por qué? (la sección Context: process-shipment-manifest no puede leer texto libre, y un modelo trae costo/riesgo/no-determinismo que el default no tiene); ¿cómo se mide si la decisión sigue siendo correcta? (la tasa de escalamiento, nombrada explícitamente en Consequences); y ¿qué alternativas se descartaron, y por qué? (la sección final, con las tres opciones consideradas y rechazadas). Si alguna de esas cuatro preguntas exige releer una lección completa de esta guía para contestarla, el documento no cumplió su función.


El cierre del Módulo 1

Con ADR-001-llm-as-escalation-path.md escrito, este módulo entrega exactamente lo que prometió en la lección 1: ninguna infraestructura de IA construida todavía —ni bedrock.tf existe, ni extract-shipment-manifest-fields tiene una sola línea de código—, pero la decisión de arquitectura que va a gobernar cómo se construye está fijada, por escrito, con su contexto, su razonamiento y sus alternativas descartadas. Entras al Módulo 2 con un criterio explícito para evaluar cada decisión de costo que sigue, en vez de una intuición general de "hay que agregar IA con cuidado".


Errores comunes

Escribir el ADR en español, rompiendo la convención de identificadores y documentos técnicos del ecosistema (de idioma). Qué pasa: alguien, cómodo escribiendo en español el resto de la guía, traduce también las secciones del ADR. Cómo detectarlo: si tu ADR-001-llm-as-escalation-path.md mezcla "Decision"/"Consequences" en inglés con prosa en español dentro de esas mismas secciones. Cómo corregirlo: los documentos técnicos de andes-cargo-infra/ —igual que el HCL, el Python y el JSON— van siempre en inglés, exactamente como ya viste con THREAT-MODEL.md, RISK-MAP.md y COST-PROFILE.md de las guías anteriores. Solo la prosa de esta lección, la que explica el ADR, va en español.

Tratar la sección "Alternatives considered" como opcional o decorativa (de alcance). Qué pasa: alguien escribe Context y Decision con cuidado, pero deja Alternatives considered como una lista corta sin razonamiento real. Cómo detectarlo: si tus alternativas descartadas no tienen, cada una, su propia razón específica de por qué se rechazó. Cómo corregirlo: la sección de alternativas es la que demuestra que la decisión tuvo criterio, no que fue la única opción que a alguien se le ocurrió — es exactamente la diferencia entre "hicimos esto" y "hicimos esto, en vez de estas otras dos opciones reales, por estas razones específicas", el estándar real de un ADR que un entrevistador técnico esperaría ver defendido.

Actualizar la tasa de escalamiento de Consequences con un número inventado antes de que el M7 la calcule de verdad (de expectativa hacia adelante). Qué pasa: alguien, ansioso por completar el documento, agrega un porcentaje específico de tasa de escalamiento a este ADR, sin haber corrido todavía el cálculo real del M7.4. Cómo detectarlo: si tu documento tiene un número de tasa de escalamiento antes de completar el Módulo 7. Cómo corregirlo: este ADR nombra la métrica —qué se va a medir, y por qué importa—, no su valor. El valor real, calculado con un conjunto fijo y determinista de eventos de prueba, es el trabajo específico del M7.4; agregarlo aquí antes de tiempo sería, exactamente, el mismo antipatrón de "escalar antes de que el parser determinista de verdad falle" que este ADR entero existe para evitar.


Ejercicios

Ejercicio 1 — Identifica qué fila de "The map" corresponde a un módulo específico, sin mirar la tabla. De memoria, ¿qué módulo de esta guía extiende el cost gate heredado con un presupuesto de tokens? ¿Y cuál mide, por primera vez, la tasa de escalamiento?

Ver solución

M6 — FinOps para tokens — extiende el cost gate heredado (cost-estimate/cost-check/cost-tags) con bedrock-budget.rego, la política nueva de presupuesto para la carga de tokens. M7 — Observabilidad, latencia y evals — calcula la tasa de escalamiento por primera vez, de forma literal, a partir de un conjunto fijo de eventos de prueba, sin invocar ningún modelo. Si identificaste ambos sin mirar la tabla, tienes clara la relación entre el ADR y los módulos que lo implementan.

Ejercicio 2 — Defiende la decisión de este ADR frente a una objeción concreta. Un colega dice: "¿Por qué no simplemente usar el LLM para todo? Es más simple mantener un solo camino de procesamiento que dos." Responde citando la sección "Alternatives considered" de este ADR.

Ver solución

Una respuesta completa suena, más o menos, así: "La primera alternativa considerada en este ADR es exactamente esa opción, y se rechaza con una razón concreta: convertiría el camino más caro, más lento y menos predecible del sistema en el default para la mayoría de los manifiestos, que el parser gratuito y determinista ya resuelve perfectamente. 'Un solo camino' suena más simple en abstracto, pero en la práctica significaría pagar por token, y aceptar variabilidad de resultado, para envíos que hoy se procesan gratis y siempre con el mismo resultado. Dos caminos, con una regla clara de cuándo usar cada uno, es más simple de operar que un solo camino caro aplicado a todo por igual."

Ejercicio 3 — Predice qué pasaría si la tasa de escalamiento, medida en el M7, resultara sorprendentemente alta. Basándote en la sección Consequences de este ADR, ¿qué decisión debería tomar Andes Cargo si, seis meses después de desplegar esta carga de IA, la tasa de escalamiento subiera de un 7% típico a un 40%?

Ver solución

Según la sección Consequences de este ADR, una tasa de escalamiento inesperadamente alta es, explícitamente, la señal de que vale la pena invertir en ampliar lo que el parser determinista reconoce directamente —por ejemplo, si un socio logístico grande cambió permanentemente su formato de envío a texto libre—, en vez de simplemente aceptar un volumen creciente de invocaciones más caras al modelo. El ADR nombra esta decisión como algo a evaluar con evidencia cuando ocurra, no algo que resuelve por adelantado — es, textualmente, "a trade-off named here, not resolved here". La señal correcta ante ese escenario no es "escalar la infraestructura de Bedrock para aguantar más volumen" por defecto, sino primero preguntar si el problema de fondo —el formato que llega— cambió, y si extender parse_manifest sigue siendo la opción más barata.


Resumen y siguiente paso

En este proyecto final del Módulo 1 escribiste ADR-001-llm-as-escalation-path.md, el documento que fija, por escrito, la decisión de arquitectura completa de esta guía: el parser determinista sigue siendo el default, sin excepción; el LLM entra únicamente como camino de escalamiento, disparado por ManifestParseFailed; y la tasa de escalamiento es la métrica de confiabilidad que prueba, con evidencia y sin invocar ningún modelo, que esa decisión sigue siendo correcta. Verificaste el documento con grep, y confirmaste que las siete filas de "The map" cubren, exactamente una vez cada uno, los siete módulos que siguen.

Antes de avanzar deberías poder: explicar la decisión central del ADR en una frase, sin mirar el documento; nombrar las tres alternativas descartadas y la razón de cada una; y ubicar, para cualquier módulo de M2 a M8, cuál fila de "The map" le corresponde y por qué.

Con este documento cerrado, el Módulo 1 completo — ocho lecciones, desde el mapa de la guía hasta esta decisión formal — queda atrás. El Módulo 2 abre con la pregunta que este ADR deja explícitamente pendiente: si el camino de escalamiento cuesta por token, ¿cuánto cuesta de verdad, y por qué Infracost —la herramienta que el resto del ecosistema ya confía— no puede resolver esa pregunta solo?

Recursos

  1. cloud-security-and-guardrails-guide, Módulo 1, lección 8 (08-project-andes-cargos-risk-map-and-guide-roadmap.md) — el mismo formato de ADR, aplicado a un dominio distinto (orden de resolución de riesgos).
  2. finops-and-cost-guardrails-guide, Módulo 1, lección 8 — COST-PROFILE.md, el documento hermano de costo que este ADR complementa, no reemplaza.
  3. Michael Nygard — Documenting Architecture Decisions — la fuente original del formato ADR que este documento sigue.
  4. Este módulo, lecciones 3, 5, 6 y 7 — la fuente completa de cada afirmación de la sección Context de este ADR.