SmartGateSmartGate

FinOps Lead: Own the AI Bill — Measure, Alert, Report

For the person who signs off on the AI bill, SmartGate turns agent spend into numbers you can defend in a review: a per-team quota percentage with an 80% and a 100% alert that arrives before the cap does, avoided-token dollars priced against one fixed reference model, and audit rows summed into a per-tool spend report.

Short answer: For the person who signs off on the AI bill, SmartGate turns agent spend into numbers you can defend in a review: a per-team quota percentage with an 80% and a 100% alert that arrives before the cap does, avoided-token dollars priced against one fixed reference model, and audit rows summed into a per-tool spend report. You pay a platform fee and share revenue only after $15 of measured savings in a month.

Key takeaways

  • Every dollar on the dashboard is derived, not asserted. autTokensToEstUsdAvoided converts avoided tokens at a fixed internal rate, and a reference price table gives the estimate a baseline that does not move when a provider changes its list price.
  • The cap has two warnings in front of it. shouldNotifyQuotaThreshold fires at 80% and again at 100%, and each email is claimed once per user, per team, per month.
  • Compression is a measurement, not a claim. count_tokens sizes the text a budget check is about to price, so the savings a compression pass reports can be re-derived from the same counter.
  • Spend reports come from the audit log. transformAuditEntry normalizes raw events and aggregateAutFromEntries sums avoided tokens into a total plus a per-tool breakdown.
  • Start by metering one team: connect a single client on the Free plan (2M tokens/month), set the monthly limit, and enable the 80% email — the first overspend you hear about is then a warning rather than an invoice.

For the person who signs the invoice

SmartGate is an MCP-native algorithm gateway for token control, traffic shaping, and agent audit — not a model host and not a wrapper around one. Where an AI bill goes wrong is rarely one expensive prompt; it is tool traffic, the fetches, searches, and context blobs an agent produces around every model call and re-sends on every turn. Bounding that traffic is the job of the seven smart_* tools — smart_fetch, smart_search, smart_context_gate, smart_dedup, smart_budget_guard, smart_memory, and smart_pipe — and metering it is the job of the twelve excerpts below.

Those excerpts answer the four questions a FinOps lead has to be able to answer about any AI program: what we used, what we avoided paying for, who is told before a limit is reached, and what the report says. In practice you connect one MCP URL per developer or agent instead of a provider key per tool, and the commercial model is "Pay for the platform. Share only when you save." — the savings share starts only after $15 of measured savings, and on Pro it is capped at roughly $36/month (SmartGate pricing).

Why AI spend lands on your desk now

AI spend stopped being an experiment and became a line item, and the person asked to explain it is usually the FinOps lead. Gartner forecasts worldwide AI spending of $2.59 trillion in 2026, up 47% year over year (Gartner via CFOtech). The FinOps Foundation's State of FinOps 2025 survey — 861 respondents responsible for roughly $69 billion in public cloud spend — found that a majority of teams now manage AI spend (63%, up from 31% a year earlier), while workload optimization and waste reduction stayed the top priority for 50% of practitioners (FinOps Foundation).

The gap those numbers bracket is this page's subject. The spend is growing fast and moving into the finance mandate, while most of the tooling that reports on it was built for cloud resources rather than for the compress-and-call traffic an agent loop generates. Two habits close that gap: attribute every token to a team and a tool, and warn about the limit before it is reached rather than explaining it afterwards. The engineering half of the same argument — the counters, and what a single call costs — is in optimizing agent execution cost.

autTokensToEstUsdAvoided: the dollar value of tokens that never reached a model

The savings figure is arithmetic, and that is the point. autTokensToEstUsdAvoided divides a count of avoided tokens by one million and multiplies by an internal per-million savings rate, so a token count becomes a dollar estimate. Tokens are "avoided" when the gateway keeps them out of a model call — by compressing context, deduplicating near-identical passages, or answering from a cheaper path — and those dollars are reported next to the dollars you did spend. That is what a unit-economics view needs: a numerator you can quote in a review without reconciling it line by line against a provider invoice. The unit model and the billing arithmetic behind that conversion are worked through in AI token cost.

