Running a Software Factory Efficiently at Uber Scale
Distinguished Engineer
Introduction
AI tools are now embedded in every phase of software development at Uber. More than 70% of pull requests are attributed to local or cloud agents. Engineers have built over 3,600 agent skills across the software development life cycle, and executed more than 30K agent skill executions per day.
At the AI Engineer 2026 conference, we shared our vision for the Software Factory and the building blocks and managed agents we are building across the lifecycle. As we progress on that vision, a growing share of sessions aren’t initiated by humans, but by automated managed agents handling code review, self-healing CI failures, completing E2E PRs with visual validation, triaging on-call alerts, debugging incoming bugs, and handling a variety of code maintenance tasks with human reviews/escalations.
As shown in Figure 1, from February to Aug 2026, weekly active users across all agentic offerings across all our employees (engineers & non-engineers) grew 7x, and weekly agentic requests grew 9.4x. Meanwhile, our total AI spend has relatively stabilized since April due to optimizations across the board.
Figure 1: Weekly active users, agent requests, and cost from Feb–Mid Aug 2026, with users deduplicated across tools.
Figure 2: Cost optimization impact with model held constant. *Cost/session data starts from end of May.
All pricing and vendor metrics in this comparison are based on publicly available information, with cost efficiency gains driven by routing our internal Uber workloads more intelligently within standard tier-pricing. While specific cost reductions we measure are unique to our environment and your mileage may vary depending on your codebase, team size, and agent workflows, the methodology of benchmarking real work and optimizing for accuracy and cost is universally applicable.
The Software Factory and Its Cost Equation
Four Layers of Agent Usage
We organize AI usage into four layers, from the most specialized to the most general. As shown in Figure 3, the higher the layer, the more control we have over cost, quality, and model selection.

