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
-
Per-execution recording -- When an LLM call completes, the API gateway captures
usage.prompt_tokensandusage.completion_tokensfrom the AIFS response. These are stored in theexecutionstable as atoken_usageJSONB column with the structure{ input, output, cost }. -
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)
-
Execution-level aggregation -- The
getFinOps()repository function queries all executions within the current month and aggregates costs intocostByModel,costByAgent,costByTenant, anddailyCostsbreakdowns. This powers the FinOps Center dashboard in the Admin Console. -
Workflow-level totals -- The
agent_workflowstable trackstotal_input_tokens,total_output_tokens, andtotal_costacross 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
| Tier | Description | Typical use cases |
|---|---|---|
| Budget | Lowest cost per token; suitable for high-volume, low-complexity tasks | Classification, routing, summarization, embeddings |
| Standard | Balanced cost and quality; default for most agents | General chat, code review, document analysis |
| Premium | Highest quality; reserved for complex reasoning or critical tasks | Legal 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
| Model | Provider | Hosting | Input ($/1K tokens) | Output ($/1K tokens) | Notes |
|---|---|---|---|---|---|
| Qwen3 30B | Alibaba | DE-hosted | $0.00015 | $0.0004 | Cheapest LLM option |
| Gemini 2.5 Flash | External | $0.00015 | $0.0006 | Fast, multimodal | |
| GPT-5 Mini | OpenAI | External | $0.0003 | $0.0012 | Latest mini model |
| GPT-4.1 Mini | OpenAI | External | $0.0004 | $0.0016 | High-volume workhorse |
| o3-mini | OpenAI | External | $0.00110 | $0.00440 | Budget reasoning |
| Jina Embeddings v2 | Jina | DE-hosted | $0.00005 | $0.00 | Embedding only |
Standard tier
| Model | Provider | Hosting | Input ($/1K tokens) | Output ($/1K tokens) | Notes |
|---|---|---|---|---|---|
| Llama 3.3 70B | Meta | DE-hosted | $0.00035 | $0.0008 | Full DE sovereignty |
| Mistral Small 24B | Mistral | DE-hosted | $0.0004 | $0.001 | DE-hosted, vision |
| Qwen3 Next 80B | Alibaba | DE-hosted | $0.0005 | $0.001 | DE-hosted, reasoning |
| Qwen3 VL 30B | Alibaba | DE-hosted | $0.0005 | $0.001 | DE-hosted, vision |
| GPT-4o | OpenAI | External | $0.0025 | $0.01 | General purpose |
| Claude 3.7 Sonnet | Anthropic | EU-hosted | $0.003 | $0.015 | Previous-gen Claude |
| o4-mini | OpenAI | External | $0.00110 | $0.00440 | Reasoning |
Premium tier
| Model | Provider | Hosting | Input ($/1K tokens) | Output ($/1K tokens) | Notes |
|---|---|---|---|---|---|
| Gemini 2.5 Pro | External | $0.00125 | $0.01 | 1M context window | |
| GPT-4.1 | OpenAI | External | $0.002 | $0.008 | Strong general-purpose |
| Claude Sonnet 4 | Anthropic | EU-hosted | $0.003 | $0.015 | Primary agent model |
| GPT-5 | OpenAI | External | $0.005 | $0.020 | Latest flagship |
| o3 | OpenAI | External | $0.010 | $0.040 | Advanced reasoning |
| Claude Sonnet 4.5 | Anthropic | External | $0.010 | $0.050 | Highest quality |
Data sovereignty pricing impact
Hosting type affects both cost and compliance posture:
| Hosting Type | Infrastructure | Data Residency | Cost impact |
|---|---|---|---|
| de-hosted | Telekom OTC (Germany) | Data never leaves Germany | Lowest cost (open-source models) |
| eu-hosted | AWS Frankfurt / partner EU | Data stays within EU (GDPR) | Moderate (proprietary models) |
| external | Provider infrastructure (US/global) | Data may leave EU | Varies 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:
- Read current spend from Redis counters for the agent (daily) and tenant (daily + monthly).
- Check agent daily cap -- if
agentCostToday >= maxCostPerDay, the request is denied with aCostBudgetResult.allowed = false. - Check tenant monthly cap -- if
tenantCostThisMonth >= maxCostPerMonth, the request is denied. - 80% warning threshold -- when an agent reaches 80% of its daily cap, the system emits a
cost-alertevent with severitywarningvia the event bus. - 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 TTLcost:daily:{tenantId}:{YYYY-MM-DD}with 48h TTLcost: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:
- The parent has sufficient remaining budget to cover the estimated sub-agent cost.
- 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 treestopCostAgents-- 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 complexity | Recommended tier | Example models |
|---|---|---|
| Simple classification, routing | Budget | Qwen3 30B, GPT-4.1 Mini, Gemini 2.5 Flash |
| Standard chat, Q&A, document analysis | Standard | Llama 3.3 70B, GPT-4o, Claude 3.7 Sonnet |
| Complex reasoning, legal review, planning | Premium | Claude 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:
| User | Department | Cost attributed |
|---|---|---|
| Alice Consumer | HR | $45.20 |
| Dave Engineer | Engineering | $78.50 |
| Bob Builder | Engineering | $156.80 |
| Eve Finance | Finance | $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:
- Call
GET /api/admin/finopsto get the current month's cost breakdown. - The
dailyCostsarray provides day-by-day trend data. - The
costByModelmap shows which models drove the most spend. - The
costByAgentmap identifies the highest-cost agents. - The
budgetUsageobject 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
| File | Purpose |
|---|---|
services/api-gateway/src/lib/model-pricing.ts | Model pricing lookup and cost calculation |
services/api-gateway/src/lib/circuit-breaker.ts | Budget enforcement, Redis cost counters, anomaly detection |
services/api-gateway/src/lib/hierarchical-cost.ts | Multi-agent cost tree and budget allocation |
services/api-gateway/src/db/repository.ts | getFinOps() 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.ts | models, executions, tenants, agent_workflows, api_key_usage tables |
packages/types/src/common.ts | FinOpsData TypeScript interface |
apps/admin/app/(main)/finops/page.tsx | FinOps Center dashboard UI |