The techniques that produce avoided tokens — capping usage, shrinking context before the model sees it, not repeating work — are collected in token optimization techniques for AI apps.

# lib/analytics/price-table.ts — source lines 14–16 (autTokensToEstUsdAvoided)
function autTokensToEstUsdAvoided(tokens: number): number {
  return (tokens / 1_000_000) * INTERNAL_SAVINGS_USD_PER_M;
}

PromptCompressor.control_sentence_budget: the per-turn budget behind AI spend management

The only compression worth having is compression that keeps the answer. control_sentence_budget is the sentence-selection step in that trade. For each context block it takes a target token figure, a budget ratio (token_budget_ratio, 1.4 by default) and optional keep-first, keep-last and high-priority sentence counts, ranks the sentences, then spends the budget in rank order and stops when it runs out. Two properties make the outcome reviewable rather than improvised: the budget is expressed in tokens instead of characters, and the sentences that survive are chosen by rank, so "we compressed the prompt" is a reproducible setting somebody can point at rather than a trim someone performed by hand.

That is the guardrail half of AI spend management — the half that keeps a looping agent from re-sending the same context on every turn. How much context can be carried in total, and what happens at the edge of that window, is covered in context window management techniques. Less context per turn is also less compute per turn, the compute-side cost recorded in inference cost.

# backend/smartgate/modules/context_gate/algorithm.py — source lines 1260–1275 (PromptCompressor.control_sentence_budget)
def control_sentence_budget(
        self,
        context: List[str],
        target_token: float,
        keep_first_sentence: int = 0,
        keep_last_sentence: int = 0,
        keep_sentence_number: int = 0,
        high_priority_bonus: int = 100,
        token_budget_ratio: float = 1.4,
        question: str = "",
        condition_in_question: str = "none",
        rank_method: str = "longllmlingua",
        context_segs: List[List[str]] = None,
        context_segs_rate: List[List[float]] = None,
        context_segs_compress: List[List[bool]] = None,
    ):
# backend/smartgate/modules/context_gate/algorithm.py — source lines 1386–1396 (PromptCompressor.control_sentence_budget)
        sentence_flags = [False] * N
        if target_token < 0:
            target_token = 100
        target_token *= token_budget_ratio
        res = []
        for idx, _ in sent_sort:
            idx = flags[idx]
            target_token -= sentence_tokens_length[idx]
            sentence_flags[idx] = True
            if target_token < 0:
                break

BudgetCheckRequest: one contract for check, count and record — MCP stdio clients included

Every decision the platform makes about money starts as one request, and BudgetCheckRequest is the schema behind it. Three details matter to finance. First, action is constrained to exactly three verbs — check (may this call proceed), count (what would this text cost) and record (book the usage) — so there is no fourth outcome in which work happens without being metered. Second, team_id travels with the request, which is the field that turns a stream of tokens into a chargeback line. Third, the request can carry monthly_limit, entitlement_limit and a per-client client_budget, which is where a written policy becomes a parameter instead of a conversation.

Because one request shape serves both HTTP and MCP callers, a desktop client connected over stdio and a hosted agent reach the same decision path; the difference is transport, not policy. The transport itself is described in MCP transports such as stdio.

# backend/smartgate/modules/budget_guard/models.py — source lines 5–19 (BudgetCheckRequest)
class BudgetCheckRequest(BaseModel):
    model_config = ConfigDict(extra="ignore")

    action: str = Field(..., pattern="^(check|count|record)$")
    team_id: Optional[str] = None
    model: Optional[str] = None
    text: Optional[str] = None
    prompt_tokens: Optional[int] = 0
    completion_tokens: Optional[int] = 0
    cost: Optional[float] = 0.0
    monthly_limit: Optional[int] = None
    entitlement_limit: Optional[int] = None
    client_budget: Optional[Dict[str, Any]] = None
    audit: bool = True
    source: Optional[str] = None

count_tokens: making prompt compression measurable

