Docs · 60
Modelo de costos.
Cómo se calcula el USD de cada run, qué es el pricing_snapshot, y cómo navegar el reporting.
El problema
Anthropic cobra por token consumido, con rates diferentes según el modelo y el tipo de token:
| Tipo | Qué es |
|---|---|
input_tokens | Lo que mandás (system + user + tool_results en el último turno). |
output_tokens | Lo que devuelve el modelo. |
cache_read_input_tokens | Input que ya estaba cacheado en el prompt cache (descuento agresivo). |
cache_creation_input_tokens | Input que escribís al cache por primera vez (premium). |
Los rates están en packages/db/src/pricing.ts como USD por millón de tokens. Update manual cuando Anthropic publica precios nuevos — un solo archivo, re-exportado donde haga falta.
export const PRICING_PER_MTOK: Record<string, ModelPricing> = {
'claude-opus-4-7': { input: 15, output: 75, cacheRead: 1.5, cacheCreate: 18.75 },
'claude-sonnet-4-6': { input: 3, output: 15, cacheRead: 0.3, cacheCreate: 3.75 },
'claude-haiku-4-5-20251001': { input: 1, output: 5, cacheRead: 0.1, cacheCreate: 1.25 },
};
El snapshot
Cuando un run termina, capturamos los rates vigentes en workspace_runs.pricing_snapshot (jsonb). Razón: si Anthropic baja Opus a la mitad mañana, queremos que el cost-report de la semana pasada siga mostrando lo que pagaste, no lo que pagarías re-corriéndolo hoy.
// Stage del workflow donde se captura — al cerrar el job:
await sb.from('workspace_runs').update({
status: 'done',
usage: anthropicUsage,
pricing_snapshot: PRICING_PER_MTOK[model], // snapshot del rate actual
duration_ms,
finished_at: new Date().toISOString(),
}).eq('id', runId);
costUsd() prefiere pricing_snapshot si está; falla al lookup actual si no (runs viejos pre-feature) o a 0 si el modelo no tiene rate configurado.
Dónde se ve
| Lugar | Qué muestra |
|---|---|
/migrations/[id]/overview → "Costo acumulado" | Suma USD de todos los workspace_runs del workspace. |
/ops → métrica "Costo total" | Suma USD del período + filtros activos (kit, stage, status, model). |
/ops/trends | Costo por día / semana / mes. |
/kits/[id] → columna "Costo total" | Suma USD acumulado por versión del kit. |
cost-report CLI | Tabla agrupada por kit + modelo, exportable a CSV. |
Casos borde
- Run sin usage: pasa cuando el worker fallea antes de cerrar la session (timeout, network error).
usagequeda null ycostUsddevuelve 0. Esto subestima el costo real porque Anthropic igual cobra por los tokens efectivamente procesados aunque no nos lleguen los counters. - Modelo desconocido: si el manifest declara un modelo que no está en
PRICING_PER_MTOK,costUsddevuelve 0. Preferimos under-report a inflar. Solución: agregar el rate al pricing table. - Cache hits dramáticos: los kits que reusan mucho prompt cache (skills compartidos, system prompts grandes) pueden tener
cache_read_input_tokens>>>input_tokens. El descuento es real — 10x más barato. Por eso lo trackeamos por separado en lugar de mergearlo con input.
Optimizar el costo
Tres palancas, ordenadas por impact típico:
-
Modelo correcto para cada agent — agents simples (extractor de campos, classifier) corren bien en Haiku 4.5 a 1/15 del precio de Opus. Configurarlo por agent en el manifest:
agents: - id: classifier model: claude-haiku-4-5-20251001 # override del default del kit -
Prompt caching — system prompts largos + skills grandes son los que más se benefician. Mantenelos estables entre runs (no incluyas datetimes, IDs random, etc.) para que Anthropic los cachee con el
prompt_cache: 1hya configurado. -
Estructura de outputs — si el agent emite tokens que no necesitás (chain-of-thought verbose, repetir contexto), eso es output cost directo. Pedile que sea conciso en el system prompt.
Auditar un run individual
pnpm --filter web inspect-run <run_id>
Imprime:
- Stage, status, duración
- Anthropic IDs (session, agent, env, memory_store)
- Tokens por tipo + costo desglosado
- Mensajes de error si falló