Resumen
AI agents ese usar search APIs puede rack up costs rapidamente if usage es no monitored. Este flujo de trabajo ejecuta on el first of cada mes, consultas your Scavio usage datos, calculates el anterior month's spend by agent o project, compara contra budget, y forecasts next month's costs basado on el usage tendencia. It envia un budget informe y alertas if cualquier project exceeded its allocation. At $0.005 per credit, este flujo de trabajo ayuda you mantener agent search costs bajo control.
Desencadenador
Cron 1st of mes 9 AM UTC
Programación
Mensual 1st 9 AM
Pasos del flujo de trabajo
Cargar Budget Configuracion
Leer per-project budget allocations y alerta umbrales de un configuracion file.
Agregar Usage by Project
Leer usage registros de el past mes y group credit consumption by project o agent ID.
Calcular Spend y Comparar Budget
Multiply credits by $0.005 to obtener dollar spend. Comparar cada project contra its mensual budget.
Forecast Next Month
Use el 3-mes tendencia to project next month's usage y marcar projects probable to exceed budget.
Generar Budget Informe
Crear un structured informe con per-project spend, budget utilization, y forecast.
Enviar Alerts
Notificar project owners via Slack o correo electronico if they exceeded budget o son trending sobre.
Implementacion en Python
import json, os
from pathlib import Path
from datetime import date, timedelta
COST_PER_CREDIT = 0.005
BUDGET_FILE = Path("search_budgets.json")
USAGE_LOG = Path("search_usage.jsonl")
REPORTS_DIR = Path("budget_reports")
REPORTS_DIR.mkdir(exist_ok=True)
def load_usage(month_str: str) -> dict:
"""Load usage from JSONL log, filtered to the given month."""
usage = {}
if not USAGE_LOG.exists():
return usage
for line in USAGE_LOG.read_text().strip().split("\n"):
if not line:
continue
entry = json.loads(line)
if entry.get("date", "").startswith(month_str):
project = entry.get("project", "default")
usage.setdefault(project, 0)
usage[project] += entry.get("credits", 0)
return usage
def load_history(months: int = 3) -> list:
"""Load usage for the last N months for forecasting."""
history = []
today = date.today()
for i in range(1, months + 1):
d = today.replace(day=1) - timedelta(days=30 * i)
month_str = d.strftime("%Y-%m")
history.append(load_usage(month_str))
return history
def forecast(history: list, project: str) -> float:
values = [h.get(project, 0) for h in history if project in h]
if not values:
return 0
return sum(values) / len(values)
def run():
budgets = json.loads(BUDGET_FILE.read_text())
last_month = (date.today().replace(day=1) - timedelta(days=1)).strftime("%Y-%m")
usage = load_usage(last_month)
history = load_history(3)
report = {"month": last_month, "projects": []}
alerts = []
for project, budget_credits in budgets.items():
credits_used = usage.get(project, 0)
spend = credits_used * COST_PER_CREDIT
budget_dollars = budget_credits * COST_PER_CREDIT
utilization = credits_used / max(budget_credits, 1) * 100
forecasted = forecast(history, project)
forecasted_spend = forecasted * COST_PER_CREDIT
entry = {
"project": project,
"credits_used": credits_used,
"spend_usd": round(spend, 2),
"budget_usd": round(budget_dollars, 2),
"utilization_pct": round(utilization, 1),
"forecast_credits": round(forecasted),
"forecast_usd": round(forecasted_spend, 2),
}
report["projects"].append(entry)
if utilization > 100:
alerts.append(f"OVER BUDGET: {project} used {utilization:.0f}% of budget")
if forecasted > budget_credits * 1.2:
alerts.append(f"FORECAST ALERT: {project} trending ${forecasted_spend:.2f} vs ${budget_dollars:.2f} budget")
out = REPORTS_DIR / f"budget_{last_month}.json"
out.write_text(json.dumps(report, indent=2))
print(f"Budget report for {last_month}:")
for p in report["projects"]:
print(f" {p['project']}: ${p['spend_usd']} / ${p['budget_usd']} ({p['utilization_pct']}%)")
for a in alerts:
print(f" ALERT: {a}")
run()Implementacion en JavaScript
const fs = await import('fs');
const COST_PER_CREDIT = 0.005;
const budgets = JSON.parse(fs.readFileSync('search_budgets.json', 'utf8'));
const USAGE_LOG = 'search_usage.jsonl';
const REPORTS_DIR = 'budget_reports';
try { fs.mkdirSync(REPORTS_DIR); } catch {}
function loadUsage(monthStr) {
const usage = {};
try {
const lines = fs.readFileSync(USAGE_LOG, 'utf8').trim().split('\n');
for (const line of lines) {
if (!line) continue;
const entry = JSON.parse(line);
if ((entry.date||'').startsWith(monthStr)) {
const project = entry.project || 'default';
usage[project] = (usage[project]||0) + (entry.credits||0);
}
}
} catch {}
return usage;
}
function getLastMonth() {
const d = new Date();
d.setDate(0);
return d.toISOString().slice(0,7);
}
function loadHistory(months) {
const history = [];
const now = new Date();
for (let i = 1; i <= months; i++) {
const d = new Date(now.getFullYear(), now.getMonth()-i, 1);
history.push(loadUsage(d.toISOString().slice(0,7)));
}
return history;
}
const lastMonth = getLastMonth();
const usage = loadUsage(lastMonth);
const history = loadHistory(3);
const report = {month:lastMonth, projects:[]};
const alerts = [];
for (const [project, budgetCredits] of Object.entries(budgets)) {
const creditsUsed = usage[project]||0;
const spend = creditsUsed * COST_PER_CREDIT;
const budgetUsd = budgetCredits * COST_PER_CREDIT;
const utilization = creditsUsed / Math.max(budgetCredits,1) * 100;
const histVals = history.map(h=>h[project]||0).filter(v=>v>0);
const forecasted = histVals.length ? histVals.reduce((s,v)=>s+v,0)/histVals.length : 0;
report.projects.push({project, creditsUsed, spendUsd:Math.round(spend*100)/100, budgetUsd:Math.round(budgetUsd*100)/100, utilizationPct:Math.round(utilization*10)/10, forecastCredits:Math.round(forecasted), forecastUsd:Math.round(forecasted*COST_PER_CREDIT*100)/100});
if (utilization > 100) alerts.push('OVER BUDGET: '+project+' used '+Math.round(utilization)+'%');
if (forecasted > budgetCredits * 1.2) alerts.push('FORECAST: '+project+' trending $'+(forecasted*COST_PER_CREDIT).toFixed(2)+' vs $'+budgetUsd.toFixed(2));
}
fs.writeFileSync(REPORTS_DIR+'/budget_'+lastMonth+'.json', JSON.stringify(report, null, 2));
console.log('Budget report for '+lastMonth+':');
report.projects.forEach(p => console.log(' '+p.project+': $'+p.spendUsd+' / $'+p.budgetUsd+' ('+p.utilizationPct+'%)'));
alerts.forEach(a => console.log(' ALERT: '+a));Plataformas utilizadas
Búsqueda web con grafo de conocimiento, PAA y resúmenes de IA