A compression claim is only worth the measurement behind it. count_tokens is that measurement: it encodes a string with the gateway's default tokenizer and returns the length — the number a budget check prices, and the number a compression pass moves. Counting tokens rather than characters is what makes a compression ratio comparable across languages and content types, and it is why two teams with the same word count can end up with very different bills. In reporting terms this is the smallest unit of account in the product: spent tokens, avoided tokens, quota percentages and dollar estimates are all downstream of a count.

The same count-before-you-call discipline, applied to a whole backend, is in a low-cost backend design.

# backend/smartgate/modules/budget_guard/algorithm.py — source lines 32–33 (count_tokens)
def count_tokens(text: str) -> int:
            return len(_default_encoding.encode(text, disallowed_special=()))

computeQuotaRingDisplay: the per-team meter on the dashboard

A quota number that only exists in a table is not a control; the meter has to be visible next to the work. computeQuotaRingDisplay takes used and cap, computes the used percentage with the same clamp the report uses, and returns what the ring shows in its centre — "used" or "left" — plus a stroke colour keyed to how full it is. The finance-relevant property is that the chart and the spreadsheet cannot disagree: both derive from one clamped percentage, so the picture a team sees in the product is the number you review. When a business unit asks what its share of the AI budget looks like this month, this is what it is looking at. The counts that feed the ring, and how they are attributed to a team and a tool, are set out in AI token usage.

Setting and enforcing that cap is a different mechanism, described in enforcing a token quota per team.

# lib/analytics/quota-ring-display.ts — source lines 9–19 (computeQuotaRingDisplay)
function computeQuotaRingDisplay(
  used: number,
  cap: number,
  display: QuotaRingDisplay = "used",
) {
  const usedPct = cap > 0 ? Math.min(100, Math.round((used / cap) * 100)) : 0;
  const centerPct =
    display === "used" ? usedPct : Math.max(0, 100 - usedPct);
  const label = display === "used" ? "used" : "left";
  return { usedPct, centerPct, label, strokeColor: strokeColor(usedPct) };
}

shouldNotifyQuotaThreshold: deciding when 80% and 100% are worth an email

The alert decision is deliberately narrow. shouldNotifyQuotaThreshold returns true only inside a band: at threshold 80, when usage is at least 80% and still below 100%; at threshold 100, when usage has reached or passed it. Limits that are zero, negative, non-finite or effectively unlimited never alert, so a plan without a hard cap generates no noise. The 80% warning exists so that the exhaustion notice is never the first time a team learns what it has been consuming. For finance that is the difference between a mid-month course correction and an explanation written after the fact.

# lib/jobs/quota-email-keys.ts — source lines 16–26 (shouldNotifyQuotaThreshold)
function shouldNotifyQuotaThreshold(
  used: number,
  limit: number,
  threshold: 80 | 100,
): boolean {
  if (limit <= 0 || !Number.isFinite(limit) || limit >= Number.MAX_SAFE_INTEGER / 2) {
    return false;
  }
  const pct = quotaUsagePercent(used, limit);
  return threshold === 80 ? pct >= 80 && pct < 100 : pct >= 100;
}

runQuotaEmailNotifications: the job that tells people before the cap bites

This job turns thresholds into messages addressed to named people. runQuotaEmailNotifications scans every team, reads each team's quota, skips teams with no real limit, computes the percentage once, then walks each member's notification preferences and sends only to the members who opted into the 80% alert, the 100% alert or both. Each message carries the used count, the limit and the percentage into the email, and the run tallies scanned, sent, skipped and errored counts, so one failed usage lookup is reported instead of silently dropped. The failure mode this avoids is a notification nobody trusts: it names the team, the threshold and the position against the limit, and it does not have to be watched to be believed.

The delivery mechanics behind those alerts - a durable queue, a claim before the send, and a retry that cannot duplicate - are the same primitives described in AI automation for SaaS operations.

