LangSmith blueprint · AI software engineering
Evals in CI with pytest and Vitest
LLM test files in pytest (@pytest.mark.langsmith) or Vitest (langsmith/vitest) run on every pull request. Each run syncs to LangSmith as an experiment on a dataset built from the tests, the build fails on regressions, and reviewers inspect results in the UI. The gate must never pass a real quality regression, and it must never block merges on judge noise or flaky model calls.
- Steps
- 8
- Subjective questions
- 33
- Objective questions
- 33
The problem and the outcome
Problem: Prompt, model and tool changes silently break LLM features because ordinary unit tests cannot judge free-text output. Ad hoc eval notebooks are run inconsistently and leave no comparable history.
Outcome: Every pull request produces a named LangSmith experiment with per-example inputs, outputs, feedback and traces. Merges are blocked when assertions or score thresholds fail, and regressions can be diffed against the previous run in the comparison view.
Architecture
How it works, step by step
- A push or pull request starts a CI job. The job has LANGSMITH_API_KEY set as a secret, LANGSMITH_TEST_SUITE set to a stable suite name, and optionally LANGSMITH_TEST_CACHE pointing at a cached directory so unchanged LLM calls are replayed instead of re-billed.
- CI runs pytest on Python test functions decorated with @pytest.mark.langsmith, or runs Vitest on files that use ls.describe / ls.test from langsmith/vitest with the LangSmith reporter. Each test case is one example, and its inputs and reference outputs come from the test parameters.
- Each test calls the real chain, LangGraph agent or wrapped client, for example with wrap_openai or @traceable. The full trace is recorded under that test case, and prompts are pulled from the Prompt Hub by tag so the version under test is explicit.
- Assertions check hard rules such as schema validity, required tool calls and forbidden content. Softer qualities are scored with LLM-as-judge or agentevals trajectory evaluators and recorded with t.log_feedback in pytest or ls.logFeedback in Vitest.
- The integration upserts the suite as a LangSmith dataset, using t.log_inputs, t.log_outputs and t.log_reference_outputs or the Vitest equivalents. It records this run as a new experiment containing per-example outputs, feedback and traces.
- Failed assertions, including explicit checks such as assert score >= threshold, make the test runner exit non-zero. CI then marks the check red and branch protection blocks the merge.
- Reviewers open the experiment link and use the comparison view to diff against the main-branch baseline experiment. They examine which examples regressed, what the feedback scores are, and the trace of each failing case.
- Ambiguous or disputed cases go to an annotation queue for human review against a rubric. Confirmed new failure modes are exported back to the dataset or added as new test cases so the suite grows over time.
Tech stack
- LangSmith SDK (Python) with pytest plugin: @pytest.mark.langsmith and langsmith.testing
- LangSmith SDK (JS/TS) with langsmith/vitest and langsmith/vitest/reporter
- GitHub Actions (or any CI) with branch protection
- LangSmith datasets, experiments and comparison view
- LLM-as-judge evaluators and agentevals trajectory evaluators
- LangSmith Prompt Hub with commit tags
- Annotation queues for human review
Key design decisions
- Split the suite into deterministic assertions, which block merges, and judge scores, which block only below a calibrated threshold or on a drop versus the baseline. This keeps judge noise from causing random red builds.
- Run a small, fast, cached smoke suite on every pull request and the full suite with repetitions nightly or before release. This balances cost, latency and statistical confidence.
- Pin the suite name with LANGSMITH_TEST_SUITE so every run lands in the same dataset. Experiments are then directly comparable across branches and commits.
- Reference prompts by Prompt Hub tag rather than inline strings. A prompt change then becomes a reviewable commit, and the experiment records which version was tested.
- Keep test cases in code as the source of truth for CI. Use production traces and annotation queues to propose new cases, which are added through normal code review.
Common mistakes
- Gating on a single sample of a non-deterministic LLM call causes flaky failures. Use repetitions, temperature control or averaged scores for soft checks.
- A stale LANGSMITH_TEST_CACHE can hide a real regression after the prompt or model changes. Key the CI cache so it is invalidated when prompts, models or dependencies change.
- Letting an uncalibrated LLM judge decide merges is unreliable. Check judge agreement against human labels in an annotation queue before trusting its threshold.
- Forked-PR builds without LangSmith secrets either fail confusingly or skip syncing. Handle the missing key explicitly, for example with LANGSMITH_TEST_TRACKING=false, and still run the deterministic assertions.
- Tests that silently overwrite reference outputs make the dataset drift. Change references only through reviewed commits.
What to measure
- Per-PR pass rate on deterministic assertions and the number of examples that regressed versus the baseline experiment
- Mean and distribution of each feedback key, such as correctness or trajectory score, per experiment
- CI eval wall-clock time and LLM spend per run, including cache hit rate
- Flake rate: tests that fail and then pass on rerun with no code change
- Escaped regressions: production issues later reproduced by a case added to the suite
Most-asked interview questions
Subjective questions 33
1How would you stop LLM non-determinism from making your CI eval gate flaky?Asked almost every time
I separate hard and soft checks. Hard checks are deterministic, things like a valid JSON schema, the correct tool being called, or no PII in the output, and they fail the build immediately. Soft checks come from LLM-as-judge scores. I never gate a soft check on one sample. I run repetitions or use low temperature, average the scores, and fail only below a threshold I calibrated against human labels, or on a meaningful drop versus the main-branch baseline experiment. In pull requests, the cache replays unchanged calls, so only the parts that changed are re-evaluated. I also track a flake rate. Any test that flips without a code change gets quarantined and fixed rather than retried until it goes green.
Sourced from Docs by LangChain (MCP)
2Walk me through the end-to-end architecture of an LLM eval gate in CI built on LangSmith's pytest and Vitest integrations.Asked almost every time
A pull request triggers a CI job that holds LANGSMITH_API_KEY as a secret, a stable LANGSMITH_TEST_SUITE name, and optionally a LANGSMITH_TEST_CACHE directory. The runner executes pytest tests marked @pytest.mark.langsmith, or Vitest files that use ls.describe and ls.test with the LangSmith reporter. Each test case becomes one dataset example. The test calls the real chain or agent, traced with wrap_openai or @traceable, using prompts pulled from the Prompt Hub by tag. Hard rules are asserted. Softer qualities are scored by judges and logged as feedback. The integration upserts the dataset and records the run as a new experiment. Any failed assertion makes the runner exit non-zero, the check turns red, and branch protection blocks the merge. Reviewers compare the experiment against the main-branch baseline, and disputed cases go to annotation queues.
Sourced from Docs by LangChain (MCP)
3How do test files map onto LangSmith's data model of datasets, examples, experiments and feedback?Asked almost every time
The test suite maps to a dataset, and the dataset is named by LANGSMITH_TEST_SUITE. Each test case, including each parametrized case, becomes an example. Its inputs and reference outputs come from the test parameters, logged with t.log_inputs and t.log_reference_outputs in pytest or the Vitest equivalents. Every CI run creates a new experiment over that dataset. The experiment holds a run per example with the actual outputs from t.log_outputs, the full trace of the chain or agent, and feedback entries from t.log_feedback or ls.logFeedback. Because the dataset stays the same and experiments accumulate, any two runs can be compared example by example. That comparison is what makes regression review possible.
Sourced from Docs by LangChain (MCP)
4How do you decide which checks are hard assertions and which are logged as feedback scores?Asked almost every time
Anything that is objectively right or wrong and cheap to check deterministically becomes a hard assertion. Examples are output that parses against the schema, a required tool call that was made, no forbidden content, and no leaked system prompt. These should never be flaky, so they block on the first failure. Qualities that need judgment, such as helpfulness, faithfulness to context or tone, are scored by an LLM-as-judge or an agentevals trajectory evaluator and logged with t.log_feedback or ls.logFeedback. Logging alone does not fail a test. Soft scores only block when I add an explicit threshold assertion, and I add one only after measuring the judge's variance, so noise does not turn into red builds.
Sourced from Docs by LangChain (MCP)
5How would you choose thresholds for judge scores so the gate catches real regressions but not noise?Asked almost every time
I start from data. I run the current main branch several times with repetitions and look at how much each example's judge score varies. I set the threshold below that observed band rather than at the mean. For noisy examples I gate on the mean or majority across repetitions instead of a single sample. Where per-example scores are inherently noisy, I gate on an aggregate compared with the baseline experiment, because a small drop across many examples is a real signal. I also validate the judge against a human-labelled sample from an annotation queue. Thresholds are versioned in code, so changing one is a reviewed decision. I revisit them whenever the judge model or the judge prompt changes.
Sourced from Docs by LangChain (MCP)
6How do you stop transient failures such as rate limits, timeouts or provider errors from blocking merges?Asked almost every time
I separate infrastructure errors from quality failures. Model and judge calls get bounded retries with backoff for retryable errors like rate limits and timeouts. If a call still fails, the test should surface it as an infrastructure error and not as a failed quality assertion, for example through a distinct error type or marker that CI can report separately. I cap concurrency to stay under provider rate limits. The cache removes calls for unchanged cases. For an outage, the team needs an explicit policy: rerun the job, or allow a documented override. The gate should never silently pass, because passing on missing results is how real regressions slip through.
Sourced from Docs by LangChain (MCP)
7Why use the pytest or Vitest integration instead of calling evaluate() directly from a script?Very often asked
The integration fits evals into the workflow engineers already use. Tests live next to the code, run with the normal test command, use ordinary assertions and fixtures, and produce a standard exit code that CI and branch protection understand. Each test file is still synced to LangSmith, where the suite becomes a dataset and each run becomes an experiment with outputs, feedback and traces, so nothing is lost for review. I reach for evaluate() when I want dataset-first workflows: large curated datasets, backtesting against production traces, or pairwise experiment comparison driven from a notebook. Many teams use both. evaluate() covers broad benchmarking, and the test integrations cover fast, code-reviewed regression gates.
Sourced from Docs by LangChain (MCP)
8When the build fails on an eval, what is your debugging workflow?Very often asked
I start from the experiment link in the CI log and open the comparison view against the last green main-branch experiment. That shows which examples regressed and which feedback keys dropped. For each failing example, I open the trace to see whether the problem is in retrieval, a tool call, the prompt, or the model's final answer. If the judge's verdict looks wrong, I send the case to an annotation queue so a human can confirm it. A real regression gets fixed, and a newly discovered failure mode becomes a permanent test case. A miscalibrated judge gets new few-shot examples or a rubric fix instead of a code change.
Sourced from Docs by LangChain (MCP)
9Why does LANGSMITH_TEST_SUITE need to be a stable name across runs?Very often asked
The suite name determines which dataset the run upserts into. If the name changes per branch or per run, every CI job creates a new, separate dataset. Experiments would then never share examples, and the comparison view against the main-branch baseline would have nothing to line up. A stable name keeps one dataset per logical suite, so each pull request's experiment sits next to main's experiments on the same examples. Use one stable name per suite, for example per service or per agent. Do not encode branch names in it. Branch and commit context belongs in the CI log and the experiment link, not in the dataset identity.
Sourced from Docs by LangChain (MCP)
10How do you establish and maintain the main-branch baseline that pull requests are compared against?Very often asked
The same suite runs on every push to main, with the same stable suite name. That produces a stream of baseline experiments on the same dataset. Reviewers compare a pull request's experiment with the most recent main experiment in the comparison view. For the baseline to be fair, the main run must use the same prompt tags, model, judge configuration and dataset version as the pull request, apart from the change under test. If the PR adds or edits test cases, those examples have no baseline, and reviewers judge them on their own merits. I also run main periodically without the cache, so the baseline reflects live model behaviour and not only replayed responses.
Sourced from Docs by LangChain (MCP)
11Why pull prompts from the Prompt Hub by tag in CI instead of hardcoding them or always taking the latest commit?Very often asked
Prompts in the Prompt Hub are versioned with commits and tags. Pulling by tag makes the version under test explicit and reproducible. If CI took the latest commit, someone editing a prompt in the Playground could change what main's baseline measures without any code change, and a PR's regression could actually be someone else's prompt edit. Pulling by tag also makes promotion a reviewable step. A prompt change is tested by pointing the PR at a new commit or a candidate tag, and the eval decides whether that tag should move. The trace records which prompt was used, so reviewers can tie a regression to a specific prompt version.
Sourced from Docs by LangChain (MCP)
12How would you estimate and control the cost of running evals on every pull request?Very often asked
I estimate model calls as examples × repetitions × (application calls per example + judge calls per example). For illustration, 200 examples, 2 repetitions, one app call and two judge calls give 200 × 2 × 3 = 1,200 calls per uncached run. Multiply that by PRs and pushes per day. Then I cut it down. LANGSMITH_TEST_CACHE replays unchanged calls instead of re-billing them. A small blocking smoke suite runs on every PR, and the full suite runs on merge to main or nightly. Path filters skip evals when only unrelated code changed. Repetitions are reserved for the examples that actually vary. Judges use cheaper models where agreement with human labels is acceptable.
Sourced from Docs by LangChain (MCP)
13How do you handle pull requests from forks, where CI secrets are not available?Very often asked
On GitHub Actions, workflows triggered by pull requests from forks do not receive repository secrets, so LANGSMITH_API_KEY and the model keys are missing. Exposing them to untrusted code would be a credential leak, because a malicious PR could exfiltrate them. A safe pattern is to require a maintainer to approve or label the PR, after which a trusted workflow runs the evals. Another is to run evals only after the code lands in a branch of the main repository. I avoid patterns that check out and execute fork code with secrets available. The required check should report clearly that evals were not run, rather than showing green.
Sourced from Docs by LangChain (MCP)
14How do you protect PII and sensitive data in CI eval traces sent to LangSmith?Very often asked
Test cases live in code and in a dataset that many engineers can read, so they should be curated or synthetic, not raw customer data. When cases come from production traces, I scrub or anonymise them before they become test parameters. Traces capture full inputs and outputs, so I mask sensitive fields before they leave the process, using the SDK's input and output masking options or by not logging those fields. API keys stay in CI secrets, are scoped to the right workspace and are never printed. Access to the workspace that holds eval datasets follows least privilege. I also check data residency and retention settings against the organisation's policy.
Sourced from Docs by LangChain (MCP)
15How do you know your LLM-as-judge is trustworthy enough to gate merges?Very often asked
I treat the judge as a model that needs its own evaluation. I sample cases, have humans score them in an annotation queue against the same rubric, and measure how often the judge agrees with them. Where it disagrees, I tighten the rubric, add few-shot examples to the judge prompt, or switch to a stronger judge model. I pin the judge model and the judge prompt version, so the measurement does not drift. I check for known biases, such as favouring longer answers or position bias in pairwise setups. Until agreement is good, the judge score stays non-blocking and visible only, and hard assertions do the gating.
Sourced from Docs by LangChain (MCP)
16Should the gate fail on per-example thresholds or on aggregate scores compared with the baseline? Discuss the trade-off.Very often asked
Per-example assertions are simple and map naturally to test runners: one bad case gives one red test with a clear trace. But they are sensitive to noise on borderline examples. They also miss broad, small degradations where each example stays just above its threshold. Aggregate comparison against the main baseline catches that drift, but it needs a post-run step that reads experiment results and compares them, and the failure is less localised. I use both. Critical cases get per-example hard assertions. Soft quality gets an aggregate check with a tolerance based on measured variance. The comparison view then shows exactly which examples drove the aggregate drop.
Sourced from Docs by LangChain (MCP)
17How does the suite grow over time from annotation queues and real failures?Very often asked
Disputed or ambiguous results go to an annotation queue where reviewers score runs against a rubric. When reviewers confirm a new failure mode, it is exported to a dataset or, more often in this workflow, added as a new parametrized test case with inputs and reference outputs in code. That way it runs on every future PR. Production issues follow the same path: a failing trace is captured, scrubbed of PII and turned into a regression test. The rule is that every confirmed bug leaves behind a test. Over time the suite reflects real failure modes rather than only the cases engineers imagined up front.
Sourced from Docs by LangChain (MCP)
18How do you upgrade the judge model without breaking the gate?Very often asked
Changing the judge changes the measuring instrument, so old and new scores are not directly comparable. I run the new judge alongside the old one on the same experiments, logging both as separate feedback keys, and compare each against human labels from an annotation queue. I recalibrate thresholds from the new judge's score distribution on main. Then I switch the blocking assertion to the new key in a dedicated PR, and re-run main to create a fresh baseline. I never bundle a judge upgrade with an application change, because a score movement could then come from either one.
Sourced from Docs by LangChain (MCP)
19Why split evals into blocking and non-blocking suites, and what goes in each?Very often asked
A single gate has to be both strict and stable, and those goals conflict for subjective metrics. The blocking suite holds deterministic assertions and well-calibrated judge checks with proven agreement with humans. It runs fast on every PR and is a required status check. The non-blocking suite holds new tests, experimental judges, quarantined flaky cases and expensive long-horizon agent scenarios. It still syncs to LangSmith as experiments, so reviewers see trends, but it does not stop merges. Tests graduate from non-blocking to blocking once they have shown stable results across repeated runs on main.
Sourced from Docs by LangChain (MCP)
20How do CI evals relate to online evaluation in LangSmith? Are they redundant?Very often asked
They answer different questions. CI evals are offline: a fixed dataset, run before merge, to catch regressions caused by code or prompt changes. Online evaluators run on production runs or threads, with filters and sampling rates, to catch issues from real traffic that the dataset never covered. They feed dashboards, alerts, automation rules and webhooks. They form a loop. Online evaluation surfaces new failure modes, those become test cases, and CI stops them from coming back. One operational difference to know: running an online evaluator on a trace upgrades that trace to extended retention, which has cost and data-retention implications.
Sourced from Docs by LangChain (MCP)
21The model provider has an outage during CI. Should the gate fail open or fail closed?Very often asked
It should fail closed by default, because a gate that passes when it could not evaluate lets regressions merge. But it must fail clearly as an infrastructure problem, not as a quality regression, so nobody wastes time debugging prompts. Retries with backoff handle short blips. For long outages, the team needs a documented break-glass path: an authorised person can override the required check with a recorded reason, and the suite is rerun once the provider recovers. Cached calls still replay, so only uncached cases are affected. I would also alert when the infrastructure error rate spikes, separately from eval failures.
Sourced from Docs by LangChain (MCP)
22The team intentionally changed behaviour and the suite now fails. How do you re-baseline correctly?Very often asked
The failing tests are doing their job. The fix is to update the test expectations, not to loosen the gate. In the same PR, I update reference outputs, assertions or thresholds for the affected cases, so the reviewer sees the behaviour change and the expectation change together. Reviewers confirm in the comparison view that only the intended examples moved. Unexpected movers are investigated separately. After merge, the next main run produces the new baseline experiment. I avoid broad threshold drops to get green, because they also lower protection on unrelated examples.
Sourced from Docs by LangChain (MCP)
23When would you use agentevals trajectory evaluators rather than only checking the final answer?Often asked
For agents, a correct final answer can hide a bad path: redundant tool calls, a tool called with the wrong arguments, or a lucky guess with no retrieval at all. The opposite also happens, where the path was correct but the final wording drifted. Trajectory evaluators in agentevals score the sequence of steps and tool calls, either against a reference trajectory or with a trajectory LLM-as-judge. I use deterministic trajectory checks, such as which required tool calls happened, as hard assertions. I use the judge-based trajectory score as feedback. This is especially useful for LangGraph agents, where the trace already contains every node and tool call.
Sourced from Docs by LangChain (MCP)
24How would you quarantine a flaky eval test without losing its signal?Often asked
First I confirm that it is flaky by running it with repetitions on an unchanged main. If it is, I move it from the blocking suite to a non-blocking suite that still runs and syncs to LangSmith as an experiment, so its scores remain visible and comparable over time. I open a ticket with an owner and a deadline. Then I fix the root cause: a vague rubric, a judge that disagrees with humans, a non-deterministic tool, or a threshold too close to the mean. Deleting the test or wrapping it in retries until it passes hides the problem. Quarantine is only acceptable if it is tracked and temporary.
Sourced from Docs by LangChain (MCP)
25How would you turn production traces into CI test cases safely?Often asked
Online evaluators and dashboards surface problem runs. I add those runs to an annotation queue, where a reviewer confirms the failure and writes the correct reference output. Before a case enters the test suite, I remove or replace personal and confidential data, because tests and datasets are widely visible and live in version control. I keep only the inputs needed to reproduce the behaviour. If the case depends on retrieved documents or tool results, I either freeze those as fixtures or confirm that the live dependency is stable. Each new case should carry a short comment explaining which incident or failure mode it guards against.
Sourced from Docs by LangChain (MCP)
26If someone edits the synced dataset directly in the LangSmith UI, what consistency problems can arise and how do you avoid them?Often asked
With this integration, the test parameters in code are the source of truth, and each run upserts the dataset from them. Manual UI edits to that dataset can diverge from what the code produces, which makes it unclear which reference output a given experiment used. The edits may also be overwritten or ignored on the next sync. To avoid this, I treat the synced dataset as derived and read-only. Changes to inputs or reference outputs go through a pull request on the test file, so they are reviewed and versioned with the code. Curated datasets that people edit in the UI live separately and feed evaluate() runs, not the CI suite.
Sourced from Docs by LangChain (MCP)
27Many pull requests run the same suite at once. How does that work and what must you watch for?Often asked
Each CI run creates its own experiment against the shared dataset, so concurrent PRs do not overwrite each other's results. Reviewers follow the experiment link from their own job. The risks are elsewhere. Concurrent jobs share provider rate limits and can trigger 429s, so I cap concurrency per job and retry with backoff. If two PRs change test parameters for the same suite, the dataset reflects whichever synced last, so baselines on changed examples need care. Shared cache directories should be scoped so that one branch's replayed responses do not mask another branch's real changes. Overall spend also scales with concurrent PRs.
Sourced from Docs by LangChain (MCP)
28A prompt change produces different but arguably better outputs, and scores are mixed. How do you decide?Often asked
Absolute judge scores are weak when two outputs are both acceptable. I use pairwise comparison instead. A pairwise annotation queue takes exactly two experiments, the PR and the main baseline, and reviewers choose the better output per example against a rubric. A pairwise LLM-as-judge can give a quicker first pass, ideally with position swapping to reduce bias. If humans prefer the new behaviour, I update the reference outputs or thresholds in the test code within the same PR, so the new baseline is explicit and reviewed. If preferences are split, I look for the specific example categories that regressed before approving.
Sourced from Docs by LangChain (MCP)
29When should a CI run bypass LANGSMITH_TEST_CACHE?Often asked
The cache is valuable on PRs because it replays unchanged LLM calls instead of re-billing them and makes reruns faster and more stable. But replayed responses do not reflect what the live model would do today. I bypass it in a scheduled job, for example nightly or before releases, so the suite exercises live model behaviour and catches provider-side changes. I also bypass or clear it when changing models, model parameters or anything that affects requests, and when debugging a suspected flake. The live runs are also the honest baseline, so I compare cached PR results with them periodically.
Sourced from Docs by LangChain (MCP)
30How do you make judge scores auditable for reviewers?Often asked
A bare number gives reviewers nothing to argue with. I have the judge return a short explanation along with its score, and I log it as the feedback comment next to the score. I trace the judge call, so reviewers can see the exact judge prompt, model and input it saw. I pin the judge prompt in the Prompt Hub by tag, which ties every score to a specific judge version. In the comparison view, a reviewer can then open a regressed example, read the app trace and the judge's reasoning, and decide whether the regression is real or a judge mistake. Disputed cases go to the annotation queue.
Sourced from Docs by LangChain (MCP)
31How would you test multi-turn conversational behaviour in this pytest or Vitest setup?Often asked
Each test case's inputs hold the conversation history up to the turn under test, plus the new user message. The reference output describes the expected response or behaviour. The test replays the history through the real chain or LangGraph agent and asserts on the final turn. For behaviour that only appears across several turns, I script a short simulated conversation within one test and log feedback per turn or for the whole exchange. I keep user simulators deterministic, or at least repeated, because a simulated user adds a second source of non-determinism. In production, threads group multi-turn conversations, so online evaluators can score whole threads too.
Sourced from Docs by LangChain (MCP)
32How would you scale this approach to a monorepo with many LLM features and teams?Often asked
I give each feature its own suite with a stable LANGSMITH_TEST_SUITE name and a clear owning team. Datasets and experiments then stay focused and comparable. CI uses path filters, so a PR runs only the suites whose code, prompts or dependencies changed, plus a small shared smoke suite. Cache directories are scoped per suite. Concurrency limits are set per job to respect shared provider quotas, and spend is tracked per suite. Shared judges and rubrics live in one internal library with pinned versions. Ownership rules make clear who triages a red suite, so failures do not sit untouched in someone else's queue.
Sourced from Docs by LangChain (MCP)
33What are the trade-offs between code-rule evaluators and LLM-as-judge evaluators in a CI gate?Often asked
Code rules are deterministic, free to run, fast and easy to debug: schema validation, regex for forbidden content, checking that a tool was called. They make ideal blocking assertions, but they cannot judge meaning, tone or faithfulness. LLM-as-judge covers those qualities with prebuilt templates and few-shot examples. But it costs model calls, adds latency and noise, can carry biases, and needs its own validation against human labels. In practice, I push as much as possible into code rules and use judges for the remainder. Judge scores gate only after calibration, preferably on aggregates or repeated samples rather than single draws.
Sourced from Docs by LangChain (MCP)
Objective questions 33
1In the LangSmith pytest integration, what makes a test function sync its results to LangSmith as part of an experiment?Asked almost every time
Why: The @pytest.mark.langsmith marker tells the plugin to log the test case as a dataset example and record the run as an experiment. Naming the file or calling evaluate() inside a test does not do this.
Sourced from Docs by LangChain (MCP)
2Which marker makes a pytest test function part of a LangSmith-tracked test suite?Asked almost every time
Why: The @pytest.mark.langsmith marker tells the integration to sync that test as an example and record its result in an experiment.
Sourced from Docs by LangChain (MCP)
3Which module provides ls.describe and ls.test for TypeScript eval tests?Asked almost every time
Why: The Vitest integration is imported from langsmith/vitest and used together with the LangSmith reporter.
Sourced from Docs by LangChain (MCP)
4A test calls t.log_feedback(key='helpfulness', score=0.2) and has no assertions. What happens to the CI build?Asked almost every time
Why: Logged feedback is only recorded; the test fails only when an assertion, such as assert score >= threshold, fails.
Sourced from Docs by LangChain (MCP)
5How does an eval failure end up blocking a merge?Asked almost every time
Why: Blocking comes from the CI check status enforced by branch protection, and the check status is driven by the runner's exit code.
Sourced from Docs by LangChain (MCP)
6Which check belongs in a hard assertion rather than a judge score?Asked almost every time
Why: Schema validity is deterministic and objectively checkable, so it can block without adding noise.
Sourced from Docs by LangChain (MCP)
7A test hits a provider rate limit (HTTP 429) after retries are exhausted. How should the gate treat it?Asked almost every time
Why: Separating infrastructure errors from quality failures avoids both false regressions and false passes.
Sourced from Docs by LangChain (MCP)
8How does an LLM eval written with langsmith/vitest actually fail a CI build?Very often asked
Why: Gating relies on the normal test runner exit code from failed assertions. The LangSmith sync records results for review but does not itself control the build.
Sourced from Docs by LangChain (MCP)
9Which environment variable controls the name of the dataset that the test suite syncs to?Very often asked
Why: LANGSMITH_TEST_SUITE sets the suite name, which becomes the dataset that each run's experiment is recorded against.
Sourced from Docs by LangChain (MCP)
10What does LANGSMITH_TEST_CACHE do when it points at a cached directory?Very often asked
Why: The cache records request and response pairs, so identical calls are replayed rather than sent to the provider again.
Sourced from Docs by LangChain (MCP)
11In this workflow, what does a single test case, including one parametrized case, correspond to in LangSmith?Very often asked
Why: Each test case becomes one example, with inputs and reference outputs taken from the test parameters.
Sourced from Docs by LangChain (MCP)
12What is created in LangSmith each time CI runs the suite?Very often asked
Why: The dataset is upserted and stays stable, while each run is recorded as a new experiment containing outputs, feedback and traces.
Sourced from Docs by LangChain (MCP)
13Why does the CI job pull prompts from the Prompt Hub by tag?Very often asked
Why: Pulling by tag pins the exact prompt version, so a score change can be tied to a known prompt version rather than an unreviewed edit.
Sourced from Docs by LangChain (MCP)
14Pull requests from forks in GitHub Actions do not receive repository secrets. What is the safest response?Very often asked
Why: This protects credentials from untrusted code and keeps the gate from showing a false green.
Sourced from Docs by LangChain (MCP)
15A judge score on a borderline example varies between runs of an unchanged main. Which change most reduces false blocks while keeping real regressions visible?Very often asked
Why: Averaging repetitions and calibrating against observed variance separates noise from real drops.
Sourced from Docs by LangChain (MCP)
16A suite has 100 examples, runs 3 repetitions, and each example makes 1 application call and 2 judge calls. How many model calls does one uncached run make?Very often asked
Why: 100 examples × 3 repetitions × (1 + 2) calls = 900 model calls.
Sourced from Docs by LangChain (MCP)
17In the comparison view, what should a PR experiment normally be diffed against?Very often asked
Why: Comparing with main's latest experiment isolates the effect of the PR's changes.
Sourced from Docs by LangChain (MCP)
18A reviewer disagrees with the judge on several failing examples. What is the workflow's intended next step?Very often asked
Why: Annotation queues resolve disputed cases with human judgment, and the results can calibrate the judge.
Sourced from Docs by LangChain (MCP)
19Human review confirms a new failure mode. How should it be captured?Very often asked
Why: Adding confirmed failures to the dataset or the tests makes the suite grow and prevents the regression from returning.
Sourced from Docs by LangChain (MCP)
20Every example stays just above its per-example threshold, but quality dropped slightly across most of them. Which check catches this?Very often asked
Why: Broad small degradation shows up in aggregates compared with the baseline, even when no single example crosses its threshold.
Sourced from Docs by LangChain (MCP)
21What is the main risk of reusing LANGSMITH_TEST_CACHE across CI runs without invalidating it?Often asked
Why: The cache replays earlier LLM responses. If it is not invalidated when prompts, models or dependencies change, tests can pass against outputs the new code would never produce.
Sourced from Docs by LangChain (MCP)
22Which pytest helper records the expected answer for an example?Often asked
Why: t.log_reference_outputs stores the reference outputs that become part of the dataset example.
Sourced from Docs by LangChain (MCP)
23Which call logs a feedback score from inside a Vitest LangSmith test?Often asked
Why: ls.logFeedback is the Vitest equivalent of t.log_feedback in pytest.
Sourced from Docs by LangChain (MCP)
24A pairwise annotation queue is configured with which experiments?Often asked
Why: Pairwise queues compare exactly two experiments, for example a PR experiment against the main baseline.
Sourced from Docs by LangChain (MCP)
25Which package provides trajectory evaluators such as a trajectory LLM-as-judge for agents?Often asked
Why: agentevals provides trajectory evaluators that score an agent's sequence of steps and tool calls.
Sourced from Docs by LangChain (MCP)
26What does wrap_openai do in an eval test?Often asked
Why: wrap_openai instruments the client, so every model call appears in the trace recorded for that test.
Sourced from Docs by LangChain (MCP)
27According to LangSmith's behaviour, what upgrades a trace to extended retention?Often asked
Why: The reference notes state that running an online evaluator on a trace upgrades it to extended retention.
Sourced from Docs by LangChain (MCP)
28Filters and sampling rates are configuration for which part of LangSmith?Often asked
Why: Online evaluation runs on production traffic and uses filters and sampling rates to choose which runs to score.
Sourced from Docs by LangChain (MCP)
29Why run the suite on a schedule with the cache bypassed, in addition to cached PR runs?Often asked
Why: Replayed responses reflect past behaviour; live runs confirm that the baseline still matches what the model does now.
Sourced from Docs by LangChain (MCP)
30Which approach keeps sensitive user data out of CI eval traces?Often asked
Why: Tests and traces are widely visible, so data should be sanitised and masked at the source.
Sourced from Docs by LangChain (MCP)
31Two pull requests run the same suite at the same time. What is true?Often asked
Why: Experiments are created per run, so concurrent runs stay separate and each can be compared with the baseline.
Sourced from Docs by LangChain (MCP)
32In LangSmith tracing, what do threads group?Sometimes asked
Why: Threads group the runs of a multi-turn conversation, and online evaluators can score whole threads.
Sourced from Docs by LangChain (MCP)
33With LangSmith's native OpenTelemetry support, how do you send the same traces to several backends?Sometimes asked
Why: LangSmith accepts OTLP, and a collector can fan traces out to several destinations.
Sourced from Docs by LangChain (MCP)
Track your progress through every blueprint in your dashboard.
Start learning