From February to mid-August 2026, Uber's Agent weekly request volume grew 9.4x and weekly active users grew 7x—yet overall AI spending has remained relatively stable since April. The key lies in Uber's item-by-item optimization of model selection, context, MCP tool calls, execution paths, and cost feedback, rather than any single model price cut. It's more like a continuously running cost engineering system.
On August 27, 2026, Uber Engineering published Running a Software Factory Efficiently at Uber Scale, detailing this cost control approach.
This retrospective has a somewhat uncomfortable backdrop. Axios reported that Uber's CTO revealed in April that the company had already exhausted its planned 2026 AI budget ahead of schedule. By August, Uber's published data showed:
- Weekly active users of Agent products grew 7x compared to February;
- Weekly Agent request volume grew 9.4x;
- Overall AI spending has remained relatively stable since April;
- Cost per 1,000 requests dropped nearly 34% from peak when comparing the same model;
- Cost per session dropped 52% from the June peak.
During the same period, Uber had accumulated over 3,600 Agent Skills internally, executing more than 30,000 Skills daily, with over 70% of Pull Requests attributed to local or cloud Agents.
This "attributed to Agent" doesn't mean 70% of code entered production without human involvement. Uber's description of Managed Agent still includes human review and exception escalation. This metric is closer to "Agents participated in these changes" rather than "Agents independently own these changes."
Breaking Down Agent Costs First
Uber describes total Agent spending using six multiplicative variables:
Total Spending
= Users
× Sessions per User
× Turns per Session
× Model Requests per Turn
× Tokens per Request
× Price per Token
This formula gets closer to the true cost of Agents than looking at token price alone.
Regular conversations typically have one input turn corresponding to one model call. Agents, however, also plan tasks, search code, spawn sub-agents, call tools, poll for task status, handle failures, and carry existing context in subsequent requests. The user issues one task, but the backend may have already executed many turns.
Uber wants the first two variables to keep growing because they represent adoption and usage depth. Optimization focuses on the extra turns, requests, and context that Agents generate to complete tasks, and the model pricing used for each type of task.
| Cost Variable | Common Amplification Factors | Uber's Control Methods |
|---|---|---|
| Turns per Session | Wrong search paths, failure retries | Context Graph, Skills, Managed Agent |
| Model Requests per Turn | Polling, chat-style tool calls | Code Mode, script batching |
| Tokens per Request | Full history, tool schemas, raw results | Compression, caching, Tool Search, CLI |
| Price per Token | Using the same tier model for all tasks | Benchmark-driven model selection |
These variables multiply together, so a few small changes in the execution chain can noticeably impact total costs.
From Cost per Token to Cost per Outcome
Uber's metrics are organized into four layers.
| Layer | Primary Metrics |
|---|---|
| Overall Portfolio | Total cost, user count, cost share per tool or Agent |
| Individual Tools | Cost per user, cost per 1,000 requests, cost per session, cost per active hour, cache hit rate |
| Model | Request share, cost share, cost per 1,000 requests, cost per million tokens |
| Managed Agent | Cost per merged PR, review, alert, or cleanup task, plus Revert Rate, F1, MTTR |
Uber also breaks down cost changes into user growth, usage frequency, input tokens, and output tokens—avoiding a blanket "everyone's using it more" explanation.
When evaluating model cost-effectiveness, successful outcomes work better than tokens as the denominator. A cheap model that fails frequently and triggers retries may not be cheaper per completed task; a pricier model that reliably completes high-risk work may offer better value.
Therefore, Uber evaluates models based on task completion cost, output quality, and reliability—not just comparing public price lists.
Choosing Models with Real-Task Benchmarks
Uber uses the same model selection process for Managed Agents:
- Build a Benchmark from the Agent's real work;
- Run the same set of tasks across different models using a unified Harness;
- Compare quality, reliability, and cost per completed task;
- Select configurations on the Pareto Frontier and retest continuously.
The code review Agent uReview's evaluation set comes from real PRs with known defects, categorized by difficulty. Metrics include Precision, Recall, F1, cost per review, latency, timeout rate, and noise. Uber reports that after switching models, F1 improved while per-PR review costs dropped significantly.
Among interactive Agents, the sub-agent's default model is one of the configurations with the greatest cost impact. The main Agent is responsible for understanding goals, breaking down tasks, and verifying results, while sub-agents typically handle work with clear inputs and narrower scope. Uber therefore defaults sub-agents to weaker, lower-cost models while keeping manual override options.
An important distinction: Uber is already doing workload-based model selection, but finer-grained dynamic model routing is listed as future work. It's not a system described in the article.
Large Context Doesn't Mean Filling the Window
Every Agent request carries conversation history, project context, and tool results. The larger the context, the higher the recurring cost for each subsequent turn.
Uber sets two default values for the interactive Harness:
- Even if the model supports 1 million tokens, auto-compression triggers at 400,000 tokens;
- Default uses Medium Reasoning Effort, raised only when needed.
These defaults create a buffer for sessions. 1 million tokens represents the upper limit, not the normal working range.
For my own Agent Runtime, I'd at least monitor session turns, context size, tool calls, sub-agent count, retries, execution time, and cost per task. After triggering thresholds, the decision becomes whether to compress, downgrade, pause, or escalate to humans—aborting just converts wasted tokens into failed tasks.
Prompt Cache TTL Should Follow Session Rhythm
Agents repeatedly send system prompts, project descriptions, conversation history, and tool definitions. Prompt Cache can reduce costs for repeated prefix reads, but cache writes have a premium—TTL shouldn't just use default values.
Uber observed that engineers often leave the terminal for more than 5 minutes, and when they return, the cache has already expired and the full prefix needs rebuilding. So interactive sessions adjusted from 5-minute TTL to 1 hour; short-lived sub-agents still keep 5 minutes.
Uber's original text also listed the vendor's cache price differences at that time: cache hit reads are about 0.1x standard input pricing, 5-minute writes are about 1.25x, and 1-hour writes are about 2x. These numbers vary by vendor—what's reusable is the decision-making method: first look at the distribution of intervals between adjacent turns, then decide on TTL.
Long human-computer interaction sessions typically benefit from longer cache, while short tasks and batch processing may not justify the higher long-term write costs.
MCP Costs Don't Only Happen During Tool Execution
Uber's unified MCP Gateway connects to over 1,000 internal and third-party MCP Servers, handling authentication and policy centrally.
Their initial problem was that direct integration paths preloaded large numbers of tool schemas into sessions. Uber measured that installing 100+ tools added approximately 50K to 70K tokens to the initial prompt; these definitions were also repeatedly sent in subsequent turns as context grew, even though most tools were never invoked.
Uber later adopted two paths:
- CLI dynamic parsing: Model calls a unified CLI, which finds and invokes tools through the Gateway during execution—MCP schemas don't permanently stay in the model context;
- Tool Search: First search the tool directory, loading only definitions needed for the current task.
What's important here is separating "capability availability" from "schema residence." MCP continues handling connections and invocations; the Harness, CLI, or Gateway decides which tools the model needs to see at any moment.
This also resonates with the progressive loading approach in Skills Over MCP: the model first sees small metadata, then loads full descriptions and resources after task matching.
Moving Deterministic Loops Out of Model Context
Submitting queries, getting task IDs, polling for status, downloading results, and filtering data—these steps don't require the model to re-think each time. If each step takes a model turn, polling responses keep entering context, and subsequent requests repeatedly carry them.
Uber uses Code Mode, where the model generates scripts and subprocesses handle polling, batching, and result trimming—only summaries return to the model.
Uber tested traditional tool calls versus Code Mode for five identical SQL queries:
| Query | Regular Tool Call | Code Mode | Savings |
|---|---|---|---|
SELECT 1, 1 row | 903 tokens | 402 tokens | 55% |
COUNT(*), 1 row | 954 tokens | 403 tokens | 58% |
GROUP BY LIMIT 20 | 1,600 tokens | 457 tokens | 71% |
SHOW COLUMNS, 175 rows | 2,200 tokens | 900 tokens | 59% |
| Wide table query, 50 rows | 1,431,594 tokens | 900 tokens | ~100% |
Even the first few queries with small results saved over 50%. This shows benefits come not just from transmitting fewer large results, but also from removing schema initialization, multi-turn polling, and repeated step reasoning. In batch workflows, Uber measured savings exceeding 90%.
The boundary isn't complex: pagination, polling, retry, format conversion, and aggregation suit regular code; understanding goals, judging exceptions, and evaluating results still belong to the model.
Good Context Also Reduces Costs
In large codebases, Agents spend significant time finding information rather than generating code. Questions like who owns a service, where a data table is used, or how incidents were handled before—if there's no reliable entry point, Agents search more files, spawn more sub-agents, and repeatedly send increasingly large contexts.
Uber's AI Context Graph contains approximately 24 million nodes and 80 million edges, integrating data from over 30 internal systems including services, teams, incidents, PRs, architecture documents, deployments, and datasets.
Uber tested the same question with the same model:
- With Context Graph: correct answer in 38 seconds;
- Without Graph: ran for 20 minutes, spawned two sub-agents, encountered three errors, and finally gave a wrong conclusion.
Regular teams don't need to start from a knowledge graph with tens of millions of nodes. Organizing repository indexes, service dependencies, code owners, data table callers, Runbooks, architecture decisions, and verification commands into Agent-queryable entry points can already reduce substantial ineffective searching.
Bringing Costs to Engineers' Attention
Uber placed real-time cost counters in the terminal status bar, showing cumulative costs for the current Harness and all user Harnesses, with alerts at 50%, 80%, and 100% of expected costs. Interactive Harnesses share one cost tier; Managed Agents use a separate tier; increasing limits requires manager approval, but approval and config propagation remain lightweight.
Monthly bills only tell teams how much they spent—they can't explain where costs occurred. Uber's Session Analysis Dashboard directly analyzes local and remote session traces, identifying 16 categories of cost anti-patterns with cost impact and remediation suggestions, such as:
- Simple tasks using overpowered models;
- Large data returned by MCP staying in context long-term;
- Prompt Cache expiring during session recovery;
- Preloading excessive system instructions and tool definitions before user input.
This way, cost governance enters the daily development workflow instead of only appearing in financial reports.
Managed Agents Make Unit Cost Calculation Easier
At article's end, Uber lists migrating more software development tasks to Managed Agents as the future direction.
Open-ended terminal sessions are flexible, but platforms struggle to control task input, context size, model selection, execution turns, and verification methods. Managed Agents can pre-define goals, tools, models, completion criteria, quality metrics, and human escalation paths—making it easier to calculate cost per successful outcome.
Uber maintains a set of dedicated Agents with independent Benchmarks and model strategies, rather than one Agent handling all tasks. For platform teams, optimizing these stable workflows is more controllable than correcting thousands of engineers' terminal usage habits one by one.
If scaling this approach down to an ordinary team, I'd implement it in this order:
- First record traces: task type, model, input/output tokens, cache, tool calls, retries, latency, cost, and results;
- Then add budget guardrails: limit turns, context, concurrency, retries, time, and cost per task;
- Next govern execution paths: context compression, on-demand tool loading, result summarization, and script batching;
- Finally, use real-task Benchmarks for model selection, and track cost and quality per successful task.
Order matters. Without traces, it's hard to know what to optimize; without outcome metrics, model routing easily degrades into simple price comparison.
The Value of This Approach
Uber's data comes from its own codebase, team size, and vendor mix—it can't be directly taken as savings commitments for other companies. Its more valuable contribution is breaking Agent costs from a single API bill into measurable runtime problems.
Users and tasks can keep growing—what needs reduction is erroneous searching, redundant context, idle tool schemas, model-involved polling, ineffective retries, and model calls mismatched to task difficulty.
When each cost can be traced back to a specific session, and each session back to a specific outcome, cost governance gains actionable leverage. Model capability is just one condition for Agent scaling—the Runtime must also be able to explain why a task cost what it did.