# lib/jobs/quota-email-notifications.ts — source lines 88–106 (runQuotaEmailNotifications)
  for (const team of teams) {
    result.teamsScanned += 1;

    let quota: Awaited<ReturnType<typeof checkQuota>>;
    try {
      quota = await checkQuota(team.id, team.monthlyTokenLimit, team.plan);
    } catch (err) {
      result.errors.push(
        `team ${team.id}: usage lookup failed — ${err instanceof Error ? err.message : String(err)}`,
      );
      continue;
    }

    if (quota.limit === Infinity) {
      result.skipped += team.members.length;
      continue;
    }

    const percentUsed = quotaUsagePercent(quota.used, quota.limit);
# lib/jobs/quota-email-notifications.ts — source lines 130–162 (runQuotaEmailNotifications)
      for (const { level } of thresholds) {
        if (!shouldNotifyQuotaThreshold(quota.used, quota.limit, level)) {
          continue;
        }

        if (await wasQuotaEmailSent(user.id, team.id, level)) {
          result.skipped += 1;
          continue;
        }

        const claimed = await markQuotaEmailSent(user.id, team.id, level);
        if (!claimed) {
          result.skipped += 1;
          continue;
        }

        try {
          await sendQuotaAlertEmail({
            to: user.email,
            threshold: level,
            teamName: team.name,
            used: quota.used,
            limit: quota.limit,
            percentUsed,
          });
          result.emailsSent += 1;
        } catch (err) {
          result.errors.push(
            `user ${user.id} team ${team.id} @${level}%: ${err instanceof Error ? err.message : String(err)}`,
          );
        }
      }
    }

resolve_budget_count_model: attributing a count in a Model Context Protocol example

A token count is only actionable once you know which model's pricing it is measured against, and that question is where a concrete picture of SmartGate in an MCP request helps. resolve_budget_count_model takes the request state and the model named in the body, and falls back to the configured budget_count_model value — deepseek-chat — when the body names none. For finance the implication is plain: the same text costs different amounts against different models, so a budget check needs an explicit model to stay comparable month over month, and an unattributed call falls back to a documented default rather than to whatever key the client happened to send. This Model Context Protocol example follows the round trip such a call travels, from the client's JSON-RPC request to the tool's answer. The published cards that set those per-model rates are the subject of AI model pricing.

# backend/smartgate/core/effective_settings.py — source lines 77–82 (resolve_budget_count_model)
def resolve_budget_count_model(request_state: Any, body_model: str | None) -> str:
    if body_model:
        return body_model
    es = getattr(request_state, "effective_settings", None) or {}
    defaults = es.get("defaults") or {}
    return str(defaults.get("budget_count_model", "deepseek-chat"))

quotaEmailSentKey: one alert per user, per team, per period

An alert that fires on every scheduled run is noise, and noise is how a warning ends up filtered into a folder nobody opens. quotaEmailSentKey builds the deduplication key out of four parts — user, team, threshold and month — into one string, quota_email_sent:userId:teamId:threshold:yyyy-mm. The month is the part that does the work: it bounds each alert to one send per period and lets the counter reset when the calendar rolls over, with no cleanup job to maintain and nothing for anyone to remember to clear. Read the other way round, the key is also a record: it says that a threshold was reached in a given month for a given team, tracked separately for 80% and for 100%.

# lib/jobs/quota-email-keys.ts — source lines 2–9 (quotaEmailSentKey)
function quotaEmailSentKey(
  userId: string,
  teamId: string,
  threshold: 80 | 100,
  month = new Date().toISOString().slice(0, 7),
): string {
  return `quota_email_sent:${userId}:${teamId}:${threshold}:${month}`;
}

budgetSnapshotKey: the cached snapshot the finance dashboard reads

Dashboards are opened far more often than spend changes. budgetSnapshotKey returns the per-team cache key budget_snapshot:teamId, which is what lets a dashboard read a team's snapshot instead of recomputing a month of usage on every page load. The trade-off is worth stating out loud in a review: a snapshot can lag live usage briefly, and in exchange the numbers open immediately while a budget conversation is happening. Where the report is the surface people argue over, the latency of the surface is part of whether it gets used.

# lib/budget/snapshot-cache.ts — source lines 3–5 (budgetSnapshotKey)
function budgetSnapshotKey(teamId: string): string {
  return `budget_snapshot:${teamId}`;
}

transformAuditEntry: turning raw audit rows into reportable spend