Figure 3: The four layers where agent sessions run.
The Cost Equation
Figure 3: The four layers where agent sessions run.
Across any of the layers above, we can decompose the cost of an agentic session into the following terms, which we could measure and optimize independently.
Figure 4: Total spend, decomposed into six terms that multiply.
How We Measure
Below is the full set of metrics we track weekly and monthly that enable us to forecast & plan our efforts short-term and long-term.
Layer | Metrics | What it answers |
Portfolio |
| Where the money is going, and which tool moved |
Unit economics, per tool |
| Whether the tool is getting cheaper or usage is just shifting |
Model economics | For every model
| Which model releases actually changed the bill, at identical or different per-token prices |
Driver decomposition | Cost change decomposed sequentially into
| Why the number moved, stated exactly, with nothing left in an unexplained residual |
Managed agent outcomes | For each managed agent:
| Whether each managed agent is getting cheaper per unit of value delivered, and whether quality holds through model migrations |
Optimization Levers
In the following sections, we detail the key levers we used to optimize each part of the cost equation. Some of these levers affect one or more rows in the cost equation.
Price / Token | Benchmark-driven, Pareto-optimal model selection Model defaults |
Tokens / Request | 400K context cap & Medium reasoning effort by default Prompt Caching Tool search and CLI-resolved MCP calls Code-mode batching of tool calls Gateway-routed SaaS MCPs |
Requests / Turn | Graph-grounded context Continuous Skill Optimization |
Visibility & Education | Live cost counter in the status line Visibility and spend tiers Session analysis dashboard |
Optimizing Price / Token
The vendor sets the token price. We pick which model runs which workload. Across all our managed agents’ layers, we pick the model that’s most Pareto efficient for that workload. For us, Pareto efficient means cost/completed task, output quality, and model reliability.
Benchmark-Driven Model Selection
Model selection happens in four steps, the same for every managed agent we run.
- Build a benchmark out of the agent’s real work.
- Run the agent on a harness that serves any model, frontier or open-weight, behind one interface.
- Move to whatever is Pareto optimal, and keep moving. The frontier shifts every few weeks.
Looking ahead, we continually refine our workload performance by leveraging aggregated insights from our managed agents to test and deploy various model routing strategies.
For example, we use uReview, which handles AI code review for all pull requests. We built its benchmark from real pull requests with known bugs and graded them easy, medium, and hard. We score precision, recall, and F1 against those bugs, plus cost per review, latency, timeouts, and noise. As shown in Figure 5, switching models improved our F1 while dramatically reducing cost/PR. In the figure, the dashed line is the Pareto frontier. Everything below and left of it is beaten by something cheaper or better.
Figure 5: Every configuration we tested for uReview.
Default Model Selection
In the interactive interface, token unit costs remain fixed; however, you can strategically manage token distribution across models. Two default settings primarily govern this distribution: the initial session model and the subagent model.
The subagent default setting has proven to be the most impactful lever, and its significance continues to grow. The proportion of sessions initiating subagents has steadily increased as the latest model capabilities enable more effective multi-agent orchestration. Because subagents perform well-defined tasks with specified inputs that often do not require frontier-level reasoning, we default them to a weaker, more cost-effective model while still allowing manual overrides. The primary model handles task decomposition and evaluation while subagents execute the work.
Optimizing Tokens / Request
Every turn re-sends the full conversation history, project context, and tool results. Anything that reduces the per-request payload compounds across the session.
Defaults
All interactive harnesses use a unified wrapper for installation management, configuration, authentication, and cost visibility. Two standardized default configurations directly reduce token consumption per request:
- Automatic compaction is triggered at 400k tokens even for 1M context window models: This threshold balances model performance against cache bursts and repeated input token costs. Our measurements show a meaningful reduction in fleet-wide input tokens per request.
- Reasoning effort defaulted to Medium: Output tokens, including internal reasoning tokens, are billed at multiples of the rate of input tokens on primary models; this policy adjustment directly reduces spend in the highest-cost token category. For a large category of tasks, Medium reasoning hits a good balance between cost vs quality.
Prompt Caching Strategy
Our prompt caching strategy is driven by the economics of provider prompt cache reads and writes. Since each turn re-transmits the full conversation history, caching the preceding context avoids paying the full cost repeatedly, reducing subsequent reads to just 0.1x the standard input token rate. However, write premiums vary: 5-minute cache entries cost 1.25x, while 1-hour entries cost 2x. Choosing an optimal TTL (Time-to-Live) therefore depends on the duration of gaps between turns. Available TTL options include 5 minutes and 1 hour from Anthropic®, alongside 30 minutes from OpenAI®.
Figure 6: A comparison of 5 turns under both TTL durations.
Executing MCP Tools via the Shell
At Uber, all MCP (Model Context Protocol) interactions are routed through a unified gateway. This single entry point encompasses more than 1,000 MCP servers across internal and third-party SaaS MCP, enabling centralized authentication and policy enforcement.
However, standard MCP loads all tool schemas directly into every session, regardless of whether an engineer will ever invoke them in that session or not. For example, with over 100 tools installed, this pre-loading added approximately 50K-70K tokens of schema overhead to the initial prompt, which was subsequently re-sent on every context turn.
Figure 7: What an agent is already carrying at the start of a session, under 3 ways of reaching the same tools.
- CLI tool resolution: Replaces direct MCP integration by allowing the model to execute a shell command. The CLI resolves and invokes the required tool against the gateway dynamically at call time, eliminating Uber MCP schemas from the session context. All 1K+ MCP tools from our internal MCP gateway are projected as CLI commands.
- Tool search: Scales to thousands of tools by allowing the model to search the tool catalog and load only required tools on demand. This approach mitigates context bloat, typically reducing token usage for tool definitions, and maintains high selection accuracy even as the available tool library expands, preventing degradation associated with large tool sets.
Code-Mode
When tools call functions directly as shell commands, models can batch multiple actions within a single script. This batching is particularly advantageous for chatty tool protocols. Under standard MCP workflows, each action requires a separate model turn to emit a request, load the raw response into the context window, and process the results sequentially. For instance, executing a single SQL query requires submitting the request, polling status 2 to 5 times, and retrieving the output. Code-mode streamlines this entire flow into an automated Python loop, keeping intermediate polling out of the model’s active context. As shown in Figure 8 on the left, the model participates in the polling loop, and every response lands in its context. On the right, the loop runs in a subprocess, and only the summary comes back.
Figure 8: The same warehouse query, both ways.
Query | LLM tool-use | Code-mode | Savings |
SELECT 1 (1 row) | 903 | 402 | 55% |
COUNT(*) (1 row) | 954 | 403 | 58% |
GROUP BY LIMIT 20 (20 rows) | 1,600 | 457 | 71% |
SHOW COLUMNS (175 rows) | 2,200 | 900 | 59% |
SELECT * wide table (50 rows) | 1,431,594 | 900 | ~100% |
Tokens per query, measured in the same Claude Code session. |
The initial three rows highlight the main finding: even for minimal result sets far below response-size limits, code-mode reduces token usage by more than 50%. Rather than bypassing large data payloads, these efficiencies stem from eliminating unnecessary overhead, including schema initialization, multi-turn polling, and redundant step-by-step reasoning.
Bulk workflows compound the effect, because the loop that would have been N model turns becomes one script and the savings compound to more than 90%. By deploying more than 25 pre-built code-mode skills for our most-accessed MCP servers, we ensure standard workflows default to the most cost-effective path.
SaaS MCPs
Managing third-party software proved significantly more challenging than our internal servers. Vendors design MCP servers to expose full product capabilities because they can't anticipate specific customer usage. For instance, a workspace suite bundles 49 tools into a single server, requiring ~22K tokens of schema, while messaging and project tracking vendors ship 34 and 46 tools, respectively. Loading two or three vendor servers makes the agent carry more schema overhead than the file being edited before a user even enters a prompt.
To address this, we route SaaS MCP servers through our MCP gateway using the same mechanism we do for our internal MCPs. We also expose all these MCPs as CLIs that any agentic surface can invoke. Additionally, we author dedicated skills within our code-mode plugin for each server to encapsulate common workflows. This unlocked efficient agentic workflows across many SaaS vendors.

