Building Production-Scale AI Agent Evaluation Systems for Customer Care

lyft · Tech · 2024 · source Agentic: yes · promotional bias: low · source-backed · extracted with prompt 0.5.5 (schema v2)

Generated from extraction.json — do not edit by hand. Every claim cites verbatim source evidence; stated means the quote directly asserts the claim, implied means it supports it indirectly.

Problem

Domain: Customer-care AI agent evaluation at production scale

Lyft needed to scale multiple AI Assist customer-care agents without using riders or drivers as test data, while ensuring offline evals actually predicted production behavior across high-stakes support workflows.

Constraints:

Architecture

Lyft built an evaluation-first operating model around AI Assist. Production agents run on a LangChain/LangGraph/LangSmith/MCP stack, but the core system-design contribution is the offline and online evaluation loop: a Tau-Bench-inspired simulator pairs the real LangGraph agent with an LLM user, drives permutations from YAML configs for intents, scenarios, personas, and mocked state, evaluates trajectories with task-specific LLM judges and code assertions, captures traces in LangSmith, routes failed traces to annotation queues, and feeds human-labeled failure analysis back into prompts, tools, graph control flow, harness design, and eventually custom model training.

Diagram confidence: reconstructed (reconstructed from prose).

flowchart LR
  rider-or-driver[Rider or driver] --> ai-assist-agent[AI Assist agent]
  ai-assist-agent --> langgraph-workflow[LangGraph workflow]
  langgraph-workflow --> mcp-tools[MCP tools]
  langgraph-workflow --> production-monitoring[Production monitoring]
  offline-simulator[Offline simulator] --> langgraph-workflow
  offline-simulator --> llm-user[LLM user]
  yaml-scenario-config[YAML scenario config] --> offline-simulator
  yaml-scenario-config --> mocked-mcp-outputs[Mocked MCP outputs]
  mocked-mcp-outputs --> offline-simulator
  offline-simulator --> evaluator-suite[Evaluator suite]
  evaluator-suite --> llm-judge[LLM judge]
  evaluator-suite --> code-assertions[Code assertions]
  evaluator-suite --> langsmith[LangSmith]
  production-monitoring --> langsmith
  langsmith --> annotation-queue[Annotation queue]
  annotation-queue --> operations-team[Operations team]
  annotation-queue --> engineers[Engineers]
  operations-team --> human-labeled-ground-truth[Human-labeled ground truth]
  human-labeled-ground-truth --> llm-judge
  engineers --> ai-assist-agent
  engineers --> eval-harness[Eval harness]
  eval-harness --> offline-simulator
Drag to pan · scroll or use +/− to zoom · reconstructed from the source's described component topology

Components

Component Role Interacts with
Rider or driver Customer or driver seeking help through AI Assist. AI Assist agent
AI Assist agent Production customer-care agent handling support workflows such as disputes, damage claims, compliance, taxes, and refund explanations. Rider or driver, LangGraph workflow, MCP tools, Production monitoring
LangGraph workflow Agent workflow implementation used for AI Assist and reused inside the offline simulator. AI Assist agent, Offline simulator, MCP tools, Production monitoring
MCP tools External data and service integrations used by the agent in production, mocked during offline evaluation. LangGraph workflow, Mocked MCP outputs
Offline simulator Lightweight Tau-Bench-inspired simulation environment for generating end-to-end agent/user trajectories before launch. LangGraph workflow, LLM user, YAML scenario config, Mocked MCP outputs, Evaluator suite
LLM user Role-playing model that simulates customer behavior during offline evaluation. Offline simulator, LangGraph workflow
YAML scenario config Configuration specifying user intents, support scenarios, personas, and mocked state of the world. Offline simulator, Mocked MCP outputs
Mocked MCP outputs Predefined offline responses returned when the simulated agent calls external tools. Offline simulator, MCP tools
Evaluator suite Combination of task-specific LLM judges and code assertions that score simulated or production trajectories. Offline simulator, LLM judge, Code assertions, LangSmith
LLM judge Rubric-based evaluator aligned to specific agent tasks and success/failure criteria. Evaluator suite, Human-labeled ground truth
Code assertions Python checks over end-state conditions used to determine success or failure for some trajectories. Evaluator suite
LangSmith Tracing, evaluator, automation, and annotation workflow layer for offline and production evaluations. Evaluator suite, Production monitoring, Annotation queue
Production monitoring Online evaluation and trace collection for agents after launch. AI Assist agent, LangSmith, Annotation queue
Annotation queue Human-review queue for traces that fail judge criteria. LangSmith, Operations team, Engineers
Operations team Human annotators who label failed traces and provide ground truth. Annotation queue, Human-labeled ground truth
Engineers Team that analyzes systematic failures and improves prompts, tools, control flow, and harness design. Annotation queue, AI Assist agent, Eval harness
Human-labeled ground truth Domain-expert labels used to calibrate LLM judges against human agreement. Operations team, LLM judge
Eval harness Planned more formal infrastructure for managing offline evaluation runs beyond lightweight scripts. Offline simulator, Engineers