A spend report is only as good as the rows behind it, and raw audit events arrive as loose, untyped records. transformAuditEntry normalizes each one: it categorizes the tool, extracts the correlation and trace identifiers, the source address, the token count, the success status and the team id, and builds a human-readable "who" for the row — the playground console, an agent platform, or a truncated team id. One field deserves a finance reader's attention: costSaved is deliberately null at this stage, because the dollar figure is computed later, in the aggregation step. That separation is a feature rather than an omission — the log records what happened, pricing is applied where the rate table lives, and a change of rate does not require rewriting history.

The same rows answer the engineering half of the question, which is what an LLM observability layer reads the correlation ids and the token counts for.

# lib/smartgate/audit-logs.ts — source lines 95–119 (transformAuditEntry)
function transformAuditEntry(raw: Record<string, unknown>): LogEntry {
  const auditTool = String(raw.tool ?? "");
  const params = parseParams(raw.params);
  const route = typeof params.route === "string" ? params.route : null;
  const agentPlatform =
    typeof params.agent_platform === "string" ? params.agent_platform : null;

  const category: ToolType =
    ACCESS_AUDIT_TOOLS.has(auditTool) || auditTool.startsWith("access_")
      ? "security"
      : AUDIT_TOOL_TO_CATEGORY[auditTool] ??
        (route === "playground" ? "compression" : "search");

  const correlationId =
    typeof params.correlation_id === "string" && params.correlation_id.trim()
      ? params.correlation_id.trim()
      : null;

  const traceId =
    typeof params.trace_id === "string" && params.trace_id.trim()
      ? params.trace_id.trim()
      : null;

  const ipAddress =
    typeof params.source_ip === "string" ? params.source_ip : null;
# lib/smartgate/audit-logs.ts — source lines 128–147 (transformAuditEntry)
  const success = raw.success === true;
  const status: LogStatus =
    raw.success === true ? "success" : raw.success === false ? "error" : "pending";

  const teamId = typeof raw.team_id === "string" ? raw.team_id : null;

  return {
    id: String(raw.id ?? ""),
    timestamp: formatTimestamp(raw),
    tool: category,
    auditTool,
    toolLabel: TOOL_LABELS[category] ?? auditTool,
    status,
    requestId: String(raw.request_id ?? ""),
    correlationId,
    traceId,
    route,
    agentPlatform,
    params,
    teamId,
# lib/smartgate/audit-logs.ts — source lines 165–166 (transformAuditEntry)
    costSaved: null,
    ipAddress,

aggregateAutFromEntries: summing avoided tokens across the audit log

The last step is the sum that becomes a line on the report. aggregateAutFromEntries walks the audit entries, accumulates avoided tokens — direct and estimated — into a total and into per-tool buckets, and separately adds raw against compressed token counts for compression entries to work out an average compression percentage. Its result is the object the dashboard and the dollar conversions consume: a total, a per-tool breakdown and one compression figure, all computed from the same rows a compliance review reads. When somebody asks how the savings number was assembled, the answer is a query over these entries rather than a spreadsheet column with a formula nobody can audit. The same audit-to-report path, carried further into financial analysis, is walked in financial-data agents.

# lib/analytics/aggregate-aut.ts — source lines 80–127 (aggregateAutFromEntries)
function aggregateAutFromEntries(
  entries: AuditEntry[],
  opts: { includeEstimatedAut: boolean },
): AutAggregateResult {
  let autDirect = 0;
  let autEstimated = 0;
  let compressRaw = 0;
  let compressOutput = 0;
  const autByTool: Record<string, { direct: number; estimated: number }> = {};

  for (const entry of entries) {
    const slice = readAutSlice(entry);
    autDirect += slice.direct;
    autEstimated += slice.estimated;

    const bucket = autByTool[entry.tool] ?? { direct: 0, estimated: 0 };
    bucket.direct += slice.direct;
    bucket.estimated += slice.estimated;
    autByTool[entry.tool] = bucket;

    if (entry.tool === "compress" && entry.success) {
      const params = (entry.params ?? {}) as Record<string, unknown>;
      const raw = Number(params.raw_tokens ?? 0);
      const compressed = Number(params.compressed_tokens ?? 0);
      if (raw > 0) {
        compressRaw += raw;
        compressOutput += compressed;
      }
    }
  }

  const autDisplayed = opts.includeEstimatedAut
    ? autDirect + autEstimated
    : autDirect;

  const avgCompressionPct =
    compressRaw > 0
      ? Math.round(((compressRaw - compressOutput) / compressRaw) * 100)
      : 0;

  return {
    autDirect,
    autEstimated,
    autDisplayed,
    autByTool,
    avgCompressionPct,
  };
}

How SmartGate fits your FinOps stack

AI-spend controls divide by what they sit in front of. SmartGate's scope is deliberately narrower than "AI gateway": it governs MCP tool traffic — the fetch, search, compress and dedup calls that surround the model — and it meters what that traffic would otherwise have cost.

What you can see How overspend is stopped What you pay
SmartGate Per-tool avoided-token dollars, per-team quota percentage, audit rows turned into a spend report, 80%/100% email alerts A hard budget cap in the request path, per-plan rate limits, a monthly quota Platform fee; savings share starts only after $15 saved, Pro capped ~$36/mo (pricing)
Raw provider keys per developer One provider invoice, no per-team or per-tool breakdown Nothing until the provider's own limit Per token, per call, uncapped
LLM gateways (Kong, Portkey, LiteLLM) LLM request and response logs, latency and cost metrics Policies applied to LLM calls Seat or enterprise contracts (Kong · Portkey · LiteLLM)

Two honest readings of that table. If what you need is a record of model requests, an LLM gateway is a reasonable fit and AI gateway versus API gateway is the comparison worth reading before you commit. If you need the request path itself to refuse the call — a hard budget cap, per-plan rate limits, a monthly quota — and you want the fee to depend on measured savings instead of on how much you spend, that is the first row of the table.

How to get started

  1. Connect one client and let it run. Create a key, paste the generated config into your MCP host, and watch a week of real traffic before you change any policy — the first month's baseline is the most useful number you will have.
  2. Set a monthly limit and switch on the 80% alert. Give the team a cap and enable the 80% quota email, so the first notice that reaches you arrives with room to act.
  3. Review the report, not the model logs. The quota percentage, the usage ring and the avoided-token dollars all derive from the same counters, which is what makes them quotable in a budget meeting.

Start on the Free plan — 2M tokens/month, all seven tools, no card — with start free, then compare caps, rate limits and the savings-share terms against your own workload on the pricing page.

Frequently Asked Questions

What does this tell me that my model provider's invoice does not?

A provider invoice reports total tokens and total dollars. It does not say which team spent them, which tool drove the traffic, or how much compression and deduplication kept out of the call. SmartGate reports a per-team quota percentage, per-tool avoided tokens, and dollar estimates computed from a fixed reference price, so the same spend can be split by owner.

How is savings actually measured?

As avoided tokens: tokens that compression and deduplication kept from reaching the model, converted to dollars against an internal per-million rate, with a reference model price used as the comparison baseline. It is a reporting estimate for budget decisions, not a copy of your provider invoice, and it should not be reconciled against one line by line.

What am I billed for, exactly?

A platform fee, plus a savings share that begins only after $15 of measured savings in a month and is capped on Pro at roughly $36 per month. A team that saves nothing pays the platform fee and nothing else.

How do the 80% and 100% alerts work?

A scheduled job checks each team's usage percentage and emails the members who opted in: once at 80%, while there is still headroom, and again at 100%. Every alert is deduplicated per user, per team, per month, so the recurring job does not send repeat mail.

How long are audit logs kept?

Log retention is a plan entitlement: 7, 30, 90 or 180 days across Free, Pro, Teams and Enterprise. Exporting records, and keeping them beyond that window, is your responsibility.

Do engineering and finance see the same numbers?

Yes. The usage ring, the quota percentage and the dollar estimates derive from the same counters and the same audit rows, so the figure finance reviews is the figure the team sees.

Limitations and what this does not do

  • The dollar figure is an estimate, not an invoice. Avoided-token dollars and the reference model price are reporting figures; they are not your negotiated provider rate, and they should not be reconciled against a provider bill line by line.
  • Alerts are monthly and deduplicated. The 80% and 100% emails fire once each per user, per team, per month, so you will not get repeat nudges inside a period — the cap, not the email, is what stops traffic.
  • A cached snapshot can lag live usage. The budget snapshot is cached under a per-team key, so a report can sit slightly behind a burst of traffic.
  • Log retention is a plan setting. Audit rows expire on a schedule (7/30/90/180 days by plan) and a retention job deletes them; your own export and retention policy remains yours.
  • A gateway is not a financial system of record. SmartGate measures, alerts and reports; it does not replace your FinOps or accounting platform, and it does not reconcile your cloud or model invoices.

Sources

Method note

The code in this article is not transcribed. Each block was cut directly out of the slice body returned by the SmartGate slice API and then re-asserted byte-for-byte as a substring of that body before publication; the first line inside every fence records the file and the exact source lines. Symbols were pinned with whole-name containment (rule A level 2) and confirmed by a server-side slot-proof call before any of them entered the text.

The code quoted here has been verified internally by the SmartGate engineering team. Repository-relative paths are shown as-is; internal hosts, credentials and private infrastructure URLs were stripped from the source text before it reached this document.

Slice provenance

# SERP keyword Symbol File Source lines How it was pinned sha256(12)
1 autTokensToEstUsdAvoided avoided token dollars for AI spend management autTokensToEstUsdAvoided lib/analytics/price-table.ts 14–16 rule A L0 → remote symbol candidates → slot-proof b7c86b831274
2 PromptCompressor.control_sentence_budget sentence budget control for AI spend management PromptCompressor.control_sentence_budget backend/smartgate/modules/context_gate/algorithm.py 1260–1275, 1386–1396 rule A L0 → remote symbol candidates → slot-proof fc3a6d3be639
3 BudgetCheckRequest budget check request for MCP stdio clients BudgetCheckRequest backend/smartgate/modules/budget_guard/models.py 5–19 rule A L0 → remote symbol candidates → slot-proof 7b1d231d3c5f
4 count_tokens token counting for prompt compression in budget checks count_tokens backend/smartgate/modules/budget_guard/algorithm.py 32–33 rule A L0 → remote symbol candidates → slot-proof a8ecfefbe30b
5 computeQuotaRingDisplay quota ring display for usage dashboards computeQuotaRingDisplay lib/analytics/quota-ring-display.ts 9–19 rule A L0 → remote symbol candidates → slot-proof f102407a5e5e
6 shouldNotifyQuotaThreshold quota alert threshold decision at 80 and 100 percent shouldNotifyQuotaThreshold lib/jobs/quota-email-keys.ts 16–26 rule A L0 → remote symbol candidates → slot-proof f76bd013b3a0
7 runQuotaEmailNotifications quota email notification job for team alerts runQuotaEmailNotifications lib/jobs/quota-email-notifications.ts 88–106, 130–162 rule A L0 → remote symbol candidates → slot-proof 6647487605cc
8 resolve_budget_count_model Model Context Protocol example for spend attribution resolve_budget_count_model backend/smartgate/core/effective_settings.py 77–82 rule A L0 → remote symbol candidates → slot-proof 7194cb800a16
9 quotaEmailSentKey redis key for quota email dedupe quotaEmailSentKey lib/jobs/quota-email-keys.ts 2–9 rule A → slot-proof 28370cbe584a
10 budgetSnapshotKey budget snapshot cache key for team dashboards budgetSnapshotKey lib/budget/snapshot-cache.ts 3–5 rule A → slot-proof 9ef0217920ab
11 transformAuditEntry audit entry transform for spend reports transformAuditEntry lib/smartgate/audit-logs.ts 95–119, 128–147, 165–166 rule A → slot-proof 74fc29181e7a
12 aggregateAutFromEntries aggregate avoided tokens from audit entries aggregateAutFromEntries lib/analytics/aggregate-aut.ts 80–127 rule A → slot-proof 74b6c8dc6181

Every fenced block above was cut from the slice body and re-asserted against it byte-for-byte before publication. 4 of 8 sections pinned, 0 abstentions, 4 misses.