Agent DocsDeveloper documentation
Admin Guide

FinOps & Cost Management

Cost attribution, budgets, model tiers, and chargeback

FinOps and Cost Management

This guide covers how the Enterprise Agentic AI Platform tracks, controls, and optimizes LLM costs across tenants, agents, and models. All LLM calls are routed through T-Systems AI Foundation Services (AIFS), and cost attribution is built into every layer of the request pipeline.


Cost Attribution Model

Every LLM call produces a cost record that is attributed along four dimensions: agent, tenant, user, and model. The platform records token counts (input and output) on each execution and computes a USD cost using the model's pricing entry.

How costs are tracked

  1. Per-execution recording -- When an LLM call completes, the API gateway captures usage.prompt_tokens and usage.completion_tokens from the AIFS response. These are stored in the executions table as a token_usage JSONB column with the structure { input, output, cost }.

  2. Real-time Redis counters -- The circuit breaker module (services/api-gateway/src/lib/circuit-breaker.ts) increments three Redis counters after every call:

    • cost:daily:{agentId}:{YYYY-MM-DD} -- per-agent daily spend (48h TTL)
    • cost:daily:{tenantId}:{YYYY-MM-DD} -- per-tenant daily spend (48h TTL)
    • cost:monthly:{tenantId}:{YYYY-MM} -- per-tenant monthly spend (35-day TTL)
  3. Execution-level aggregation -- The getFinOps() repository function queries all executions within the current month and aggregates costs into costByModel, costByAgent, costByTenant, and dailyCosts breakdowns. This powers the FinOps Center dashboard in the Admin Console.

  4. Workflow-level totals -- The agent_workflows table tracks total_input_tokens, total_output_tokens, and total_cost across multi-turn durable workflows managed by Temporal.

Token usage structure

// services/api-gateway/src/lib/domain-types.ts
interface TokenUsage {
  input: number;   // prompt tokens
  output: number;  // completion tokens
  cost: number;    // USD cost for this call
}

Per-user cost attribution

Each user record in the users table carries a metadata.costAttributed field that accumulates total spend attributed to that user across all their conversations and agent interactions.

External agent cost estimation

For external agents (execution mode external-procode or external-n8n), the platform cannot directly measure token usage because inference runs outside the platform boundary. Instead, the agent's externalConfig.costModel field specifies a reference model (e.g., gpt-4.1-mini) whose pricing is used to estimate costs based on message sizes.


Model Cost Tiers

The platform classifies every model into one of three cost tiers and one of three hosting types. Both dimensions affect the effective cost to the tenant.

Tier definitions

TierDescriptionTypical use cases
BudgetLowest cost per token; suitable for high-volume, low-complexity tasksClassification, routing, summarization, embeddings
StandardBalanced cost and quality; default for most agentsGeneral chat, code review, document analysis
PremiumHighest quality; reserved for complex reasoning or critical tasksLegal review, advanced reasoning chains, multi-step planning

Model pricing table

Pricing is defined in two places: the models database table (primary source, seeded from AIFS catalog) and a hardcoded fallback in services/api-gateway/src/lib/model-pricing.ts. The calculateCost() function resolves pricing in order: DB lookup, then hardcoded table, then a default fallback of Claude Sonnet 4 rates.

Budget tier

ModelProviderHostingInput ($/1K tokens)Output ($/1K tokens)Notes
Qwen3 30BAlibabaDE-hosted$0.00015$0.0004Cheapest LLM option
Gemini 2.5 FlashGoogleExternal$0.00015$0.0006Fast, multimodal
GPT-5 MiniOpenAIExternal$0.0003$0.0012Latest mini model
GPT-4.1 MiniOpenAIExternal$0.0004$0.0016High-volume workhorse
o3-miniOpenAIExternal$0.00110$0.00440Budget reasoning
Jina Embeddings v2JinaDE-hosted$0.00005$0.00Embedding only