Data flow

Before launch, a YAML configuration defines support scenarios, user intents, personas, and mocked world state. The offline simulator pairs the actual LangGraph agent with an LLM user, returns mocked MCP outputs for tool calls, and produces full interaction trajectories. Task-specific LLM judges and code assertions evaluate those trajectories. In production, LangSmith traces and online evals capture real interactions; failed traces go to annotation queues; operations and engineering teams label and analyze failures; and the lessons feed back into prompts, tool definitions, graph logic, harness design, and future custom model training.

5 supporting quotes
“a public benchmark that all the other LLM models and AI labs are using as a benchmark. So for this offline evaluation pipeline, we built a lightweight simulator. On the right here, we have our LangGraph agent, which is the AI agent that we built for AI Assist. And then we have an LLM”transcript, stated
“built a lightweight simulator. On the right here, we have our LangGraph agent, which is the AI agent that we built for AI Assist. And then we have an LLM user — we just use one of the out-of-the-box LLM models to role- play as a user so that we can generate this end-to-end trajectory of an”transcript, stated
“end-to-end trajectory of an interaction, right? And then we use a very config-driven approach. We have a YAML file that specifies what the user intents are, what the support scenarios are that we're looking at, and how we mock the state of the world. Because in offline, you're”transcript, stated
“we sort of just mock the MCP output with one of the values that's in the config file. So we get this long chain of trajectory on the permutations — our config is permutations of different combinations of different things, right? The state of the world, the”transcript, stated
“for traces that fail your LLM judge criteria, we can set up an automation that sends the failed traces to an annotation queue.”transcript, stated

Why this architecture

Lyft treats agent evaluation like traditional ML engineering: offline evaluation is a launch quality gate, not an afterthought. The simulator prevents production users from becoming test data, the task-specific rubric judges turn failures into actionable product insight, LangSmith connects offline and online traces to human annotation, and custom user simulation is planned because polite generic LLM users made the first benchmark too easy.

4 supporting quotes
“my approach to thinking about AI eval for AI agents is no different than traditional ML evaluations. So for those of you who come from a data science background or ML engineering background — you're working in the notebook. You develop this model. You train”transcript, stated
“the offline eval really serves as a quality gate. You don't want to use your users as test data. But maybe if you're a start- up with five customers, maybe that's okay. But at the scale of Lyft, we really don't want to use our customers as test data. And”transcript, stated
“That becomes product insight to help your tech team, your engineering team, to improve your AI agent. Tweak a prompt, tweak a tool, change your control flow logic, or whatnot, and then you run the loop again and see if it improved. So this is just another”transcript, stated
“see user verbatim in production is like one or two words, right? People are very impatient. People don't sit down and nicely explain their issues. So when we did this, our first AI agent was giving us a 90% pass rate. Nice. We can launch, right? But it was a rude awakening”transcript, stated

Models used: Claude · OpenAI models · LLM-as-judge models · Custom fine-tuned LLM user · LLMs used by AI Assist

Scale

Alternatives considered (roads not taken)

Ship agents without offline evaluation