Figure 9: Every SaaS MCP server is exposed behind our MCP gateway to ensure a unified, efficient access pattern.
Optimizing Requests / Turn
Figure 9: Every SaaS MCP server is exposed behind our MCP gateway to ensure a unified, efficient access pattern.
An ungrounded agent fails slowly rather than cheaply, repeatedly sending an expanding context window to search one more location. Providing richer information upfront remains the single most powerful lever to reduce this search overhead.
Context Engineering
Across Uber’s vast codebase and data ecosystem, comprising hundreds of millions of code lines and thousands of tables, agents spend most of their turns locating information rather than generating code. To address this, we engineered the AI Context Graph: a unified network containing 24 million nodes and 80 million edges across 86 nodes and 117 edge types. It integrates data from over 30 internal systems, including services, engineering teams, incident logs, pull requests, architectural design docs, deployments, datasets, and historical table usage queries, and lets any agent query it in natural language.
Figure 10: Comparing execution paths for the identical prompt submitted to the same model, with and without graph grounding.
Visibility & Education
The levers here are visibility and feedback loops that help engineers and agents converge faster.
The Status Line
We put a live cost counter in the harness status line that tracks live spend per harness and across all harnesses for each user.

Figure 11: The status line, with the session analyzer and efficiency guide that ship alongside it.
Visibility and Spend Tiers
Figure 11: The status line, with the session analyzer and efficiency guide that ship alongside it.
To avoid imposing strict caps, we implemented real-time spend tracking and automated nudges:
- Statusline live counter. Running session cost is always visible in the terminal.
- Harness pool. One shared tier across all interactive harnesses, not per-tool budgets. And separate tiers for managed agents.
- Slack nudges. Alerts at 50/80/100% of expected spend so engineers have time to plan.
- Easy approval flows. Manager sign-off for tier upgrades with quick propagation.
- Cost check skill and tips. A dashboard skill for on-demand cost breakdown and live status line coaching.
These enable engineers to evaluate task ROI independently while mitigating runaway expenses.
Session Analysis Dashboard
While the status line highlights a session's total expenditure, it lacks visibility into cost drivers or actionable efficiency steps. General guidance provides high-level principles, but can’t evaluate individual developer workflows. The session analysis dashboard bridges this gap by inspecting session artifacts directly.
Built directly into the runtime, it requires zero setup or opt-in. Executing the cost dashboard skill analyzes all session traces for the user across local and remote cloud sandboxes across all harnesses they use. Rather than producing an aggregate metric, it flags 16 distinct anti-patterns across sessions, pairing each with its financial impact and a targeted remediation. Some of the categories include:
- Suboptimal model routing: Executing simple multi-turn sessions on Opus that Sonnet could easily fulfill.
- Context window bloat: Large MCP payloads (for example, 40KB responses) persisting in context and incurring repeated billing on subsequent turns.
- Cache expiration inefficiencies: Resuming sessions after extended breaks where expired prompt caches force full-price prefix rebuilds.
- Prompt initialization overhead: Pre-loading 100,000 tokens of system instructions and tool definitions before any user input is provided.

