Introduction
We built Ask DoorDash on a common platform that lets domain teams build and evolve their agents without rebuilding the systems beneath them. We judged the platform by two practical outcomes: how quickly teams could add features and domains, and how quickly they could evaluate and release improvements to cost, quality, and latency.
We launched Ask DoorDash with Restaurant and Grocery support in roughly two months, and it has since handled more than two million conversations. Adding Reservations, our third domain agent, took one week, roughly 10x faster than building the initial domain agents.
Our shared evaluation harness and rollout controls give teams clear quality signals as they move changes into production. Within a week of a new LLM’s release, we evaluated and deployed it, cutting p50 turn latency by 35% with no drop in quality scores. A subsequent model upgrade cut p50 turn latency by another 40%.
This post explains how we chose what belonged in the platform, how its components fit together, and the tradeoffs behind those decisions. It follows our engineering overview, our deep dive on intelligence, and our deep dive on evaluation. A deep dive on user experience will follow.
How we chose what to standardize
We centralized a capability only when multiple domains needed it and separate implementations would create reliability or operational problems. Orchestration, memory, model access, tracing, evaluation infrastructure, and rollout controls met that bar. Domain teams retained ownership of the instructions, skills, tools, evaluation criteria, and model choices that define their agents.
Where a suitable industry standard existed, we adopted it. Agent2Agent (A2A) defined how agents communicate, while Google Agent Development Kit (ADK) provided the framework for building and running them. These standards sometimes limited our design choices, but they gave teams shared contracts and saved us from developing proprietary equivalents.
For recurring problems without a suitable standard, we built the capability ourselves. A regression in shared code could affect several agents, so evaluation and rollout controls were mandatory. Every shared change had to pass common quality checks and release safeguards.
Ask DoorDash architecture
The central architectural decision was what every agent should share and what each domain should own. We built a shared execution path around specialized, domain-owned agents. A single general-purpose agent would grow harder to reason about as it took on more responsibilities, while fully independent agent stacks would duplicate infrastructure and produce inconsistent experiences.
As Figure 1 shows, each request enters through the Gateway. The Gateway authenticates the user, assembles entry-point context, and translates between the client’s HTTP and streaming interfaces and the platform’s A2A protocol. It then passes the request to the Orchestrator, which chooses the domain agent for each turn while preserving continuity as the conversation moves between domains. The selected agent loads the appropriate skills and uses Model Context Protocol (MCP) tools to interact with existing DoorDash services.
Below that request path, the platform provides session state, memory, artifacts, model access, tracing, evaluation infrastructure, and rollout controls. Domain agents use these common services while retaining control of their instructions, skills, tools, and evaluation criteria.

Figure 1: Ask DoorDash separates domain-specific agent behavior from the shared execution and production capabilities used across the system.
A Gateway for responsive, multimodal experiences
DoorDash client gateways were built for APIs that return a complete response quickly. Agents work differently. The first text may be ready while the agent is still calling tools, and the final response may combine prose with interactive store or item cards. We needed to stream that work without teaching every client how agents communicate.
The Gateway handles this translation. It authenticates the user, adds context about where the conversation started, and converts client HTTP requests into A2A requests. On the return path, it uses the Vercel AI SDK to send text updates and widget payloads to clients over Server-Sent Events (SSE). Clients render the updates as they arrive, so users can see progress while the agent completes the turn.
Building and operating the Gateway took work, but it concentrated work that would otherwise be duplicated across every DoorDash client. Agents can change behind one stable client contract without requiring coordinated client releases. A new domain agent reuses the existing authentication and streaming path instead of integrating separately with each app.
One assistant, specialized domain agents
A conversation can cross domains without warning. A user might start with “I want chicken pot pie delivered in under 30 minutes,” then decide, “actually, I want to make it at home.” The first request belongs to the Restaurant domain and the second to the Grocery domain, but the experience needs to feel like one conversation.
We tried a single-agent architecture, but Restaurant, Grocery, and Reservations rely on different tools, policies, and evaluation criteria. Combining them would make the agent harder to test and force every domain onto the same release cycle. Each domain therefore owns a specialized agent. The Orchestrator reads the conversation and routes each turn to the appropriate agent over A2A.
That routing adds latency and input tokens, even when the conversation remains in the same domain. To reduce this cost, the Orchestrator pins follow-up turns to the selected domain agent. Pinning lets that agent handle subsequent requests directly, without another routing step. If the conversation changes direction, the domain agent recognizes the out-of-scope message and returns control to the Orchestrator. The Orchestrator reroutes the request within the same turn, hidden from the user.

