Coste
Mantén el gasto en modelos predecible cuando crece el uso
Envía cada tarea por un único endpoint OpenAI-compatible, enrútala al modelo más barato capaz de hacerla y registra el uso de tokens que devuelve cada respuesta.
Copiar el prompt
Sustituye los campos entre corchetes y pégalo en Claude Code, Codex o cualquier IA con acceso a terminal. Instala el skill de Felo, pregunta antes de gastar créditos y ejecuta el flujo.
Revisa nuestro gasto en modelos y propone un plan de enrutado para estas tareas: [lista de tareas o funciones]. Restricciones: presupuesto mensual [importe], objetivo de latencia [objetivo], nivel de calidad [nivel]. Lee el catálogo de modelos en vivo antes de recomendar nada. Genera: 1. Una tabla tarea -> modelo recomendado. 2. Qué tareas pueden bajar un nivel y el riesgo de calidad. 3. Un plan de registro de uso por tarea y función. 4. Qué medir antes de cambiar producción. Reglas: - Lee los ID y precios actuales del catálogo en vivo; nunca cites una tarifa de memoria. - No cambies la configuración de producción ni envíes tráfico real. - Pregunta antes de gastar créditos en llamadas de prueba. - Mantén un plan de rollback y un límite de gasto por función. - Escribe el plan en ./routing-plan.md y resúmelo en el chat.
La copia también incluye los pasos de instalación y las reglas de seguridad.
Lo que obtienes
Salida de ejemplo de una ejecución. No es generación en vivo.
| Tarea | Actual | Propuesto | Riesgo |
|---|---|---|---|
| Clasificar ticket | modelo fuerte | modelo rápido | bajo |
| Redactar respuesta | modelo fuerte | modelo fuerte | ninguno |
| Resumir changelog | modelo fuerte | modelo rápido | medio |
Antes de cambiar nada: registra el uso por tarea durante una semana y compara la calidad en 50 salidas muestreadas.
Las llamadas exactas
Para desarrolladores: el mismo flujo como código, en orden de ejecución.
Mostrar las llamadas reales a la API
Todas las tareas por un endpoint
Usa un endpoint OpenAI-compatible y una clave, sin un SDK por proveedor.
routing.ts const BASE_URL = "https://openapi.felo.ai/api/v1"; const headers = { Authorization: `Bearer ${process.env.FELO_API_KEY}`, "Content-Type": "application/json", }; type Completion = { choices: { message: { content: string } }[]; usage: { prompt_tokens: number; completion_tokens: number; total_tokens: number }; }; async function chat(model: string, prompt: string): Promise<Completion> { const res = await fetch(`${BASE_URL}/chat/completions`, { method: "POST", headers, body: JSON.stringify({ model, messages: [{ role: "user", content: prompt }] }), }); if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`); return res.json() as Promise<Completion>; } const summary = await chat( "claude-haiku-5-5", "Summarize this changelog in three bullets: …", ); console.log(summary.choices[0].message.content);Salida de ejemplo
{ "choices": [{ "message": { "content": "• …" } }], "usage": { "prompt_tokens": 812, "completion_tokens": 96, "total_tokens": 908 } }Enruta el modelo por tarea
Elige modelo rápido o fuerte según complejidad y registra primero la base.
routing.ts type TaskKind = "classify" | "extract" | "summarize" | "draft" | "review"; const MODEL_ROUTES: Record<TaskKind, string> = { classify: "claude-haiku-5-5", extract: "claude-haiku-5-5", summarize: "claude-haiku-5-5", draft: "claude-sonnet-5-5", review: "claude-sonnet-5-5", }; export async function route(kind: TaskKind, prompt: string) { const model = MODEL_ROUTES[kind]; const result = await chat(model, prompt); return { model, text: result.choices[0].message.content, usage: result.usage, }; }Salida de ejemplo
{ "model": "claude-haiku-5-5", "text": "• …", "usage": { "prompt_tokens": 812, "completion_tokens": 96, "total_tokens": 908 } }Lee y registra el uso
Lee el usage de cada respuesta y registra tokens y latencia por función.
routing.ts type UsageRecord = { model: string; kind: TaskKind; promptTokens: number; completionTokens: number; totalTokens: number; }; const usageLog: UsageRecord[] = []; function logUsage(kind: TaskKind, model: string, usage: Completion["usage"]) { const entry: UsageRecord = { model, kind, promptTokens: usage.prompt_tokens, completionTokens: usage.completion_tokens, totalTokens: usage.total_tokens, }; usageLog.push(entry); console.log(JSON.stringify(entry)); // ship this line to your metrics store return entry; } export function tokensByModel() { return usageLog.reduce<Record<string, number>>((totals, entry) => { totals[entry.model] = (totals[entry.model] ?? 0) + entry.totalTokens; return totals; }, {}); } const result = await route("summarize", "Summarize this changelog in three bullets: …"); logUsage("summarize", result.model, result.usage); console.log(tokensByModel());Salida de ejemplo
{"model":"claude-haiku-5-5","kind":"summarize","promptTokens":812,"completionTokens":96,"totalTokens":908} { "claude-haiku-5-5": 18234, "claude-sonnet-5-5": 4201 }Una clave para todos los proveedores
Llama a los modelos del catálogo con la misma clave Felo y reduce la gestión de proveedores.
routing.ts async function chatOnChannel(model: string, prompt: string, channel?: string) { const res = await fetch(`${BASE_URL}/chat/completions`, { method: "POST", headers: { ...headers, ...(channel ? { "X-Felo-Channel": channel } : {}), }, body: JSON.stringify({ model, messages: [{ role: "user", content: prompt }] }), }); if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`); return res.json() as Promise<Completion>; } // Leave `channel` undefined for the default supplier. export function routePinned(kind: TaskKind, prompt: string, channel?: string) { return chatOnChannel(MODEL_ROUTES[kind], prompt, channel); }Precios desde el catálogo vivo
No fijes tarifas; lee precios actuales del catálogo y la página de precios.
routing.ts type Catalog = { data: { id: string; owned_by: string; model_kind: string }[]; }; export async function chatModelIds() { const res = await fetch( `${BASE_URL}/models?exclude_video_and_decisions=true`, { headers }, ); if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`); const catalog = (await res.json()) as Catalog; return catalog.data .filter((model) => model.model_kind === "chat") .map((model) => model.id); } // Price `tokensByModel()` against https://openapi.felo.ai/pricing and // https://openapi.felo.ai/models. Keep the links, not the rates, in your code.Salida de ejemplo
["claude-haiku-5-5", "claude-sonnet-5-5"]
Qué incluye
- Endpoint y clave unificados
- Elección de modelo rápido o fuerte por tarea
- Registro de tokens de cada respuesta
- Precios leídos del catálogo en vivo, no fijados en código
Qué no hace
- No garantiza reducir la factura
- No conmuta tráfico de producción automáticamente
- Los ids y precios cambian; lee siempre el catálogo en vivo
- No evalúa calidad por ti; necesitas tus muestras
- No sustituye facturación ni observabilidad
Preguntas
¿Bajará la factura?
Indica qué tareas pueden bajar de nivel, pero el ahorro es real solo tras comparar muestras y registrar uso.
¿Llama modelos automáticamente?
Solo si apruebas llamadas de prueba. Por defecto lee el catálogo y escribe recomendaciones sin tocar producción.
¿Cómo sé qué modelo es más barato?
Lee el catálogo de modelos en vivo y la página de precios; el flujo no fija tarifas porque cambian.
¿Puedo fijar un proveedor?
Sí, cuando la latencia importa más que el precio. Fijar es una elección, no una estrategia de reintentos; añade tu fallback.
¿Qué registrar?
Por llamada: tarea, función, modelo, prompt token, completion token, total y latencia. Agrega por función antes de fijar presupuesto.
¿Cuánto cuesta una revisión?
Leer el catálogo no genera llamadas. Las llamadas de prueba se facturan por uso; el prompt pide aprobación antes.
Flujos relacionados
Responde preguntas de soporte desde tu propia documentación
Crea un LiveDoc, carga el centro de ayuda y el runbook interno, recupera los pasajes que responden al ticket y deja que el modelo responda solo con esas evidencias.
Abrir el flujo de trabajoInvestigaciónConvierte una pregunta en un brief de investigación con fuentes
Pregunta a la web, guarda las páginas detrás de la respuesta como Markdown, añade lo que dicen los profesionales en X y conserva las evidencias en un LiveDoc que puedes consultar después.
Abrir el flujo de trabajoOficinaConvierte una página de investigación en una presentación
Extrae la página, guárdala como contexto LiveDoc, deja que la API PPT Task construya el deck y consulta hasta obtener el enlace final.
Abrir el flujo de trabajoHazlo tuyo
La misma receta, adaptada a cómo entregas de verdad.
Primero solo registrar
Antes de producción, registra una semana de uso y luego decide bajar de nivel.
Presupuesto por función
Fija un límite mensual por función y alerta o degrada al superarlo.
Fijar proveedor por latencia
Cuando la latencia importa más que el precio, fija el proveedor y añade tu fallback.
Seguir
Las páginas de referencia detrás de esta receta y los siguientes pasos.