Standard tier

ModelProviderHostingInput ($/1K tokens)Output ($/1K tokens)Notes
Llama 3.3 70BMetaDE-hosted$0.00035$0.0008Full DE sovereignty
Mistral Small 24BMistralDE-hosted$0.0004$0.001DE-hosted, vision
Qwen3 Next 80BAlibabaDE-hosted$0.0005$0.001DE-hosted, reasoning
Qwen3 VL 30BAlibabaDE-hosted$0.0005$0.001DE-hosted, vision
GPT-4oOpenAIExternal$0.0025$0.01General purpose
Claude 3.7 SonnetAnthropicEU-hosted$0.003$0.015Previous-gen Claude
o4-miniOpenAIExternal$0.00110$0.00440Reasoning

Premium tier

ModelProviderHostingInput ($/1K tokens)Output ($/1K tokens)Notes
Gemini 2.5 ProGoogleExternal$0.00125$0.011M context window
GPT-4.1OpenAIExternal$0.002$0.008Strong general-purpose
Claude Sonnet 4AnthropicEU-hosted$0.003$0.015Primary agent model
GPT-5OpenAIExternal$0.005$0.020Latest flagship
o3OpenAIExternal$0.010$0.040Advanced reasoning
Claude Sonnet 4.5AnthropicExternal$0.010$0.050Highest quality

Data sovereignty pricing impact

Hosting type affects both cost and compliance posture:

Hosting TypeInfrastructureData ResidencyCost impact
de-hostedTelekom OTC (Germany)Data never leaves GermanyLowest cost (open-source models)
eu-hostedAWS Frankfurt / partner EUData stays within EU (GDPR)Moderate (proprietary models)
externalProvider infrastructure (US/global)Data may leave EUVaries by provider

Tenants requiring strict data sovereignty can set allowedModelTags: ['de-hosted'] in their model policy, which restricts all agents to Germany-hosted open-source models only. This is both the most cost-effective and most sovereign option.


Budget Controls

The platform enforces cost limits at two levels: per-agent daily caps and per-tenant monthly caps. These are checked before every LLM call by the circuit breaker.

Per-agent daily budget caps

Each agent can have a maxCostPerDay limit set in its config.modelAccess section:

// Agent config — modelAccess section
interface AgentModelAccess {
  allowedModels?: string[];
  allowedModelTags?: string[];
  deniedModels?: string[];
  maxCostPerRequest?: number;  // max USD per single LLM call
  maxCostPerDay?: number;      // max USD per day for this agent
  maxTokensPerRequest?: number;
}

Configured in Agent Studio under the Model tab, or via the API:

# Set a $50/day cap on an agent
PATCH /api/agents/{agentId}
{
  "config": {
    "modelAccess": {
      "maxCostPerDay": 50.00
    }
  }
}

Per-tenant monthly budget limits

Tenant-level budgets are configured in Admin Console under tenant settings:

// Tenant quotas (stored in tenants.quotas JSONB)
interface TenantQuotas {
  maxAgents: number;
  maxTokensPerMonth: number;
  maxCostPerMonth: number;          // e.g., 15000 for $15,000/month
  maxConcurrentExecutions: number;
}

Example from the Acme Corporation tenant seed data:

{
  "maxAgents": 50,
  "maxTokensPerMonth": 10000000,
  "maxCostPerMonth": 15000,
  "maxConcurrentExecutions": 20
}

Circuit breaker mechanism

The circuit breaker (services/api-gateway/src/lib/circuit-breaker.ts) is called before every LLM request. It operates as follows:

  1. Read current spend from Redis counters for the agent (daily) and tenant (daily + monthly).
  2. Check agent daily cap -- if agentCostToday >= maxCostPerDay, the request is denied with a CostBudgetResult.allowed = false.
  3. Check tenant monthly cap -- if tenantCostThisMonth >= maxCostPerMonth, the request is denied.
  4. 80% warning threshold -- when an agent reaches 80% of its daily cap, the system emits a cost-alert event with severity warning via the event bus.
  5. Fail-open -- if Redis is unavailable, the circuit breaker allows the request to proceed (fail-open design to avoid blocking production traffic).