Rejected because: At Lyft's scale, using customers as test data is unacceptable.

“helps to scale AI agents in production. So maybe just a quick show of how many of you here ship agents without eval. I'm literally guilty of that, so don't be embarrassed. I know it's one of those things that we always forget about, but really shouldn't. Hopefully,”transcript, stated
“start- up with five customers, maybe that's okay. But at the scale of Lyft, we really don't want to use our customers as test data. And once we got the agent into production, we have continuous monitoring. We have our online eval, getting all the LangSmith traces, human in the loop — all that”transcript, stated

Generic helpfulness or tone LLM-judge scores

Rejected because: Scalar generic scores were not actionable for improving agent behavior.

“We were defining things like tone appropriateness, response helpfulness, naturalness, and all that. And these have been scored on a scale of zero to one — a scalar metric. So what's the problem with this, right? For response helpfulness, for example, what”transcript, stated
“scalar metric. So what's the problem with this, right? For response helpfulness, for example, what does a 0.4 score mean compared to 0.7? What does that mean? How can you move the needle, right? And if you want to move your overall score, what product insight is this giving you?”transcript, stated

Make live MCP/network calls during offline evaluation

Rejected because: The offline environment should use controlled mocked outputs rather than live source-system calls.

“what the support scenarios are that we're looking at, and how we mock the state of the world. Because in offline, you're not making network calls to other MCP servers. So in an offline setting, we're mocking those MCP outputs. And imagine if an agent calls a tool offline — we sort of just”transcript, stated
“in offline, you're not making network calls to other MCP servers. So in an offline setting, we're mocking those MCP outputs. And imagine if an agent calls a tool offline — we sort of just mock the MCP output with one of the values that's in the”transcript, stated

Use off-the-shelf LLMs as nice, cooperative simulated users

Rejected because: They made the eval too easy by explaining issues more clearly than real support users.

“Claude or OpenAI model to role-play as a user. But often what we see is — as you can see here — the LLMs are being a nice, helpful assistant. They explain their issues very nicely to our AI agent. But I'm guilty of this as well. I don't typically do this when I”transcript, stated
“don't typically do this when I reach out to support. More often than not, what we see user verbatim in production is like one or two words, right? People are very impatient. People don't sit down and nicely explain their issues. So when we did this, our first AI agent was giving us a 90% pass rate.”transcript, stated

Optimize only for support deflection

Rejected because: Lyft held the system to true end-to-end issue resolution rather than simply blocking access to support.

“We want the agents to solve the customer issue fully end to end, and not just block the customer from reaching support.”transcript, stated

Patterns

eval-driven-development (evaluation)

Lyft uses offline simulation as a quality gate before launch and uses production traces to drive continuous agent improvements.

“Think about this as a quality gate. Can we launch? So I really want to emphasize the offline eval piece. If that has been the way that we do ML engineering for the last couple of years, why should AI engineering be any different, right?”transcript, stated
“once we got the agent into production, we have continuous monitoring.”transcript, stated

llm-as-judge (evaluation)

The evaluation suite uses task-specific LLM judges with rubrics instead of generic helpfulness scores.

“So for the trajectory, we also define evaluators. We use LLM-as-judge. I think everyone is doing that. Code assertion — we run some very simple Python scripts that check the end state of the world to see if certain conditions are met to define success or failure.”transcript, stated
“it should be framed around the task that you want your AI agent to perform”transcript, stated

human-in-the-loop-gate (quality-control)

Failed judge traces are sent to human annotation queues where operations teams label examples and engineers analyze systematic failures.

“have automations in LangSmith. So for traces that fail your LLM judge criteria, we can set up an automation that sends the failed traces to an annotation queue. And here we have our operations team set up on this annotation queue to help us manually label these examples, and our engineers go in and”transcript, stated
“our operations team set up on this annotation queue to help us manually label these examples”transcript, stated

observability-tracing (operations)

LangSmith captures offline and production trajectories, evaluator results, automation, and annotation workflows.