Figure 12: Session-level cost dashboard identifies waste patterns and potential savings..
What’s Next?
Figure 12: Session-level cost dashboard identifies waste patterns and potential savings..
Current initiatives in progress include:
- Growing the fleet of managed agents: For every new agent, we follow a consistent roadmap: establish target outcome metrics, assemble evaluation benchmarks, and identify a Pareto-optimal model. This systematic approach aims to elevate each stage of the SDLC higher up the factory maturity model.
- Dynamic Model Routing: We’re expanding benchmark coverage across diverse programming languages, code repositories, and agent modalities. Effective model routing relies heavily on comprehensive evaluation, given that model capabilities vary widely.
- Deepening context-graph integration: We’re unlocking graph query capabilities across a wider selection of autonomous agents.
- Evolving session analytics into real-time developer guidance: By shifting from periodic batch detection of anti-patterns to continuous trace monitoring, we aim to deliver personalized, real-time efficiency recommendations directly to engineers.
- Continuous Skill Improvement: We are working on an automated way to record papercuts from agent skill executions and auto-generate skill updates from the collected traces.
Conclusion
Managing and curbing rising AI coding expenses is also a tractable engineering challenge. By eliminating wasted, zero-value token consumption rather than relying solely on lower unit prices or downgrading tooling, we scaled usage 7x while simultaneously reducing unit costs across all metrics and improving/maintaining output quality.
The core strategic shift is moving from interactive developer workflows to fully managed agents. Transitioning SDLC workloads into managed environments grants complete control over model routing, execution harnesses, and operational spend. Optimizing a fleet of specialized managed agents, each paired with dedicated evaluation benchmarks and a Pareto-efficient model, is inherently more cost-effective and scalable than optimizing individual terminal sessions across thousands of engineers.
Acknowledgments
This is a collective effort by many engineers who are building the most efficient blocks to implement Software Factory at Uber scale, while ensuring we get ROI for every token we spend. We would like to thank our core team involved in various efforts across Software Factory listed here: Abhishek Bhatia, Adam Huda, Aditya Patel, Alok Srivastava, Ameya Ketkar, Anil Purohit, Atakan Kandemir, Ben Chou, Brandon Barker, Danielle Yim, Deepanshu Mehndiratta, Gaurav Gill, Israel Marban, Jason Varbedian, Karen Xu, Lei Shi, Mager Mager, Meghana Somasundara, Peng Liu, Preet Inder, Qiushen Wang, Rush Tehrani, Shesh Patel, Shiven Tripathi, Shubham Gupta, Stas Khalup, Ting Chen, Tse-Shi Wang, Ty Smith, Vikram Hullukunte, Weiqiang Wang, Will Bond.
Also would like to thank Johannes Gehrke, Mattie Toia, Sumanth Sukumar, and Praveen Neppalli Naga for their leadership.
Cover Photo Attribution: Himer Romana
Anthropic® is a registered trademark of Anthropic PBC.
Claude Code™ and Claude® are trademarks of Anthropic, PBC.
OpenAI® and its logos are registered trademarks of OpenAI®.
Uday Kiran Medisetty
Distinguished Engineer
Uday Kiran Medisetty is a Distinguished Engineer at Uber, where he leads initiatives for engineering productivity (agentic coding, AI debugging, code reviews, and large-scale refactoring). He also co-leads the company-wide engineering community shaping Uber's architecture, culture, and standards.
Products
Company