// Simplified flow in the orchestrator
const budgetCheck = await checkCostBudget(tenantId, agentId);
if (!budgetCheck.allowed) {
  return { error: budgetCheck.reason }; // e.g., "Agent daily cost budget exceeded: $50.00 / $50.00"
}

// ... proceed with LLM call ...

// After successful call, record the cost
await recordCost(tenantId, agentId, computedCost);

Cost recording

After each LLM call, recordCost() increments three Redis keys using INCRBYFLOAT:

  • cost:daily:{agentId}:{YYYY-MM-DD} with 48h TTL
  • cost:daily:{tenantId}:{YYYY-MM-DD} with 48h TTL
  • cost:monthly:{tenantId}:{YYYY-MM} with 35-day TTL

Admin reset capability

Admins can reset an agent's daily cost counter via resetAgentDailyCost(agentId), which deletes the Redis key. This is useful after adjusting budgets or resolving false trips.


Cost Monitoring

FinOps Center dashboard

The Admin Console provides a dedicated FinOps Center page (apps/admin/app/(main)/finops/page.tsx) that visualizes:

  • Total Cost MTD -- month-to-date aggregate spend across all agents
  • Daily Average -- totalCostMTD / daysElapsed
  • Cost trend chart -- daily cost time series (area chart)
  • Cost by model -- pie/bar breakdown showing which models consume the most budget
  • Cost by agent -- ranked list of agents by total cost
  • Cost by tenant -- multi-tenant cost allocation
  • Budget utilization -- percentage of tenant monthly budget consumed
  • Agent budget status -- per-agent daily spend vs. configured caps, with circuit breaker trip indicators
  • Optimization recommendations -- suggestions for model downgrades and token savings

FinOpsData type

The API returns the following structure to the frontend:

// packages/types/src/common.ts
interface FinOpsData {
  totalCostMTD: number;
  totalRequestsMTD: number;
  costByModel: Record<string, number>;
  costByTenant: Record<string, number>;
  costByAgent: Record<string, number>;
  dailyCosts: { date: string; cost: number }[];
  budgetUsage?: {
    tenantMonthlyBudget: number;
    tenantMonthlySpend: number;
    utilizationPercent: number;
  };
  agentBudgetStatus?: Array<{
    agentId: string;
    agentName: string;
    dailySpend: number;
    dailyCap: number | null;
    circuitBreakerTripped: boolean;
  }>;
}

Alert configuration for cost spikes

The circuit breaker automatically creates platform alerts when:

  • An agent reaches 80% of its daily cost cap (severity: warning)
  • An agent exceeds its daily cost cap (request denied, agent effectively suspended for the day)
  • A tenant exceeds its monthly budget (all agents under that tenant are blocked)

Behavioral baselines (also in the circuit breaker module) detect anomalous cost patterns by comparing today's costPerCall against a 7-day rolling average. If the deviation exceeds 2 standard deviations, a warning alert is created.


Hierarchical Cost Attribution

For agents that invoke sub-agents (multi-agent orchestration), the platform builds a hierarchical cost tree using services/api-gateway/src/lib/hierarchical-cost.ts. This module provides:

Cost tree structure

interface CostNode {
  agentId: string;
  agentName: string;
  ownCost: number;        // direct LLM cost of this agent
  childrenCost: number;   // sum of all sub-agent costs
  totalCost: number;      // ownCost + childrenCost
  budgetAllocation: number | null;
  budgetRemaining: number | null;
  children: CostNode[];
}

Budget allocation checks