Figure 2: Pinning avoids an Orchestrator call on follow-up turns while still allowing the conversation to move between domains.
Skills keep context and cost bounded
Specialized agents kept Restaurant, Grocery, and Reservations from sharing one enormous context window. As each agent gained capabilities, however, the same context problem appeared within individual domains. New features added instructions and tools to every turn, even when the turn never used them. That increased input-token cost, and overlapping or conflicting instructions confused the agent.
We added skill support to our harness to modularize instructions and tools. On each turn, the agent loads only what is relevant. A user might begin with, “find me a highly rated Thai restaurant that delivers in under 30 minutes,” then say, “show me the menu at the first one and add pad see ew to my cart.” Both requests stay with the Restaurant agent, but the first loads the search-discovery skill. The second loads the cart-ordering skill, which handles menu browsing and cart actions.
Dynamic loading adds a selection problem. The selector must recognize when a capability is needed without loading unrelated context too often, so we evaluate skill selection as part of the agent’s behavior. The added complexity was worthwhile because teams could add capabilities without expanding the context of every turn.
To measure the effect, we counted the tokens in the agent’s base and loaded skill instructions. We excluded conversation history, consumer messages, tool schemas, and tool results. The median skill-scoped turn used fewer than half as many instruction tokens as the monolithic system prompt.
| Agent | Base and skill instructions with all skills loaded | Median skill-scoped instructions per turn | Reduction |
| Restaurant | ~42,000 tokens | ~20,000 tokens | 50%+ |
| Grocery | ~25,000 tokens | ~10,000 tokens | 60% |
Safe, reusable service access through MCP
Ask DoorDash needs access to DoorDash services to search for stores and items, read menus, manage carts, and act on a user’s behalf. The APIs behind these operations assume deterministic application code. An LLM choosing operations at runtime needs a narrower interface. Exposing the APIs directly would force the model to interpret low-level interfaces. Encoding permissions and business rules only in the prompt would add context without guaranteeing enforcement.
We built a shared Model Context Protocol (MCP) layer between the agents and DoorDash APIs. Each MCP tool exposes a focused operation with the inputs and outputs the model needs. The model chooses which tool to call. Deterministic code validates each request and enforces permissions and business rules before the call reaches the underlying service.
Prompts help the model choose the right operation, but that guidance is advisory. Validation and enforcement run in tool code on every call, creating a stable safety boundary as prompts and models change.
Tool design requires balance. A tool that is too broad can present the model with too many choices, while one that is too narrow can turn a task into a long chain of calls. Our shared MCP server now provides more than 60 tools across public and internal agent workflows. A new agent selects the tools it needs from that library, and improvements to validation, telemetry, or service integration benefit every agent that uses them.

Figure 3: Prompts influence what the model requests; MCP tool code determines what can execute.
Production readiness by default
ADK gave us the basic pieces for building an agent, including instructions, tools, callbacks, sessions, and model wiring. DoorDash agents also needed distributed tracing, model access, durable state, and rollout controls. Without a shared layer, each domain team would have to make those decisions and operate the resulting infrastructure independently.
We built reusable modules on top of ADK for capabilities that should work the same way across agents. Domain teams still choose their instructions, tools, and model configuration. The platform connects those choices to the systems required to run agents reliably in production.
Tracing is one example. A team enables it through configuration, and the shared SDK propagates a trace ID through A2A calls, MCP tools, and downstream DoorDash services. Engineers can follow one request across the Orchestrator, domain agents, and tool calls instead of piecing together logs from separate systems. The same trace data supports debugging and evaluation. Providing tracing through the platform saves roughly a month of observability work for each new agent launch.
Model access follows the same principle. Domain teams choose which models their agents use, while the platform standardizes how those models are invoked, traced, and protected by fallback behavior. Teams can evaluate and adopt new models without rewriting provider-specific integrations. That common path enabled the rapid model upgrades and latency improvements described earlier.
Shared state for reliable conversations
Earlier attempts at DoorDash agent products in 2025 showed how quickly the experience breaks down when state is unreliable. An agent could respond well to one request, then forget or misuse information from an earlier turn. Solving that problem required more than adding conversation history to the prompt.
Ask DoorDash uses three forms of state. Session state tracks the active conversation and work already completed within it. Memory preserves information that may be useful in later conversations, such as a user’s preferences. Artifacts hold structured outputs that agents create and update, including shopping lists and interactive cards. Each has a different lifetime and access pattern.
Earlier DoorDash agent projects implemented these capabilities independently. That duplicated persistence work and made reliability depend on each team’s choices. We centralized them in Managed Agent Services, which provides ADK-compatible APIs for sessions, memory, and artifacts. Domain agents use the same interfaces without operating their own stateful systems.
Centralizing state still requires separate storage and lifecycle rules for session data, long-term memory, and artifacts. Managed Agent Services keeps those boundaries in one place. Each domain still decides what information its experience should save and retrieve.
Managed Agent Services and the memory architecture are covered in more detail in Part Two.
Stay Informed with Weekly Updates
Subscribe to our Engineering blog to get regular updates on all the coolest projects our team is working on
Please enter a valid email address.
Thank you for Subscribing!
What the platform changed
Reservations was a concrete test of the platform. The team reused the production path already serving Restaurant and Grocery and launched Reservations support in one week, roughly 10x faster than building the initial domain agents.
Domain teams keep ownership of agent behavior and quality criteria. The platform provides the evaluation harness, MCP tools, tracing, model access, and rollout controls, so improvements to those components reach every agent that uses them.
Shared infrastructure increases the blast radius of mistakes. A defect can affect several agents, and a premature abstraction can force different products into the same shape. We standardize a capability only after multiple domains need it and separate implementations would create reliability or operational problems.
Join Us
If building agent platforms and user-facing AI at scale sounds interesting, see our open engineering roles at careersatdoordash.com.
