Usage, Quota & Spend Tracking (Español)
Descripción general
Sección titulada «Descripción general»Cada solicitud que pasa por OmniRoute genera un registro de uso que contiene:
- Identidad: qué clave de API, proveedor, modelo y combinación
- Tokens: tokens del prompt, tokens de finalización, tokens en caché y total
- Coste: importe en USD (calculado a partir de los datos de precios)
- Tiempos: latencia y marcas de tiempo de inicio/fin
- Estado: éxito, error, limitación por tasa, etc.
Estos registros se agregan en análisis, se conservan como instantáneas de cuota y se utilizan para aplicar límites de presupuesto por clave.
Solicitud ──▶ chatCore ──▶ usage.record() ──▶ SQLite │ ┌───────┼───────┐ ▼ ▼ ▼ análisis cuota facturación (panel) (aplicar) (exportar)Qué se registra
Sección titulada «Qué se registra»El servicio usage.ts captura un evento de uso para cada solicitud:
| Campo | Tipo | Origen |
|---|---|---|
id |
string | UUID generado al registrar |
apiKeyId |
string | La clave de API que inició la solicitud |
provider |
string | ID del proveedor (openai, anthropic, etc.) |
model |
string | ID del modelo (gpt-5, claude-opus-4-6, etc.) |
comboId |
string? | ID de la combinación si se enrutó mediante una combinación |
promptTokens |
number | De la respuesta del proveedor |
completionTokens |
number | De la respuesta del proveedor |
cachedTokens |
number | Tokens encontrados en caché (caché de prompts de Anthropic, etc.) |
totalTokens |
number | prompt + finalización |
costUsd |
number | Calculado a partir de los datos de precios |
latencyMs |
number | Duración total de la solicitud |
status |
enum | success, error, rate_limited, timeout, cancelled |
errorClass |
string? | Clase de error si status != success |
timestamp |
string | ISO 8601 UTC |
metadata |
object | Datos personalizados inyectados por plugins |
De dónde proceden los tokens
Sección titulada «De dónde proceden los tokens»Los tokens se extraen de la respuesta del proveedor en el controlador de respuestas:
// De open-sse/handlers/chatCore.tsconst response = await providerExecutor.execute(provider, request);const usage = response.usage || { prompt_tokens: 0, completion_tokens: 0, cached_tokens: 0,};Para los proveedores que no devuelven datos de uso (algunos proveedores basados en cookies web), OmniRoute estima los tokens mediante una heurística de ~4 caracteres por token (consulte open-sse/services/autoCombo/pipelineRouter.ts).
Tokens en caché
Sección titulada «Tokens en caché»OmniRoute registra cached_tokens por separado de prompt_tokens porque:
- El almacenamiento en caché de prompts de Anthropic aplica una tarifa reducida a los tokens en caché (el 10 % de la tarifa normal)
- Algunos proveedores devuelven
cache_read_input_tokens, cuyo precio debe calcularse de forma diferente - Los análisis pueden mostrar la tasa de aciertos de caché =
cached_tokens / prompt_tokens
Cálculo de costes
Sección titulada «Cálculo de costes»Los costes se calculan a partir de los datos de precios sincronizados desde LiteLLM (src/lib/pricingSync.ts):
| Modelo | Entrada $/1M | Salida $/1M | En caché $/1M |
|---|---|---|---|
| gpt-5 | $2.50 | $10.00 | — |
| claude-opus-4-6 | $15.00 | $75.00 | $1.50 |
| claude-sonnet-4-5 | $3.00 | $15.00 | $0.30 |
| gemini-2.5-pro | $1.25 | $10.00 | — |
La fórmula de coste (src/lib/usage/costCalculator.ts):
cost = (prompt_tokens - cached_tokens) * input_price + cached_tokens * cached_price + completion_tokens * output_price;¿Por qué se resta la parte en caché del prompt? La parte en caché tiene un precio independiente; aplicar el precio de entrada al prompt completo produciría un recuento excesivo.
Sincronización de precios
Sección titulada «Sincronización de precios»Los datos de precios se sincronizan automáticamente desde LiteLLM mediante el endpoint /api/pricing/sync (activado por la tarea cron integrada, no por una variable de entorno expuesta al usuario):
# Activación manualcurl -X POST http://localhost:20128/api/pricing/syncPara los modelos sin datos de precios, OmniRoute recurre a estimar el coste mediante tarifas medias internas (obtenidas de los datos de precios de LiteLLM).
Agregación por intervalo de fechas
Sección titulada «Agregación por intervalo de fechas»El módulo usageAnalytics.ts calcula los widgets del panel a partir de los datos de uso sin procesar. Admite 7 intervalos de tiempo:
| Intervalo | Ventana | Caso de uso |
|---|---|---|
1d |
Últimas 24 horas | Detección horaria de picos de coste |
7d |
Últimos 7 días | Revisión semanal |
30d |
Últimos 30 días | Facturación mensual |
90d |
Últimos 90 días | Análisis trimestral |
ytd |
Desde el 1 de enero del año en curso | Seguimiento del presupuesto anual |
all |
Todo el período | Estadísticas históricas |
custom |
Inicio/fin definidos por el usuario | Auditorías, consultas ad hoc |
Widgets calculados del panel
Sección titulada «Widgets calculados del panel»Para cualquier intervalo de fechas, la capa de análisis calcula:
| Widget | Descripción |
|---|---|
| Tarjetas de resumen | Solicitudes totales, coste total, tokens totales, tasa de éxito |
| Gráfico de tendencia diaria | Coste + tokens por día, apilados por modelo |
| Mapa de calor de actividad | Cuadrícula de hora del día × día de la semana, color = número de solicitudes |
| Desglose por modelo | Gráfico circular del coste por modelo |
| Desglose por proveedor | Gráfico de barras de las solicitudes por proveedor |
| Principales claves de API | Tabla de las 10 claves principales por coste |
| Análisis de errores | Tasa de errores a lo largo del tiempo, principales clases de error |
Acceso mediante programación
Sección titulada «Acceso mediante programación»import { computeAnalytics } from "@/lib/usageAnalytics";
const analytics = await computeAnalytics( history, // registros del historial de uso "7d", // intervalo de tiempo: "1d" | "7d" | "30d" | "90d" | "ytd" | "all" | "custom" connectionMap, // mapa de conexiones de proveedores (connectionId → nombre de la cuenta) { startDate: "2025-01-01", // opcional: para el intervalo "custom" endDate: "2025-06-01", // opcional: para el intervalo "custom" });
console.log(analytics.summary.totalCost); // 12.34 (centavos)console.log(analytics.byModel[0]); // { model, cost, requests, promptTokens, completionTokens }
---
## Aplicación de cuotas
La cuota por clave de API se aplica en dos lugares:
1. **Límite flexible** (`quotaWarnAt`): advertencia en el panel cuando el uso supera el umbral2. **Límite estricto** (`quotaLimit`): la solicitud se rechaza con HTTP 429 cuando se supera
### Configuración
```ts// Por clave de APIawait updateApiKey(keyId, { quotaWarnAt: 5_00, // $5.00 — mostrar advertencia quotaLimit: 10_00, // $10.00 — límite estricto quotaWindow: "month", // "day" | "week" | "month" | "all"});Flujo de aplicación
Sección titulada «Flujo de aplicación»Solicitud ──▶ quotaCheck() │ ├── ¿Dentro del límite? ──▶ permitir │ └── ¿Límite superado? ──▶ 429 Too Many Requests con encabezado Retry-AfterInstantáneas de cuota
Sección titulada «Instantáneas de cuota»La tabla quotaSnapshots almacena el estado histórico de las cuotas para el análisis de tendencias:
| Campo | Descripción |
| ———– | –––––––––––––––––––––– | —— | —–– |
| apiKeyId | La clave de la que se realiza el seguimiento |
| window | “day” | “week” | “month” |
| used | Coste utilizado en esta ventana (centavos) |
| limit | El límite (centavos) |
| resetAt | Cuándo se restablece la ventana |
| createdAt | Cuándo se tomó la instantánea |
Se toman instantáneas en cada solicitud que tenga un coste > 0 y se utilizan para:
- Mostrar la barra de progreso de la cuota en el panel
- Mostrar gráficos de tendencias de cuota de 30 días
- Activar alertas cuando el uso se aproxima al límite
API REST
Sección titulada «API REST»Listar registros de uso
Sección titulada «Listar registros de uso»GET /api/usage?range=7d&limit=100GET /api/usage?apiKeyId=key-123&range=30dGET /api/usage?provider=openai&range=1dRespuesta:
{ "records": [ { "id": "uuid", "apiKeyId": "key-123", "provider": "openai", "model": "gpt-5", "promptTokens": 1234, "completionTokens": 567, "totalTokens": 1801, "costUsd": 0.005, "latencyMs": 1234, "status": "success", "timestamp": "2026-06-08T12:00:00Z" } ], "total": 1234, "nextCursor": "..."}Obtener el resumen de análisis
Sección titulada «Obtener el resumen de análisis»GET /api/usage/analytics?range=7d&groupBy=modelRespuesta:
{ "summary": { "totalCost": 12.34, "totalRequests": 5678, "totalTokens": 12345678, "successRate": 0.987, "avgLatencyMs": 1234 }, "models": [ { "model": "gpt-5", "cost": 8.5, "requests": 1234, "tokens": 4567890 }, { "model": "claude-opus-4-6", "cost": 3.84, "requests": 234, "tokens": 234567 } ], "daily": [ { "date": "2026-06-01", "cost": 1.5, "requests": 800 }, { "date": "2026-06-02", "cost": 2.0, "requests": 1000 } ]}Consultar los análisis de uso
Sección titulada «Consultar los análisis de uso»Se accede a los datos de uso mediante el panel o las herramientas MCP, no mediante endpoints de exportación REST directa. Análisis disponibles:
/api/usage/analytics— métricas de uso agregadas (agrupadas por modelo, proveedor y clave)/api/usage/quota— estado actual de la cuota por clave de API/api/usage/history— registros del historial de solicitudes
Herramientas MCP
Sección titulada «Herramientas MCP»Dos herramientas MCP exponen los datos de uso a los agentes (consulta open-sse/mcp-server/tools/):
| Herramienta | Descripción |
|---|---|
omniroute_cost_report |
Genera un informe de costes por clave para un período determinado |
omniroute_check_quota |
Devuelve el estado actual de la cuota de una clave de API |
Ejemplo de invocación por parte de un agente:
{ "tool": "omniroute_cost_report", "args": { "period": "week" }}Retención y limpieza
Sección titulada «Retención y limpieza»Los datos de uso aumentan ~1-10KB por solicitud. A gran escala, esto puede ser significativo.
Configuración de retención
Sección titulada «Configuración de retención»La retención del historial de uso se configura mediante la configuración de la base de datos en la interfaz de usuario o mediante /api/settings/database.
De forma predeterminada, el historial de uso se conserva durante 90 días.
Limpieza
Sección titulada «Limpieza»Los registros antiguos se eliminan mediante src/lib/db/cleanup.ts:
- Se activa mediante el proceso cron en segundo plano
- Elimina de
usage_historylos registros más antiguos que el período de retención configurado enusageHistory
Estimación de almacenamiento
Sección titulada «Estimación de almacenamiento»| Tasa de solicitudes | Almacenamiento de 30 días | Almacenamiento de 90 días |
|---|---|---|
| 100 solicitudes/día | ~3MB | ~9MB |
| 1,000 solicitudes/día | ~30MB | ~90MB |
| 10,000 solicitudes/día | ~300MB | ~900MB |
| 100,000 solicitudes/día | ~3GB | ~9GB |
Para un tráfico muy alto, considere:
- Reducir el período de retención mediante la configuración de la base de datos
- Usar
aggregated_metricsen lugar de registros sin procesar (solo para análisis)
Consejos para optimizar costos
Sección titulada «Consejos para optimizar costos»1. Use el modelo adecuado
Sección titulada «1. Use el modelo adecuado»# Respuesta rápida — use un modelo económico y rápidocurl -d '{"model":"auto/fast","messages":[...]}'
# Tarea compleja — priorice la calidadcurl -d '{"model":"auto/smart","messages":[...]}'2. Habilite el almacenamiento en caché
Sección titulada «2. Habilite el almacenamiento en caché»El almacenamiento en caché de prompts de Anthropic permite ahorrar un 90% en contexto repetido:
// El almacenamiento en caché es automático — simplemente incluya el mismo prompt de sistema extensoconst response = await openai.chat({ model: "claude-sonnet-4-5", system: longSystemPrompt, // Se almacenará en caché automáticamente messages: [{ role: "user", content: "..." }],});3. Use compresión
Sección titulada «3. Use compresión»La compresión RTK + Caveman permite ahorrar entre un 15% y un 95% en sesiones con un uso intensivo de herramientas:
const config = { compression: { engine: "rtk", intensity: "aggressive", },};4. Establezca cuotas por clave
Sección titulada «4. Establezca cuotas por clave»Establezca siempre quotaLimit para evitar costos descontrolados:
await updateApiKey(keyId, { quotaLimit: 10_00 }); // Límite de $10/mes5. Audite a los principales consumidores
Sección titulada «5. Audite a los principales consumidores»Use el panel o /api/usage/analytics para agrupar por clave de API y ordenar por costo:
GET /api/usage/analytics?groupBy=apiKeySolución de problemas
Sección titulada «Solución de problemas»“El costo es mayor de lo esperado”
Sección titulada «“El costo es mayor de lo esperado”»- Consulte
/api/usage/analytics?groupBy=model— encuentre el modelo costoso - Consulte
/api/usage/analytics?groupBy=apiKey— encuentre al consumidor intensivo - Verifique que los datos de precios estén actualizados:
POST /api/pricing/sync
“Faltan registros”
Sección titulada «“Faltan registros”»- Compruebe la configuración de retención de la base de datos en Panel → Base de datos → Limpieza — la tarea de limpieza periódica (
src/lib/db/cleanup.ts) elimina los registros antiguos - Compruebe si hay errores en
src/lib/db/usage*.ts— los errores de escritura en la base de datos se registran, pero no se muestran - Verifique que la solicitud haya llegado realmente a
chatCore— compruebe el enrutamiento combinado
“La cuota no se aplica”
Sección titulada «“La cuota no se aplica”»- Compruebe la configuración
quotaLimitde la clave - Verifique que
quotaWindowesté configurado correctamente - Busque registros de
quotaSnapshots— deberían crearse con cada solicitud
Véase también
Sección titulada «Véase también»- DATABASE_GUIDE.md — Esquema de las tablas de uso
- ENVIRONMENT.md — Variables de entorno de sincronización de precios
- AUTO-COMBO.md — Cómo
auto/fastyauto/cheapreducen los costos - API_REFERENCE.md — Referencia completa de
/api/usage/* - Fuente:
open-sse/services/usage.ts,src/lib/usageAnalytics.ts,src/lib/db/usage*.ts
HagiCode
HagiCode es un espacio de trabajo de programación con agentes, flujos estructurados, ejecución multiagente y vistas de Hero Dungeon.
Convierte ideas en software útil con un flujo de trabajo con agentes más inteligente, rápido y ameno.

- SmartLos flujos estructurados convierten la intención en un itinerario ejecutable desde la idea hasta la entrega.
- EfficientLos flujos multiagente permiten avanzar en paralelo con la investigación, implementación y revisión.
- FunHero Dungeon hace que las largas sesiones de programación sean visuales y colaborativas.