Before a parent agent delegates to a sub-agent, checkBudgetAllocation() verifies:

  1. The parent has sufficient remaining budget to cover the estimated sub-agent cost.
  2. The child agent itself has not exceeded its own budget allocation.

Platform cost summary

getCostSummary() returns a platform-wide view:

  • totalPlatformCost -- sum of all root-level agent trees
  • topCostAgents -- top 5 agents by total cost (including sub-agent costs)
  • hierarchyCosts -- full tree structures for all root-level agents

Optimization Strategies

1. Model tiering -- match model to task complexity

Use the cheapest model that delivers acceptable quality for each agent's task:

Task complexityRecommended tierExample models
Simple classification, routingBudgetQwen3 30B, GPT-4.1 Mini, Gemini 2.5 Flash
Standard chat, Q&A, document analysisStandardLlama 3.3 70B, GPT-4o, Claude 3.7 Sonnet
Complex reasoning, legal review, planningPremiumClaude Sonnet 4, o3, GPT-4.1

A simple routing agent using GPT-4.1 Mini at $0.0004/$0.0016 per 1K tokens is roughly 25x cheaper than Claude Sonnet 4 at $0.003/$0.015.

2. Token limit configuration

Set maxTokens appropriately per agent to avoid runaway generation:

// Agent config → model section
{
  "model": {
    "primary": "claude-sonnet-4",
    "fallback": "gpt-4.1",
    "temperature": 0.7,
    "maxTokens": 1024  // cap output tokens
  }
}

Agents that only need short answers (classification, yes/no, structured data extraction) should use maxTokens: 256 or lower.

3. Use DE-hosted open-source models for cost and sovereignty

DE-hosted models on Telekom OTC are the cheapest option and provide full German data sovereignty:

  • Qwen3 30B: $0.00015 input / $0.0004 output -- 20x cheaper than Claude Sonnet 4
  • Llama 3.3 70B: $0.00035 input / $0.0008 output -- 8.5x cheaper than Claude Sonnet 4
  • Mistral Small 24B: $0.0004 input / $0.001 output -- 7.5x cheaper than Claude Sonnet 4

4. Semantic caching

The platform can cache common query-response pairs in memory (L4) before calling AIFS. Identical or semantically similar prompts return cached results at zero token cost. This is especially effective for FAQ-style agents with repetitive queries.

5. Tool usage review

External tool calls via MCP can involve expensive API calls (e.g., web search, database queries, third-party SaaS). Review the costByAgent breakdown in the FinOps Center to identify agents with high tool-related costs and consider:

  • Caching tool results in short-term memory
  • Reducing tool call frequency via prompt engineering
  • Using cheaper tool alternatives

6. Tenant-level model policies

Admins can restrict which models a tenant's agents may use, preventing accidental use of premium models:

// Tenant model policy (stored in tenants.modelPolicy)
{
  "allowedModels": ["claude-sonnet-4", "gpt-4.1", "gpt-4.1-mini", "Llama-3.3-70B-Instruct"],
  "deniedModels": [],
  "euHostedOnly": false,
  "defaultMaxCostPerRequest": 1.00,
  "defaultMaxCostPerDay": 50.00,
  "preset": "standard"
}

FinOps API Endpoints

GET /api/admin/finops

Returns aggregated FinOps data for the authenticated tenant. Includes budget utilization and per-agent budget status when Redis is available.

Response: FinOpsData object (see type definition above).

Query parameters: None. Tenant is inferred from the authenticated user's JWT.

Example response shape:

