Lesson 12 · 15 in the route · 3 min read · Level 3
Lab 04 — Production grade: async, errors, logging, versioning
Process 200 indicators in under two minutes within the rate limit, survive 429 and 529 without losing work, log every call, and switch prompt or model with evidence.
Spanish only for now · Solo en español por ahora
Proyecto: signal-agent (ledger de predicciones; 163 tests, mypy strict, GitHub Actions). Objetivos: D2.T4.a/b/c · D2.T6 · D2.T2 · D5.T2.a · D5.T3.c · D4.T1 Tiempo: 4–5 h.
Requerimiento
El módulo que genera señales debe procesar 200 indicadores en < 2 min sin superar el rate limit del tier, sobrevivir a 429/529 sin perder trabajo, registrar cada llamada de forma auditable, y permitir cambiar de versión de prompt o de modelo con evidencia (eval de regresión) y sin sorpresas.
Pasos
1. Async con concurrencia acotada
AsyncAnthropic+asyncio.Semaphore(N)+asyncio.gather(..., return_exceptions=True). Medir tiempo total con N = 1, 4, 8, 16. Observar dónde aparece el 429.- Idempotencia: cada indicador tiene
id; si el proceso se cae a la mitad y se relanza, no duplica señales en el ledger.
2. Errores y reintentos
- Configurar
max_retriesytimeouten el cliente; probarmax_retries=0para ver los errores crudos. - Tabla de decisión implementada: 400/401/404 → no reintentar, fallar ruidoso; 429 → backoff exponencial + jitter, respetar
retry-after; 500/529 → backoff;overloadedsostenido → fallback de modelo (Sonnet → Haiku) con marca en el log. - Test con
respx/mock que simula cada código.
3. Logging estructurado
- Un registro JSON por llamada con:
ts, request_id, modelo, prompt_version, input_tokens, output_tokens, cache_read, cache_write, stop_reason, latencia_ms, tools, costo_estimado, indicador_id. Nada de PII. - Un script que lee los logs con DuckDB y saca: costo/día, p95 de latencia, distribución de
stop_reason, tasa de error por tipo.
4. Versionado de prompts y modelos
prompts/senal_v3.mdcon frontmatter (versión, fecha, modelo objetivo, changelog). El código carga por versión; el log registraprompt_version.config.tomlconmodel = "claude-…-YYYYMMDD"pinneado. Documentar el procedimiento de migración: cambiar en staging → correr eval → comparar → promover.
5. Eval de regresión en CI
eval/senales.jsonl: 30 casos (indicador + señal esperada o rúbrica). Test parametrizado que corre el prompt actual y exige ≥ umbral de acuerdo. Por costo, correrlo con Batches en el job nocturno y con Haiku en cada PR.- GitHub Actions: secret
ANTHROPIC_API_KEY, job que ejecuta la eval y publica el resumen como comentario del PR (opcional: conclaude -pheadless, D3).
6. Trazas: aislar integración vs modelo
- Introduce 3 fallas a propósito: (a) modelo inexistente, (b)
max_tokens=20, (c) descripción de tool ambigua. Para cada una, escribe enLAB.mdcómo la traza te dice en qué capa está el problema.
Verificación
- 200 indicadores en < 2 min sin errores no manejados; sin duplicados tras relanzar.
- Tests de los 6 códigos HTTP.
- Log JSON + consulta DuckDB funcionando.
- Cambio de
prompt_versionvisible en el log; eval de regresión pasa en CI. -
LAB.mdcon las 3 trazas analizadas.
Qué aprendiste
- ¿Qué errores reintenta el SDK solo y con qué política?
- RPM/ITPM/OTPM: ¿cuál te limitó y cómo lo supiste?
- ¿Por qué idempotencia importa en un pipeline con LLM?
- ¿Qué es un breaking change de modelo y cómo lo detecta tu eval?
- ¿Qué campos del log te permiten calcular el costo exacto?
- ¿Cómo distinguiste en las trazas integración vs modelo?
Saved only in this browser.