“with offline simulation and our online runs in production, we're using LangSmith to help us capture these nice trajectories.”transcript, stated
“Tracing, evaluator setup, automation, annotation queue. If you're here, you're probably familiar with LangSmith.”transcript, stated

synthetic-data-generation (evaluation)

The simulator creates synthetic end-to-end user/agent trajectories from configured intents, personas, and state permutations.

“we just use one of the out-of-the-box LLM models to role- play as a user so that we can generate this end-to-end trajectory”transcript, stated
“our config is permutations of different combinations of different things, right? The state of the world, the user intent, user persona.”transcript, stated

data-quality-loop (evaluation)

Human-labeled traces and judge alignment feed back into prompt, tool, control-flow, and model-training improvements.

“collect some human-labeled ground truth from your domain experts about how to score a certain interaction based on a rubric.”transcript, stated
“And here we have our operations team set up on this annotation queue to help us manually label these examples, and our engineers go in and analyze what the systematic failure modes are, and that feeds back into how we improve our AI agents. All right, so what's next for AI Assist, right?”transcript, stated

Tradeoffs

Make offline evaluation a launch gate

Chose Simulator-based offline evaluation before production launch over Learning from live customer failures.

Rationale: At Lyft's scale, the team did not want real customers to be the test set.

“And the offline eval really serves as a quality gate. You don't want to use your users as test data. But maybe if you're a start- up with five customers, maybe that's okay.”transcript, stated
“at the scale of Lyft, we really don't want to use our customers as test data.”transcript, stated

Use task-specific judges

Chose Rubric judges for concrete support tasks over Generic helpfulness, tone, and conciseness scores.

Rationale: Task-specific rubrics create actionable failure modes; generic scalar scores did not tell product teams what to improve.

“hopefully no one's using a generic helpfulness score for an agent in production.”transcript, stated
“The way that we think about LLM Judge is that it should be framed around the task”transcript, stated

Mock MCP outputs in offline evaluation

Chose Configuration-defined mock world state and tool outputs over Calling live MCP servers during offline eval runs.

Rationale: Offline evaluation needs controlled, repeatable scenarios with state permutations rather than live service dependencies.

“Because in offline, you're not making network calls to other MCP servers. So in an offline setting, we're mocking those MCP outputs.”transcript, stated
“we sort of just mock the MCP output with one of the values that's in the config file.”transcript, stated

Make simulated users harder

Chose Fine-tuned or persona-grounded LLM users based on real verbatims over Out-of-the-box helpful assistant role-play.

Rationale: A harder benchmark may reduce offline scores, but it better predicts production because real users are terse and impatient.

“Technically making our eval a little bit harder — your benchmark score might go down.”transcript, stated
“But you really want this to be a good proxy for production, right? Otherwise, what's the point of this? The other thing that we are looking to work on with our UX team is defining clear user personas, right?”transcript, stated

Improve the harness before training custom weights

Chose Prompts, tools, graph, system prompt, RAG pipeline, and eval harness improvements first over Immediately updating LLM weights for AI Assist.

Rationale: The team had been using traces for product and harness improvement and identified model training as a next active area rather than the initial lever.

“Managing the harness around the model — which is basically everything around the model”transcript, stated
“we haven't really done much on model training — updating the weights of the LLM and training a custom LLM for AI Assist.”transcript, stated

Gotchas (what bit them)

A high offline pass rate can be fake confidence if simulated users are too cooperative.

Root cause: Off-the-shelf LLM users explained their issues clearly, unlike real users who often send only one or two words.

Resolution: Train or condition LLM users on real Lyft user verbatims and explicit personas, even if the harder benchmark lowers scores.

3 supporting quotes
“when we did this, our first AI agent was giving us a 90% pass rate.”transcript, stated
“People don't sit down and nicely explain their issues. So when we did this, our first AI agent was giving us a 90% pass rate.”transcript, stated
“We are actively looking into fine-tuning a custom LLM that's aligned with our Lyft”transcript, stated

Generic LLM-judge metrics do not tell teams what to fix.

Root cause: Scalar helpfulness, tone, or naturalness scores lack a task-specific failure interpretation.