{
  "totalCostMTD": 487.32,
  "totalRequestsMTD": 12450,
  "costByModel": {
    "claude-sonnet-4": 312.50,
    "gpt-4.1": 98.20,
    "Llama-3.3-70B-Instruct": 76.62
  },
  "costByTenant": {
    "tenant-1": 487.32
  },
  "costByAgent": {
    "agent-1": 156.80,
    "agent-2": 89.30,
    "agent-3": 45.20
  },
  "dailyCosts": [
    { "date": "2026-02-01", "cost": 14.20 },
    { "date": "2026-02-02", "cost": 16.80 }
  ],
  "budgetUsage": {
    "tenantMonthlyBudget": 15000,
    "tenantMonthlySpend": 487.32,
    "utilizationPercent": 3.25
  },
  "agentBudgetStatus": [
    {
      "agentId": "agent-1",
      "agentName": "Customer Service Bot",
      "dailySpend": 12.50,
      "dailyCap": 50.00,
      "circuitBreakerTripped": false
    }
  ]
}

GET /api/admin/cost-usage

Returns real-time cost usage for a specific agent from Redis counters.

Query parameters:

  • agentId (optional) -- specific agent to query

Response:

{
  "tenantId": "tenant-1",
  "agentId": "agent-1",
  "usage": {
    "agentCostToday": 12.50,
    "tenantCostToday": 45.80,
    "tenantCostThisMonth": 487.32
  }
}

PATCH /api/tenants/{tenantId}/quotas

Update tenant-level budget limits. Requires admin role.

{
  "maxCostPerMonth": 20000,
  "maxTokensPerMonth": 15000000,
  "maxConcurrentExecutions": 30
}

PATCH /api/tenants/{tenantId}/model-policy

Update tenant model access policy including default cost caps.

{
  "allowedModels": ["claude-sonnet-4", "gpt-4.1", "Llama-3.3-70B-Instruct"],
  "defaultMaxCostPerRequest": 2.00,
  "defaultMaxCostPerDay": 100.00,
  "euHostedOnly": true
}

Chargeback and Showback

Per-tenant cost allocation

The getFinOps() function produces a costByTenant map by joining execution records with their agent's tenant_id. Each tenant sees only their own cost data, scoped by the JWT's tenant context.

For platform-wide views (super-admin), the tenant filter can be omitted to see cross-tenant aggregates.

Per-user cost attribution

Each user record tracks cumulative cost in metadata.costAttributed. This allows department-level rollups by grouping users by their IdP groups:

UserDepartmentCost attributed
Alice ConsumerHR$45.20
Dave EngineerEngineering$78.50
Bob BuilderEngineering$156.80
Eve FinanceFinance$32.10

Department-level cost reports

By aggregating costAttributed across users who share an IdP group, platform admins can produce department-level showback reports. The users table includes groups (from IdP sync) which map to organizational units.

Monthly cost report generation

To generate a monthly cost report:

  1. Call GET /api/admin/finops to get the current month's cost breakdown.
  2. The dailyCosts array provides day-by-day trend data.
  3. The costByModel map shows which models drove the most spend.
  4. The costByAgent map identifies the highest-cost agents.
  5. The budgetUsage object shows budget utilization percentage.

These data points can be exported to CSV or fed into enterprise FinOps tooling (e.g., Apptio, CloudHealth) for integration with broader cloud cost management.

API key cost tracking

The api_keys table tracks daily_cost_cap and total_cost per API key. The api_key_usage table provides daily aggregates of token_input, token_output, and cost per key. This allows cost attribution to external consumers who access agents via API keys.


Key source files

FilePurpose
services/api-gateway/src/lib/model-pricing.tsModel pricing lookup and cost calculation
services/api-gateway/src/lib/circuit-breaker.tsBudget enforcement, Redis cost counters, anomaly detection
services/api-gateway/src/lib/hierarchical-cost.tsMulti-agent cost tree and budget allocation
services/api-gateway/src/db/repository.tsgetFinOps() aggregation from executions table
services/api-gateway/src/routes/admin.ts/api/admin/finops and /api/admin/cost-usage endpoints
services/api-gateway/src/db/schema.tsmodels, executions, tenants, agent_workflows, api_key_usage tables
packages/types/src/common.tsFinOpsData TypeScript interface
apps/admin/app/(main)/finops/page.tsxFinOps Center dashboard UI