Cuando el proxy no basta — cómo acabé usando Claude Code como backend
Ayer estaba celebrando. El proxy OAuth funcionaba, Harvie hablaba a través de Sonnet, todo era bonito. ¿Hoy? Todo se rompió otra vez.
Qué falló
El proxy de ayer reenvía peticiones API a api.anthropic.com usando el token OAuth de Claude Code. Simple, elegante. Pero hoy empezó a devolver esto:
You're out of extra usage. Add more at claude.ai/settings/usage and keep going.
No era un rate limit. No era un timeout. Un error de facturación — en peticiones con más de ~720 tokens de entrada. Las peticiones pequeñas iban bien. El system prompt completo de Harvie (35KB, ~9000 tokens) — rechazo instantáneo.
La madriguera del conejo
Pasamos horas probando de todo:
- Replicar cada header que manda Claude Code (
x-stainless-*,anthropic-beta: claude-code-20250219, headers de facturación) - Probar diferentes valores de hash
cchen el header de facturación - Testear con el token del VPS y el del Mac
- Curl directo a la API saltándonos el proxy
Nada funcionó. Incluso el token del Mac — el que alimenta una sesión de Claude Code totalmente funcional — fallaba al usarlo desde curl con los mismos headers exactos.
El problema real
Finalmente revisamos la configuración de organizaciones de la cuenta:
Org: joca.dev
capabilities: ['api']
billing_type: prepaid
rate_limit_tier: auto_prepaid_tier_0 ← sin créditos
Org: [email protected]
capabilities: ['claude_max', 'chat'] ← ¡SIN 'api'!
billing_type: stripe_subscription
rate_limit_tier: default_claude_max_5x
Dos organizaciones. La personal tiene Claude Max 5x pero sin capacidad API. La otra tiene capacidad API pero sin créditos. Las llamadas API se enrutan a la organización equivocada.
Claude Code funciona porque usa facturación claude_max, no facturación api. Son canales diferentes. El token OAuth te da acceso a ambos, pero las llamadas API directas van por el canal api — que no tiene créditos.
La solución: claude -p como backend
Si Claude Code puede usar la suscripción, ¿por qué no usar Claude Code como backend?
Hermes → POST /v1/messages → proxy (Node.js)
→ escribe el system prompt como CLAUDE.md
→ ejecuta: claude -p --output-format stream-json --model opus
→ traduce la respuesta al formato API de Anthropic
→ devuelve a Hermes
La clave: CLAUDE.md. Cuando Claude Code arranca, carga CLAUDE.md del directorio de trabajo como parte de su system prompt. Este contenido se integra con el sistema de facturación de Claude Code correctamente — sin topes de tokens, sin "out of extra usage". Probamos con 35KB de system prompt y más de 25.000 tokens. Funciona perfecto.
--append-system-prompt tiene el mismo tope de 720 tokens que la API. ¿Pero CLAUDE.md? Sin límite. Misma suscripción, diferente ruta de facturación.
La arquitectura
Telegram → Hermes (agente, tools, memoria, SOUL.md)
→ HTTP proxy (:18791)
→ escribe CLAUDE.md con el system prompt de Hermes
→ lanza: claude -p --output-format stream-json
→ parsea eventos estructurados (tool_use, text, result)
→ envía progreso de tools a Telegram (edita el mismo mensaje)
→ devuelve respuesta final en formato API de Anthropic
→ Hermes envía respuesta a Telegram
El proxy traduce entre el formato API de Anthropic (lo que habla Hermes) y el CLI de Claude Code (lo que realmente habla con los modelos). Hermes no sabe que hay un CLI detrás del telón.
Progreso de herramientas en Telegram
Algo que perdimos con este enfoque: Hermes antes mostraba el progreso de tools en vivo en Telegram (qué está ejecutando, lecturas de ficheros, etc.). Con claude -p, las tools se ejecutan dentro de Claude Code — Hermes nunca las ve.
La solución: el proxy parsea los eventos de --output-format stream-json, detecta bloques tool_use y los envía directamente a Telegram vía la API del bot. Mismo formato visual que Hermes: un mensaje que se va editando con cada nueva tool, dedup con contadores (×2).
Compromisos
Lo que funciona:
- Suscripción completa de Claude Max, sin facturación API
- Opus con 1M de contexto, system prompts de 35KB, tools, todo
- Progreso de tools visible en Telegram
- Cola de peticiones (de una en una, las demás esperan)
Lo que es más lento:
- Cada mensaje lanza un nuevo proceso
claude -p(~8-10s de overhead de arranque) - Sin streaming real — la respuesta llega toda junta cuando Claude termina
- Más pesado en el VPS (proceso Node.js + Claude Code por petición)
Lo que se pierde:
- La elegancia de un proxy HTTP simple
- Tiempos de respuesta API sub-segundo
- Streaming SSE real al cliente
Lo que aprendí
claude_max≠api. Son capacidades de facturación separadas. Tu suscripción Max no incluye acceso API directo.- Los tokens OAuth funcionan para ambos, pero la API se enruta por la org que tenga capacidad
api— que puede no ser la de tu suscripción. - CLAUDE.md es magia. Se integra con la facturación de Claude Code de una forma que
--system-prompty--append-system-promptno. --output-format stream-jsonte da eventos estructurados (llamadas a tools, deltas de texto, resultados) — mucho mejor que parsear texto crudo.
Próximos pasos
El enfoque con claude -p funciona pero es un compromiso. La solución ideal sería añadir capacidad api a la org de Max — entonces el proxy rápido original funciona al instante. Hasta que Anthropic incluya acceso API con las suscripciones Max (o te dejen activarlo), esto es lo mejor que tenemos.
Siguiente: investigar sesiones persistentes de Claude Code (--input-format stream-json) para eliminar los 8-10s de arranque por mensaje. Mantener un proceso vivo, enviarle mensajes por pipe. Eso lo haría casi tan rápido como la API directa.
Lo que el agente hizo hoy en la práctica
Todo lo anterior — el debugging del proxy, el cambio de arquitectura — era la infraestructura. Pero la gracia de la infraestructura es lo que corre encima. Esto es lo que Harvie hizo hoy mientras yo estaba currando:
Construyó un vault de Obsidian para OhanaSmart con el patrón LLM Wiki. Le pasé un vídeo de Karpathy sobre reemplazar RAG con wikis en markdown gestionadas por un LLM. Harvie analizó el vídeo, extrajo la arquitectura y la aplicó a nuestro proyecto de vending. El resultado: un vault completo con 31 leads documentados (cada uno con su propia página — datos de contacto, objeciones, siguientes acciones), análisis de competencia, páginas de normativa y estrategia de pitch. Todo cruzado. La idea es que cada interacción con un lead mejora la wiki, así que para el lead #15 ya has visto todas las objeciones posibles.
Analizó un vídeo de YouTube y extrajo conclusiones de negocio. No un resumen — conclusiones estratégicas mapeadas a mis tres proyectos. "Este patrón podría ser un servicio premium para Pimesit.es." "Así deberíamos estructurar el conocimiento de OhanaSmart." Ese es el filtro: si un vídeo no conecta con ingresos o LOIs, no pasa el corte.
Arregló sus propios bugs. La transcripción de voz estaba fallando porque una config apuntaba a whisper-1 (el modelo cloud de OpenAI) en vez del nombre del modelo local de Whisper (base). Harvie encontró el bug, lo parcheó y siguió. Yo ni sabía que estaba roto hasta que ya estaba arreglado.
Nada de esto requirió que yo abriera un terminal. Mandé mensajes de voz desde Telegram mientras los niños jugaban. El agente hizo el resto.
Ese es el valor real de envolver Claude Code como backend: no el diagrama de arquitectura, sino el hecho de que un agente de IA está construyendo bases de conocimiento, analizando contenido, generando media y arreglándose a sí mismo — todo a través de un chat de Telegram, alimentado por una suscripción de Claude Max y un proxy Node.js chapucero en un VPS de 7€/mes.