Resolution: Write rubrics around agent tasks and success/failure criteria so failed traces reveal common failure modes.

3 supporting quotes
“what does a 0.4 score mean compared to 0.7? What does that mean?”transcript, stated
“So your AI agent is being instructed to do tasks A, B, and C, and each of those tasks has its own success and failure criteria. So a very simple example that I pulled from our LangSmith platform is this educational rubric.”transcript, stated
“when you see interactions that fail your rubric, you can very quickly know what some of the common failure modes are”transcript, stated

Offline evaluation is only useful if it approximates production behavior.

Root cause: A simulator can generate diverse trajectories, but if the data distribution is unrealistic it will not predict launch quality.

Resolution: Use state/user/persona permutations and production verbatim data to make offline data a better proxy.

“You want your offline eval to be a good proxy for how your agent is going to perform when you actually turn it on.”transcript, stated
“you should be training your LLM user using real-world verbatim data”transcript, stated

LLM judges themselves need evaluation.

Root cause: A judge prompt can drift away from domain-expert expectations even when it appears to score conversations.

Resolution: Treat the LLM judge like an ML model: collect human labels, tune prompts/reasoning, and measure human agreement.

3 supporting quotes
“how do we trust this LLM-as-judge, right? We define a rubric, we define some prompts, but how do we know it's doing the right thing?”transcript, stated
“So my own personal take is that, well, you just train an LLM judge like a machine learning model. You collect some human-labeled ground truth from your domain experts about how to score a certain interaction based on a rubric.”transcript, stated
“And you go through this traditional ML engineering loop — change your prompt, change your reasoning — see if it aligns with your human agreement score, and then if it does, you have an LLM judge that's aligned with human judgment.”transcript, stated

Complex agents cannot be shipped safely by deflection metrics alone.

Root cause: A chatbot can block support without actually resolving the customer's issue.

Resolution: Define success as full end-to-end resolution and use eval gates to protect that standard.

“We want the agents to solve the customer issue fully end to end, and not just block the customer from reaching support.”transcript, stated
“35% might seem a little bit low, but we really hold ourselves to a very high bar.”transcript, stated

Evaluation

Lyft evaluates AI Assist with a layered system: offline simulation acts as a pre-launch gate, LLM judges and code assertions evaluate generated trajectories, human-labeled domain-expert data calibrates judges, and production LangSmith traces plus human annotation drive online monitoring and iteration.

Metrics: Offline pass rate · Human agreement score for LLM judges · Task-specific rubric pass/fail · Code assertion success/failure · Deflection rate · AI resolution rate · Production LangSmith trace failures · Human annotation labels

4 supporting quotes
“You have some kind of ground truth for regression or classification tasks. And then you run this offline evaluation and see what the performance is.”transcript, stated
“Code assertion — we run some very simple Python scripts that check the end state of the world”transcript, stated
“And you go through this traditional ML engineering loop — change your prompt, change your reasoning — see if it aligns with your human agreement score, and then if it does, you have an LLM judge that's aligned with human judgment.”transcript, stated
“getting all the LangSmith traces, human in the loop — all that good stuff that's giving us feedback”transcript, stated

Outcomes

The source is highly quantified: 79 million trips per month, 270,000 AI interactions per month, seven-plus production agents, 65% deflection, 35% resolution, resolution growth from 10% to 35%, 15-minute damage-claim decisions, 80-plus refund rules, and an initial 90% offline pass rate that failed to transfer.

5 supporting quotes
“our AI Assist chat today has served about 270,000 AI interactions per month.”transcript, stated
“We've been able to build seven AI agents and more in production. Our deflection rate is 65%, and AI resolution rate is at 35%.”transcript, stated
“Our deflection rate is 65%, and AI resolution rate is at 35%. 35% might seem a little bit low, but we really hold ourselves to a very high bar.”transcript, stated
“our resolution rate has really gone up from 10% to 35% and climbing.”transcript, stated
“we wouldn't have been able to ship so many AI agents, or test and make sure that such complex AI agents actually perform in production, without a great eval system.”transcript, stated