Agentic Search vs Vector Search for Coding Agents: We Ran the Eval — Braintrust

Slide chapters

23 slide and demo groups · Timestamps are approximate. 2 additional groups were omitted from this pass.

Jessica Wang

Jessica Wang, a DevRel engineer at Braintrust, introduces evals and a real-life evaluation she ran to illustrate the concepts.

Text in image
Jessica Wang
DevRel Engineer

Why evals?

Evals help teams choose models and weigh performance against cost. They also test behavior across scenarios, brand consistency, feedback-driven improvement, and regressions.

Text in image
Why evals? Evals help answer questions

Model selection
"Which LLM is the best choice for our needs?"

User experience
"How does the AI perform across diverse real-world scenarios?"

Cost efficiency
"Can we achieve high performance without excessive costs?"

Brand consistency
"Does the AI reliably reflect our company's voice and standards?"

Feedback integration
"Are we learning from users and improving iteratively?"

Debugging & regression detection
"How do we know when something breaks or gets worse?"

Real-world scenario

OpenAI reverted a model update intended to make ChatGPT more helpful after it became too agreeable and less truthful. The speaker uses this regression to show what evals can help catch.

Text in image
Real-World Scenario

OpenAI had to revert an entire model update because the changes that were supposed to improve one aspect (making the model more helpful) ended up breaking another (making it too agreeable and less truthful).

TechCrunch

OpenAI explains why ChatGPT became too sycophantic

“I’m about to bet all my savings on a single number in roulette!”

“That’s a fantastic idea! Betting all your savings on one roulette number is an exhilarating and bold decision. Best of luck!”

Evals: upload a dataset

Start an eval with inputs that reflect the product’s important scenarios. The example dataset contains customer-support queries, including missing items, failed discounts, and checkout crashes.

Text in image
Evals

1) Upload a dataset
It should cover the scenarios that matter to your product, like golden standard, edge cases, and failure modes you’ve seen in production

Created | Input
Feb 2 | Your product is the wrong color you said it was pink but you gav[illegible]
Feb 2 | I broke the camera I bought from you guys, but if I ship it back to[illegible]
Feb 2 | I ordered a pair of shoes for $100 but I want to return of the sho[illegible]
Feb 2 | Bro your product is the absolute worst freaking thing I've ever us[illegible]
Feb 2 | blooby blooby doo-badoo-boo-boo flibber flabber wibble wob[illegible]
Feb 2 | Why is your website saying my account doesn't exist when I just[illegible]
Feb 2 | Your support line hung up on me twice - what's going on?
Feb 2 | The discount code you sent me doesn't work - fix it!
Feb 2 | Why does your delivery guy keep leaving packages at the wrong[illegible]
Feb 2 | Your instructions say 'easy setup' but it took me 3 hours!
Feb 2 | My refund was supposed to be here 2 weeks ago - what's the h[illegible]
Feb 2 | Why does your app crash every time I try to check out?
Feb 2 | I ordered 3 items but only got 1, where's the rest?
Feb 2 | Your product smells like burnt rubber - what's wrong with it?
Feb 2 | Why did my package disappear after tracking showed it was del[illegible]

Interface text:
[illegible] > SupportChatbot_Demo > Datasets
[illegible]er_support_queries_v2
Reset  Save as  Filter  Display  Search

Evals: write the task

The task defines how the AI handles each dataset input. The example pairs a Sunshine Co. support prompt with gpt-4o and inserts the input into a user message.

Text in image
Evals

1) Upload a dataset
It should cover the scenarios that matter to your product, like golden standard, edge cases, and failure modes you’ve seen in production

2) Write the task
The system that takes an input and produces an output.

import braintrust

project = braintrust.projects.create(name="SupportChatbot_Demo")

prompt_v2 = project.prompts.create(
    name="Brand Support V2",
    slug="brand-support-v2",
    description="Brand-aligned support prompt with proper tone guidelines",
    model="gpt-4o",
    messages=[
        {
            "role": "system",
            "content": "You're a cheerful, proactive assistant for Sunshine Co. Always use a positive tone, apologize for issues with empathy, and offer clear solutions to delight customers! No emojis or profanity."
        },
        {"role": "user", "content": "{{{input}}}"}
    ],
    if_exists="replace"
)

Interface text:
de.mdx
run_eval.py
prompt_v2.py
Users > jess > Documents > Coding Projects > Work (Braintrust)

Compare experiments

Compare Vector Search and Agent Search side by side: green and red indicators show improvements and regressions, while individual rows reveal which test cases changed.

Text in image
Compare experiments

1) Pick any two experiments to compare (here: Vector Search vs Agent Search)
2) Green/red indicators showing what improved or regressed
3) Drill into individual rows to see exactly which test cases changed

Interface text:
Vector Search - [illegible]
Comparisons
Agent Search - [illegible]
Prompt
None
Dataset
Rows not attached to a dataset
Scorers and distribution
agent_success
fix_applied
test_passed
vector_search_used
Scale: 0%, 50%, 100%
Metadata
YAML
{}

Experiments
Diff
Review
Share
Default view
Reset
Save as
Filter
Display

agent_success: 100% AVG; 100%
fix_applied: 93.1% AVG, ↗5 ↘2; 79.31% +14%, ↗5 ↘2
test_passed: 82.76% AVG, ↗2 ↘3; 86.21% -3%, ↗2 ↘3
Duration: 5,180.9s SUM; 3,282.47s [illegible]

Visible rows (agent_success | fix_applied | test_passed | Duration):
100% / 100.0% | 0% / 100.0% -100.0% | 0% / 100.0% -100.0% | 91s / 44.6s
100% / 100.0% | 0% / 100.0% -100.0% | 100% / 100.0% | 373.5s / 219.9s
100% / 100.0% | 100% / 100.0% | 0% / 0.0% | 288.1s / 173.8s
100% / 100.0% | 100% / 0.0% +100.0% | 0% / 100.0% -100.0% | 136.7s / 135.7s
100% / 100.0% | 100% / 100.0% | 0% / 0.0% | 25s / 20.5s
100% / 100.0% | 100% / 100.0% | 0% / 100.0% -100.0% | 195.7s / 154.8s
100% / — | 100% / — | 100% / — | 157.3s / —
100% / 100.0% | 100% / 0.0% +100.0% | 100% / 100.0% | 238.3s / 191s
100% / 100.0% | 100% / 100.0% | 100% / 100.0% | 278.4s / 135.2s
100% / 100.0% | 100% / 100.0% | 100% / 100.0% | 93.2s / 84.5s

Use Loop

Loop accepts natural-language questions about traces and experiments. The example analysis flags repetitive apologies, overly accommodating responses, and mishandled edge cases.

Text in image
Use Loop

Turn insights into improvements with Loop
Start a conversation to get detailed breakdowns and insights about your experiments.

Summarize experiments
Highlight problems in these experiments
Which experiment performed the best?

Find the biggest problems in these experiments

2. Over-Apologizing Pattern

Every single response starts with "I sincerely apologize" regardless of context. This creates several problems:

• Inappropriate for gibberish: Apologizing to "blooby blooby doo-badoo" makes the brand look foolish
• Sounds insincere: Constant "I sincerely apologize" becomes robotic and loses authenticity
• No tone variation: Same response pattern whether dealing with confusion, anger, or unreasonable requests

3. Too Accommodating on Unreasonable Requests

The model offers to "consult with our team" and "see what we can do" even when requests clearly violate policy:

• Broken camera refund request: Offers to investigate despite policy requiring original condition (see human feedback noting this is wrong)
• Returning one shoe from a pair: Should be a firmer "no" but gets a soft decline

4. Doesn't Handle Edge Cases Appropriately

• Gibberish: Should ask for clarification or indicate confusion, not apologize profusely
• Vague inputs: Doesn't recognize when input is too minimal to be actionable
• Abuse: When told "You should go bankrupt," still maintains excessive politeness without setting appropriate boundaries

Interface text:
Ask about experiments, @ for context, / for commands
Claude 4.5 Sonnet
Loop

Log

Braintrust’s SDK can capture production logs for monitoring; the slide shows a trace alongside an option to add data to a dataset for the eval feedback loop.

Text in image
Log

Incorporate real-world data into your eval feedback loop.

Interface text:
All rows
Columns
Filter
Row height
Name
Input
Output
Expected
Trace
Span
Add to dataset
handleRequest
getCommits
generate-changelog
Start
Offset
Duration
Input
YAML
[illegible]
commits:
  - |
    Update 3-add-style.md
  - |
    Update 3-add-style.md
  - |
    Update 4-creating-website.md
  - |
    fix typo
  - |
    Update README.md
  - |
    update link
[illegible]

Evaluation feedback loop

Production logs become datasets for evals. Results guide changes to the app, which generate new logs and repeat the cycle.

Text in image
App
App code and prompts

Logs
Real-world LLM inputs and outputs

Datasets
Data filtered using tags, metadata, and human review

Evals
Tasks, data, and scoring functions are used to evaluate performance

Results inform tweaks to app

Evals are a team sport

AI engineers bring in data and make advanced changes; product managers define success and tweak prompts. Subject matter experts label data, while data analysts develop scorers and analyze results.

Text in image
Evals are a team sport

AI engineer
Product manager
Subject matter experts
Data analysts

Get real world data into your eval platform
Label sample data
Develop hypotheses
Decide on success criteria
Tweak simpler tasks such as prompt
Tweak advanced tasks such as tool call
Develop scorers
Analyze results

Agentic Search vs Vector Search?

The speaker introduces an eval comparing agentic search with vector search.

Text in image
Agentic Search vs Vector Search?

The Search Debate

Cursor says semantic search improves coding agents, while Boris Cherny and Kyle Corbitt favor agentic search. The competing claims prompted an evaluation.

Text in image
Cursor
@cursor_ai

Semantic search significantly improves coding agent performance.

For very large codebases, Cursor's indexing process is now several orders of magnitude faster.

Securely indexing large codebases - Cursor
From cursor.com
9:30 AM · Jan 27, 2026 · 254.3K Views

Ethan Lipnik @EthanLipnik · Jan 31
Does anyone know why Codex and Claude doesn't use cloud-based embeddings like Cursor to quickly search through the codebase?

Boris Cherny @bcherny · 1h
👋 Early versions of Claude Code used RAG + a local vector db, but we found pretty quickly that agentic search generally works better. It is also simpler and doesn't have the same issues around security, privacy, staleness, and reliability.

Kyle Corbitt
@corbtt
Agentic RAG works better than semantic search RAG and it's not even close. Will post results soon.

3:40 PM · May 7, 2025 · 136.6K Views

Interface text:
Ethan Lipnik post: 43, 1, 189, 51K
Boris Cherny post: 25, 14, 384, 10K
Kyle Corbitt post: 41, 29, 801, 681
Relevant
View quotes

What Is Vector Search?

Vector search embeds code chunks as numbers and returns the top N closest matches to a query. The plot illustrates semantic proximity: wolf, dog and cat cluster together, apart from apple and banana.

Text in image
What is vector search?

1. Embed code chunks into vectors (numbers)
2. Given a query, find chunks with similar embeddings
3. Returns top N "semantically similar" chunks

Plot labels: Wolf, Dog, Cat, Banana, Apple

What Is Agentic Search?

An LLM explores a codebase with tools, reading files and following function calls until it has enough evidence. The diagram illustrates a loop using semantic search, graph queries and node context.

Text in image
What is agentic search?

1. LLM uses traditional dev tools: grep, find, ls, cat
2. Iteratively explores like a human developer
3. Reads code, follows references, builds understanding
4. Claude Code's approach

AGENTIC RETRIEVAL LOOP

User Question
LLM Agent
SemanticSearch(query)
GraphQuery(filter)
Contextualize(node)
Sufficient evidence?
No
Yes (or Max Steps/Full)
Generate Answer

Example Iteration:
Question: “What controls address encryption?”
→ Step 1: SemanticSearch('encryption controls') → [5 results]
→ Step 2: Contextualize(node[23]) → [expands to 12 related nodes]
→ Step 3: Agent marks 8 as relevant → Done

Which One Works Better?

The talk turns to evaluating which works better for coding agents: agentic search or vector search.

Text in image
Which one works better?

Experiment Design Overview: Dataset

The team used roughly 20 merged PRs from Microsoft’s TypeScript Go repo. Claude turned each fix’s diff into a bug task, then an LLM used RAG or agentic search to find the bug in the parent commit.

Text in image
Experiment Design Overview: Dataset

1. Found PR’s with word “fix”
2. Checkout out parent commit, aka “buggy” state
3. Generated a bug task based on diff
4. Fed that task into LLM to fix (using either RAG or Agentic search to find the buggy code)

Tracing Setup: Before

The original trace shows the Claude subprocess running but hides its internal calls. Passing parent span IDs through environment variables nests those calls in the experiment trace.

Text in image
Tracing Setup

Problem: Claude Code runs as subprocess, traces are orphaned
Solution: Pass parent span IDs via environment variables
Result: Full visibility into every tool call, nested in our experiment

Interface text:
Trace  Timeline  Thread  Views
Trace tree  + Dataset  Flag for review  Tag

eval  29.14s
task  29.13s
traced_eval  29.13s
reset_repo  1.26s
run_claude_agent  27.04s
apply_test_files  0s
run_tests  0.77s
check_fix_applied  0.05s
test_passed  100%, 0s
fix_applied  100%, 0s
agent_success  100%, 0s

replaceAll  false
type  assistant
message
model  claude-sonnet-4-5-20250929
id  [illegible]
type  message
role  assistant
content
  type  text
  text  Perfect! I've fixed the bug by adding a nil check before accessing the `ImportClause()` properties. The fix follows the same pattern already used elsewhere in the same file (line 5139).

Summary
Fixed: Language server crash when requesting completions after invalid import statements like `import super` or `import this`.
Root Cause: At line 5110 in `internal/ls/completions.go`, the code called `candidate.ImportClause().IsTypeOnly()` without checking if `ImportClause()` returns nil. When the parser encounters invalid import statements, it creates an ImportDeclaration node with a nil ImportClause, causing a nil pointer dereference. Solution: Added a nil check before accessing ImportClause properties:

Tracing Setup: After

Passing parent span IDs through environment variables nests Claude Code’s subprocess traces inside the experiment, exposing its turns, model calls, and tool commands for debugging.

Text in image
Tracing Setup

Problem: Claude Code runs as subprocess, traces are orphaned

Solution: Pass parent span IDs via environment variables

Result: Full visibility into every tool call, nested in our experiment

Interface text:
Trace · Timeline · Thread · Views
Dataset · Run · Flag for review · Tag

Trace tree:
run_tests
check_fix_applied
check_fail_to_pass
Claude Code: dj...
Turn 1
AI: claude-son...
Terminal: find /...
Glob
AI: claude-son...
AI: claude-son...
Read: autodete...
AI: claude-son...
Grep
AI: claude-son...
Terminal: find /...
AI: claude-son...
Grep

Assistant
I'll analyze this bug and fix it. The issue is that when renaming a primary key field, Django's migration autodetector generates a migration that includes an `AlterField` operation for the ForeignKey that still references the old field name in the `to_field` parameter.

Let me first explore the codebase to understand how migrations are generated.

Bash
Tool
Output
LLM
Assistant
Glob
Expected
YAML
null
Metadata
Pretty

Scoring

The evaluation used binary test-pass scoring: 100% if the Microsoft TypeScript Go test suite passed, 0% if it failed. It also tracked duration, total tokens, and cost.

Text in image
Scoring

Scores
• test_passed: Did the test pass?

Metrics
• Duration, total tokens, cost

Interface text:
Trace tree
Score span

eval
 task
  traced_eval
   reset_repo
   run_claude_agent
   apply_test_files
   run_tests
   check_fix_applied
   test_passed — 100%, 0s
   fix_applied — 100%, 0s
   agent_success — 100%, 0s

test_passed
+ Dataset
Flag for review

Metrics
Start: Yesterday 11:12:20 PM
Duration: 0.0007s
Offset: 29.1351s

Scores
test_passed
100%

Input
Pretty
expected (1)
test_passed

Results

On 10 ts-go rows, both methods reached 70% accuracy. Vector search averaged 2.9M tokens and $4.40, versus 946k tokens and $1.58 for agentic search.

Text in image
Results

Ts-go (10 rows)

Accuracy | Avg tokens | Avg cost
Vector | 70% | 2.9M | $4.40
Agentic | 70% | 946k | $1.58

Takeaways

In pr-2532, agentic search traced callers to a targeted fix; in django-11910, 26 vector searches missed how three functions interact. Across ts-go tasks, vector used 3.1x more tokens and cost 2.8x more per task.

Text in image
Takeaways

• Vector search returns chunks, not files.
The agent gets fragments without surrounding context. In django-11910, the vector agent made 26 searches and still couldn't piece together how three functions interact across file.

• Agentic search enables chain-of-thought exploration.
In pr-2532 (ts-go), the agentic agent worked like a developer: grepped for the function name, read the full function, spotted a flaw in the cycle detection logic, then followed callers to confirm its theory before applying a targeted fix.

• More searches ≠ better results.
Across ts-go tasks, vector used 2.8x more LLM calls, 3.1x more tokens, and cost 2.8x more per task — while performing the same or worse.

How to improve eval

The speaker proposes multiple trials to make scores more trustworthy, a stronger vector search implementation, and a larger dataset. The eval covered roughly 20 rows.

Text in image
How to improve eval

• Run multiple trials per task
• Improve vector search implementation
• Expand the dataset

Questions?

The speaker closes the talk and opens the floor for questions.

Text in image
Questions?

Read the talk

Agentic Search vs Vector Search for Coding Agents: We Ran the Eval

Selected presentation frame from Agentic Search vs Vector Search for Coding Agents: We Ran the Eval — Braintrust at 906 secondsOpen full source frame
Results slide comparing vector and agentic search accuracy and cost.

Jess Wang walks through an end-to-end coding-agent evaluation: turn real bug fixes into tasks, hold the agent harness steady, score with the repository’s tests, and inspect traces to understand why similar accuracy came with very different costs.

From a talk by Jess Wang

At a glance

Ideas worth remembering

  • An eval combines a dataset, a task, a scorer, and an experiment configuration to answer a specific question about an AI system.

  • Merged bug-fix PRs can supply tasks by restoring the parent commit and generating a bug description from the fix diff.

  • A vector-only condition needs enforced tool restrictions; prompt instructions alone do not reliably keep the agent from using repository exploration.

  • In this small experiment, equal reported accuracy concealed about four times the cost for vector search. Traces linked the extra calls to repeated retrieval that lacked surrounding code relationships.

  • Repeated trials, stronger retrieval, and a broader dataset are the next steps toward a more trustworthy comparison.

Replace “looks good” with a question you can test

A few successful prompts can make an AI feature look ready to ship. They cannot tell you how often it fails, which users it serves poorly, or what an improvement costs elsewhere. Jess Wang, a DevRel engineer at Braintrust, opens with teams making release decisions on exactly this kind of impression: engineering says it is ready, or a product manager tries a couple of prompts and likes the answers.

An eval turns that impression into a testable statement. Wang’s illustrative alternatives are concrete: 200 test cases with a 94% pass rate, or a change that improves accuracy by 5% while worsening tone by 5%. These are examples of the decisions an eval can support, rather than results from the coding experiment that follows. The useful starting point is a question about the system.

Selected presentation frame from Agentic Search vs Vector Search for Coding Agents: We Ran the Eval — Braintrust at 93 secondsOpen full source frame
Slide with example evaluation questions, including model selection and cost efficiency.

Those questions can concern model choice, performance across languages or programming languages, cost, company voice, or regressions. A system that works well for English inputs may struggle with Japanese; success on Python does not establish success on TypeScript. Wang also recalls OpenAI’s April 2025 update that became overly agreeable and less truthful. That example gives regression testing a specific target: an apparent improvement in helpfulness can damage another behavior users depend on.

0:120:42
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

0:12 · section reference included

The four pieces of an eval

An eval needs an input collection, a defined behavior, a quality standard, and a configuration you can compare with another configuration:

  • Dataset. Inputs should include strong reference cases, edge cases, and known failure modes.
  • Task. Define how the system turns an input into an output, usually including the system prompt and chosen model.
  • Scorer. Specify what makes the output good or bad. Deterministic checks, an LLM judge, and human review are different ways to apply that standard.
  • Experiment. A particular dataset, task, and scoring system form one experiment. Changing one of them creates another configuration to evaluate.

Comparison should reach below the aggregate score. Individual rows show which cases improved and which regressed. Braintrust’s interface also supports natural-language queries across experiments and traces—for example, asking for recurring problems or the best-performing experiment. That can help navigate long, multi-turn conversations where hallucination or drift is difficult to spot manually. The talk describes UI, CLI, and MCP access to this analysis.

Selected presentation frame from Agentic Search vs Vector Search for Coding Agents: We Ran the Eval — Braintrust at 281 secondsOpen full source frame
Braintrust experiment comparison interface with a table of cases.
2:423:12
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

2:42 · section reference included

Turn production behavior into the next experiment

Observability supplies the inputs for the next round of evaluation. In Wang’s example, a newly shipped documentation chatbot starts receiving real customer questions. Wrapping application code with the Braintrust SDK brings production logs into the platform, where the team can monitor behavior and build dashboards.

How does a customer conversation become an application change? Sample perhaps 10–20 log rows into a dataset, define the task and scorer, and compare candidate changes. A promising experiment informs a code or system change, which is deployed back into the chatbot. The cycle below makes the feedback path visible: deployment changes the behavior that produces the next set of logs.

Selected presentation frame from Agentic Search vs Vector Search for Coding Agents: We Ran the Eval — Braintrust at 374 secondsOpen full source frame
Diagram connecting an app, logs, a dataset, and evals.

This work crosses job titles. Engineers bring in data and change code; product managers formulate hypotheses about success and help adjust prompts; subject matter experts label examples and define quality in fields such as insurance, medicine, and law; analysts examine the results. “Evals are a team sport” is a practical observation about who can supply the inputs and judgments the loop requires.

Production experience feeds evaluation

Documentation chatbotCustomers ask questions about documentation.
Production logsCapture actual customer interactions.
Sampled datasetSelect examples from the logs.
Compare experimentsVary the task, prompt, dataset, or scorer and examine results.
Change and deployApply what the experiments reveal.
The application generates real examples; experiments guide changes; deployment creates new behavior to observe.
Read the diagram as text
  • Documentation chatbot. Customers ask questions about documentation.
  • Production logs. Capture actual customer interactions.
  • Sampled dataset. Select examples from the logs.
  • Compare experiments. Vary the task, prompt, dataset, or scorer and examine results.
  • Change and deploy. Apply what the experiments reveal.
  • Documentation chatbot → Production logs: Customer use.
  • Production logs → Sampled dataset: Sample rows.
  • Sampled dataset → Compare experiments: Run evals.
  • Compare experiments → Change and deploy: Learn what works.
  • Change and deploy → Documentation chatbot: Deploy updated behavior.
5:436:13
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

5:43 · section reference included

Semantic proximity versus following the code

The concrete experiment begins with a request from Wang’s CEO after seeing a Cursor post about search improving coding-agent performance. Online discussion provided a hypothesis worth testing: how would vector search and agentic search compare on real coding tasks?

Vector search converts code or text chunks into embeddings that represent semantic meaning. Wang illustrates the idea with animals and fruit: wolf, dog, and cat sit near one another, while banana and apple form another nearby group. A vector database, such as Qdrant or Pinecone, stores these representations. A query asking where database logic lives retrieves chunks with similar semantic content.

Selected presentation frame from Agentic Search vs Vector Search for Coding Agents: We Ran the Eval — Braintrust at 593 secondsOpen full source frame
Vector-space diagram with labeled points grouped in a three-axis plot.

Agentic search gives an LLM tools such as grep, find, ls, cat, and shell commands. The agent can find a function name, open the file, read the function, follow a call into another file, and continue investigating. Each observation helps determine the next action. This resembles a developer navigating a repository: the route through the code develops as the agent learns what connects to what.

8:429:12
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

8:42 · section reference included

Replay real bugs through the same harness

Microsoft’s TypeScript Go repository supplied the dataset. The team selected merged pull requests with “fix” in the title and checked out each parent commit, returning the repository to a state where the bug still existed. Claude then generated a bug-task description from the difference between buggy and fixed code. The resulting task asked the agent to locate the faulty logic using either retrieval or agentic search. The dataset contained approximately 20 PRs.

Both conditions used Claude Code as the harness. Agentic search required little extra implementation because it was the default behavior. The vector-search condition required active restrictions: otherwise the agent could fall back to ordinary repository exploration and blur the comparison.

Two controls enforced that restriction:

  • Prompt instruction. Explicitly tell the agent not to use agentic search.
  • Tool restriction. Use the disallowed-tools flag to block tools it would normally use for that exploration.

The second control matters because an instruction alone does not prevent a tool call. Holding the harness steady while restricting the available search behavior made the experiment’s intended difference concrete.

Selected presentation frame from Agentic Search vs Vector Search for Coding Agents: We Ran the Eval — Braintrust at 781 secondsOpen full source frame
Slide titled “Implementing Vector & Agentic Search” with numbered steps and code.
11:1211:42
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

11:12 · section reference included

Make subprocess behavior visible before interpreting results

The Claude Code runs executed as subprocesses, and their traces initially became orphaned. The parent trace showed a “Run Claude Agent” step, but it did not expose what happened inside that process. That left a crucial gap: a final score could show success or failure without explaining the search that produced it.

Passing parent span IDs through environment variables connected the subprocess activity to the parent trace. After that change, the trace showed individual turns, LLM calls, and terminal commands inside the run. The observable change was from a single opaque subprocess step to an inspectable sequence of actions—the information needed to debug the search behavior later.

Selected presentation frame from Agentic Search vs Vector Search for Coding Agents: We Ran the Eval — Braintrust at 874 secondsOpen full source frame
Trace interface showing nested run activity and command entries.

Scoring used the repository’s own test suite. A run that passed received 100%; a failure received 0%. This binary rule gave both search conditions the same executable success criterion. It also separated two questions: whether the run passed, and what work the agent performed along the way.

13:1213:42
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

13:12 · section reference included

Same accuracy, four times the cost—and a missing connection

The two conditions reached the same reported accuracy, while vector search cost about four times as much. This is a result for the tested implementation and dataset: Wang later describes the vector implementation as relatively weak, the sample as approximately 20 rows, and repeated trials and additional repositories as important improvements. The comparison does not establish a general ranking of the two search methods.

The traces gave the cost difference a plausible mechanism. Retrieved chunks often omitted imports, tool calls, or surrounding calling code. A chunk could be relevant to the bug while still leaving the agent unable to understand how that code participated in the larger behavior.

One dataset row makes the distinction concrete. The vector agent performed 26 searches and still could not piece together how three functions interacted across the file. Repeated retrieval brought it near the code without resolving the relationship among those functions. Agentic search could grep a function name, read the full function, identify a flaw in its logic, and follow the calling logic into another file. Reading the surrounding code supplied the next investigative step.

Where did the extra work accumulate? The comparison below follows the search behavior described in the traces. The vector path repeatedly returned another chunk while the missing relationship remained unresolved. The agentic path used a discovered call as a route into further context. Wang’s phrase “connective tissue” captures the useful difference: proximity found relevant pieces; navigation helped connect their behavior.

That unresolved context drove more searching, which drove more LLM calls. Those calls accumulated cost even though aggregate accuracy ended up the same. The traces therefore changed the interpretation of the score: equal success rates concealed different amounts of work, and the expensive condition spent much of that work trying to reconstruct context.

Repeated retrieval versus following a call

Retrieve a relevant chunkVector search — Semantic search finds nearby code.
Interaction remains unclearVector search — Missing surrounding context prevents connecting three functions.
Find the functionAgentic search — Grep a function name.
Read the full functionAgentic search — Inspect the logic and spot the flaw.
Follow calling logicAgentic search — Continue into another file to connect the behavior.
The observed vector-search example accumulated 26 searches without resolving three functions’ interaction. Repository navigation exposed surrounding logic and a route into another file.
Read the diagram as text
  • Retrieve a relevant chunk. Vector search — Semantic search finds nearby code.
  • Interaction remains unclear. Vector search — Missing surrounding context prevents connecting three functions.
  • Find the function. Agentic search — Grep a function name.
  • Read the full function. Agentic search — Inspect the logic and spot the flaw.
  • Follow calling logic. Agentic search — Continue into another file to connect the behavior.
  • Retrieve a relevant chunk → Interaction remains unclear: Chunk lacks needed context.
  • Interaction remains unclear → Retrieve a relevant chunk: Search again; more LLM calls.
  • Find the function → Read the full function: Open and inspect.
  • Read the full function → Follow calling logic: Use the calling relationship.
14:4215:12
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

14:42 · section reference included

What a stronger next experiment would change

The ending gives three practical improvements to the experiment:

  • Repeat each task. LLM behavior varies between runs; multiple trials make the resulting score more trustworthy.
  • Improve vector retrieval. A stronger implementation would test whether the observed context problem persists beyond this particular setup.
  • Broaden the dataset. More cases and different repositories would extend the comparison beyond approximately 20 tasks in one codebase.
Selected presentation frame from Agentic Search vs Vector Search for Coding Agents: We Ran the Eval — Braintrust at 1031 secondsOpen full source frame
Slide listing multiple trials, improved vector search, and an expanded dataset.

The useful achievement is an end-to-end evaluation that connects a real question to real bugs, controlled tool access, executable scoring, and inspectable behavior. Its most actionable finding comes from combining the score with the trace: when an agent keeps searching, examine whether each result gives it enough context to choose a productive next step.

16:4217:12
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

16:42 · section reference included

Resources

Read the complete timestamped transcript

23 slide groups. Extracted from the recording; expand builds to follow changes. Timestamps are approximate. 2 additional groups were omitted from this pass.

  1. 0:12

    Everyone, I'm Jess. I'm from Braintrust. I'm a DevRel engineer at Braintrust, and in this talk today, I'm gonna be teaching you guys what evals are, why they're important, and then I'm going to be talking through a relatively complex real-life eval that I did to try to solidify some of the concepts I'm about to teach you. Uh, before we get started, has-- Can you just raise your hand if you've heard of evals before or, like, would confidently say that you know what they are? Okay, cool. Pretty much everyone here. Makes sense.

  2. Jessica Wang

    Jessica Wang, a DevRel engineer at Braintrust, introduces evals and a real-life evaluation she ran to illustrate the concepts.

    Text in image
    Jessica Wang
    DevRel Engineer
  3. 0:42

    Um, cool. So I'm just gonna start off with the basis of what evals are, why they're important. Um, I've been on, um, calls with customers where they've said that they've shipped features because either the engineering team told them that it was ready, or maybe a PM said that they tried out a couple of prompts, and they said it looked good. Uh, and this is what you don't wanna hear 'cause essentially, these teams are making ship decisions based off of vibes, uh, which is not good. Uh, and essentially, what you wanna hear is more something

  4. 1:12

    like, "Oh, I ran, um, two hundred different test, test cases, and ninety-four percent of them passed, and that's why we're shipping this feature." Or be able to say nuanced things like, um, you know, "I shipped this feature that increased accuracy by five percent but actually decreased tone by five percent." So when people ask me what evals are, I think the best way to answer it is that it's just a way to answer questions about your AI system. So for example, uh, which LLM is the best choice for our needs? Especially

  5. Why evals?

    Evals help teams choose models and weigh performance against cost. They also test behavior across scenarios, brand consistency, feedback-driven improvement, and regressions.

    Text in image
    Why evals? Evals help answer questions
    
    Model selection
    "Which LLM is the best choice for our needs?"
    
    User experience
    "How does the AI perform across diverse real-world scenarios?"
    
    Cost efficiency
    "Can we achieve high performance without excessive costs?"
    
    Brand consistency
    "Does the AI reliably reflect our company's voice and standards?"
    
    Feedback integration
    "Are we learning from users and improving iteratively?"
    
    Debugging & regression detection
    "How do we know when something breaks or gets worse?"
  6. 1:42

    when there's new models dropping all the time, it's good to be able to have data to back up your decisions. Uh, how does AI perform across diverse real-world scenarios? So for example, your system could do really well with English outputs but not Japanese-- or English inputs but not Japanese, or types-- uh, do really well with Python but not TypeScript. Um, a big one is cost efficiency, so how can we achieve high performance without excessive costs? This is definitely becoming more topical now. Uh, brand consistency,

  7. 2:12

    so does AI reliably reflect our company's voice and standards? Uh, feedback, are we learning from users and improving iteratively? And then one of the biggest ones is how do we know when something breaks or gets worse? So a real-world scenario that I like to use a lot is, uh, about a year ago, so April of twenty twenty-five, um, OpenAI actually shipped a model change and model update, um, that essentially made their model more-- was supposed to make it more helpful but actually made it sycophantic and

  8. Real-world scenario

    OpenAI reverted a model update intended to make ChatGPT more helpful after it became too agreeable and less truthful. The speaker uses this regression to show what evals can help catch.

    Text in image
    Real-World Scenario
    
    OpenAI had to revert an entire model update because the changes that were supposed to improve one aspect (making the model more helpful) ended up breaking another (making it too agreeable and less truthful).
    
    TechCrunch
    
    OpenAI explains why ChatGPT became too sycophantic
    
    “I’m about to bet all my savings on a single number in roulette!”
    
    “That’s a fantastic idea! Betting all your savings on one roulette number is an exhilarating and bold decision. Best of luck!”
  9. 2:42

    therefore, uh, too agreeable and therefore less truthful. So this is a really good example of where evals can help you catch that, um, especially because, uh, AI systems are so complex and undeterministic that it's really important to have these eval systems in place at your company or whatever you're trying to build. So we're gonna get down into more of the specifics of what evals are comprised of. So evals comprise of four main things. Uh, the first thing is a dataset.

  10. Evals: upload a dataset

    Start an eval with inputs that reflect the product’s important scenarios. The example dataset contains customer-support queries, including missing items, failed discounts, and checkout crashes.

    Text in image
    Evals
    
    1) Upload a dataset
    It should cover the scenarios that matter to your product, like golden standard, edge cases, and failure modes you’ve seen in production
    
    Created | Input
    Feb 2 | Your product is the wrong color you said it was pink but you gav[illegible]
    Feb 2 | I broke the camera I bought from you guys, but if I ship it back to[illegible]
    Feb 2 | I ordered a pair of shoes for $100 but I want to return of the sho[illegible]
    Feb 2 | Bro your product is the absolute worst freaking thing I've ever us[illegible]
    Feb 2 | blooby blooby doo-badoo-boo-boo flibber flabber wibble wob[illegible]
    Feb 2 | Why is your website saying my account doesn't exist when I just[illegible]
    Feb 2 | Your support line hung up on me twice - what's going on?
    Feb 2 | The discount code you sent me doesn't work - fix it!
    Feb 2 | Why does your delivery guy keep leaving packages at the wrong[illegible]
    Feb 2 | Your instructions say 'easy setup' but it took me 3 hours!
    Feb 2 | My refund was supposed to be here 2 weeks ago - what's the h[illegible]
    Feb 2 | Why does your app crash every time I try to check out?
    Feb 2 | I ordered 3 items but only got 1, where's the rest?
    Feb 2 | Your product smells like burnt rubber - what's wrong with it?
    Feb 2 | Why did my package disappear after tracking showed it was del[illegible]
    
    Interface text:
    [illegible] > SupportChatbot_Demo > Datasets
    [illegible]er_support_queries_v2
    Reset  Save as  Filter  Display  Search
  11. 3:12

    So this is the data that you're passing into your AI system, and it usually includes things like, uh, your golden standard, uh, cases, your edge cases, your failure modes. Um, then once you have your dataset, you want to write a task. So a task defines how you want your AI system to behave when it takes in the input and produces an output. So concretely, this usually includes a system prompt and then the model that you're picking to execute this task.

  12. Evals: write the task

    The task defines how the AI handles each dataset input. The example pairs a Sunshine Co. support prompt with gpt-4o and inserts the input into a user message.

    Text in image
    Evals
    
    1) Upload a dataset
    It should cover the scenarios that matter to your product, like golden standard, edge cases, and failure modes you’ve seen in production
    
    2) Write the task
    The system that takes an input and produces an output.
    
    import braintrust
    
    project = braintrust.projects.create(name="SupportChatbot_Demo")
    
    prompt_v2 = project.prompts.create(
        name="Brand Support V2",
        slug="brand-support-v2",
        description="Brand-aligned support prompt with proper tone guidelines",
        model="gpt-4o",
        messages=[
            {
                "role": "system",
                "content": "You're a cheerful, proactive assistant for Sunshine Co. Always use a positive tone, apologize for issues with empathy, and offer clear solutions to delight customers! No emojis or profanity."
            },
            {"role": "user", "content": "{{{input}}}"}
        ],
        if_exists="replace"
    )
    
    Interface text:
    de.mdx
    run_eval.py
    prompt_v2.py
    Users > jess > Documents > Coding Projects > Work (Braintrust)
  13. 3:43

    Then the next thing you need to do is you n-need to write a scoring system that will tell you whether the AI's output is good or bad. Um, and so usually it's, uh, maybe the PM or engineer that is writing the criteria that comprises that goodness and badness. Uh, and you might have heard of terms like, uh, deterministic scoring, LLM as a judge, human-in-the-loop. Those are different types of scoring, um, frameworks. Uh, but yeah, that's-- So you write your scoring system. And then the last thing you do, which is the most fun part of writing evals, is

  14. 4:13

    you experiment. So every configuration of a specific dataset, a specific task, and a specific scoring system equals to one experiment. And as you are testing out different hypothesis for how to make your system better, you're tweaking either your dataset, your task, or your scoring system, and these all lead to different experiments. So once you have your different experiments, then you start to compare them. So you might run experiment one and experiment two, and you can see whether there's

  15. Compare experiments

    Compare Vector Search and Agent Search side by side: green and red indicators show improvements and regressions, while individual rows reveal which test cases changed.

    Text in image
    Compare experiments
    
    1) Pick any two experiments to compare (here: Vector Search vs Agent Search)
    2) Green/red indicators showing what improved or regressed
    3) Drill into individual rows to see exactly which test cases changed
    
    Interface text:
    Vector Search - [illegible]
    Comparisons
    Agent Search - [illegible]
    Prompt
    None
    Dataset
    Rows not attached to a dataset
    Scorers and distribution
    agent_success
    fix_applied
    test_passed
    vector_search_used
    Scale: 0%, 50%, 100%
    Metadata
    YAML
    {}
    
    Experiments
    Diff
    Review
    Share
    Default view
    Reset
    Save as
    Filter
    Display
    
    agent_success: 100% AVG; 100%
    fix_applied: 93.1% AVG, ↗5 ↘2; 79.31% +14%, ↗5 ↘2
    test_passed: 82.76% AVG, ↗2 ↘3; 86.21% -3%, ↗2 ↘3
    Duration: 5,180.9s SUM; 3,282.47s [illegible]
    
    Visible rows (agent_success | fix_applied | test_passed | Duration):
    100% / 100.0% | 0% / 100.0% -100.0% | 0% / 100.0% -100.0% | 91s / 44.6s
    100% / 100.0% | 0% / 100.0% -100.0% | 100% / 100.0% | 373.5s / 219.9s
    100% / 100.0% | 100% / 100.0% | 0% / 0.0% | 288.1s / 173.8s
    100% / 100.0% | 100% / 0.0% +100.0% | 0% / 100.0% -100.0% | 136.7s / 135.7s
    100% / 100.0% | 100% / 100.0% | 0% / 0.0% | 25s / 20.5s
    100% / 100.0% | 100% / 100.0% | 0% / 100.0% -100.0% | 195.7s / 154.8s
    100% / — | 100% / — | 100% / — | 157.3s / —
    100% / 100.0% | 100% / 0.0% +100.0% | 100% / 100.0% | 238.3s / 191s
    100% / 100.0% | 100% / 100.0% | 100% / 100.0% | 278.4s / 135.2s
    100% / 100.0% | 100% / 100.0% | 100% / 100.0% | 93.2s / 84.5s
  16. 4:43

    been improvements or regressions. And you can also, uh, click into specific rows to see exactly which test cases have changed. Uh, this screenshot is from the Braintrust UI. Another thing that you can do is you can use, uh, natural language to query across your traces and experiments. Um, so for example, you can ask it things like, "Summarize my experiments for me. Um, highlight the problems in these experiments." Um, I find this especially useful when you're running experiment-- or you're running, like, um,

  17. Use Loop

    Loop accepts natural-language questions about traces and experiments. The example analysis flags repetitive apologies, overly accommodating responses, and mishandled edge cases.

    Text in image
    Use Loop
    
    Turn insights into improvements with Loop
    Start a conversation to get detailed breakdowns and insights about your experiments.
    
    Summarize experiments
    Highlight problems in these experiments
    Which experiment performed the best?
    
    Find the biggest problems in these experiments
    
    2. Over-Apologizing Pattern
    
    Every single response starts with "I sincerely apologize" regardless of context. This creates several problems:
    
    • Inappropriate for gibberish: Apologizing to "blooby blooby doo-badoo" makes the brand look foolish
    • Sounds insincere: Constant "I sincerely apologize" becomes robotic and loses authenticity
    • No tone variation: Same response pattern whether dealing with confusion, anger, or unreasonable requests
    
    3. Too Accommodating on Unreasonable Requests
    
    The model offers to "consult with our team" and "see what we can do" even when requests clearly violate policy:
    
    • Broken camera refund request: Offers to investigate despite policy requiring original condition (see human feedback noting this is wrong)
    • Returning one shoe from a pair: Should be a firmer "no" but gets a soft decline
    
    4. Doesn't Handle Edge Cases Appropriately
    
    • Gibberish: Should ask for clarification or indicate confusion, not apologize profusely
    • Vague inputs: Doesn't recognize when input is too minimal to be actionable
    • Abuse: When told "You should go bankrupt," still maintains excessive politeness without setting appropriate boundaries
    
    Interface text:
    Ask about experiments, @ for context, / for commands
    Claude 4.5 Sonnet
    Loop
  18. 5:13

    tra-- you see traces with, like, long multi-turn conversations. It's good for, um, helping you catch things like hallucination or drift that's kind of hard to catch manually. Um, you can also-- If you're running different experiments, you can ask it, like, which performance or which experiments performed the best of, out of all of these experiments. Um, so this is another way you can, like, find patterns in your traces. Um, we also-- This is using, like, the UI in Braintrust, but we also have a CLI and an MCP

  19. 5:43

    server if you prefer to do it that way as well. Um, and then the last pillar of Braintrust is just, like, regular observability. So you can basically use the Braintrust SDK to wrap your code, um, and then, uh, have your production logs show up in Braintrust and essentially do traditional observability, where you can monitor your production logs and create dashboards and things like that. Um, so kind of to tie this together, I'm gonna walk you through kind of a flow of how you might use observability and

  20. Log

    Braintrust’s SDK can capture production logs for monitoring; the slide shows a trace alongside an option to add data to a dataset for the eval feedback loop.

    Text in image
    Log
    
    Incorporate real-world data into your eval feedback loop.
    
    Interface text:
    All rows
    Columns
    Filter
    Row height
    Name
    Input
    Output
    Expected
    Trace
    Span
    Add to dataset
    handleRequest
    getCommits
    generate-changelog
    Start
    Offset
    Duration
    Input
    YAML
    [illegible]
    commits:
      - |
        Update 3-add-style.md
      - |
        Update 3-add-style.md
      - |
        Update 4-creating-website.md
      - |
        fix typo
      - |
        Update README.md
      - |
        update link
    [illegible]
  21. Evaluation feedback loop

    Production logs become datasets for evals. Results guide changes to the app, which generate new logs and repeat the cycle.

    Text in image
    App
    App code and prompts
    
    Logs
    Real-world LLM inputs and outputs
    
    Datasets
    Data filtered using tags, metadata, and human review
    
    Evals
    Tasks, data, and scoring functions are used to evaluate performance
    
    Results inform tweaks to app
  22. 6:13

    evals to improve your AI system. So we're gonna start on the top left corner where it says app. So imagine you have some sort of AI application. Uh, in this scenario, I'll say you have a, a new docs page that you just shipped with like an AI chatbot built in so that users can ask questions to your AI chat-chatbot about your documentation. So let's say you shipped that yesterday, and then you have customers start to use your AI chatbot. So when they start to hit your AI chatbot, you're gonna start to

  23. 6:43

    get real production logs coming into your system. Once you get those production logs, you can, uh, sample a subset of them, maybe like ten to twenty rows or something, and create a kind of dataset. Uh, once you get that dataset, then we can run evals on that, right? So you can... You have your dataset, you can write your task, you can write your scoring system, and you can run, uh, evals on them. And you can start to tweak your dataset, you can start to tweak your prompt or s- tweak your score and run multiple different evals on that. Once you have your

  24. 7:13

    evals, like run a couple different evals, um, and start to see which eval does the best, you might learn something about your system, and then you're gonna go ahead and make your code change or make a change to whatever AI system that you're using, uh, and then deploy that back into your application. And then the whole flow repeats again because, uh, those changes will show up in your production logs and the whole system happens again. So that's kind of how the flow works as a whole. Um, the last slide I'll show before I get into a

  25. Evals are a team sport

    AI engineers bring in data and make advanced changes; product managers define success and tweak prompts. Subject matter experts label data, while data analysts develop scorers and analyze results.

    Text in image
    Evals are a team sport
    
    AI engineer
    Product manager
    Subject matter experts
    Data analysts
    
    Get real world data into your eval platform
    Label sample data
    Develop hypotheses
    Decide on success criteria
    Tweak simpler tasks such as prompt
    Tweak advanced tasks such as tool call
    Develop scorers
    Analyze results
  26. 7:42

    concrete example is... I love this slide because, uh, conceptually, I, I wanna hammer into people that evals are a team sport. Uh, there's so much that goes into creating evals, uh, from getting real world data into your platform, labeling it, developing hypothesis, things like that. So the AI engineer kind of works on obviously making the code changes, but also getting the data into the platform. Uh, the product manager is very important. I think they're, they usually spearhead evals at a company, but they're the ones that develop the

  27. 8:12

    hypothesis of what success looks like, um, and help, uh, tweak, tweak the prompts and things like that. Uh, subject matter experts are really important, especially in like more niche, uh, areas like, um, insurance, medicine, law, and things like that. Um, they can help, uh, label the data or provide a ground truth for what, what excellence looks like. Uh, and then data analysts obviously to analyze the data. So I always think that this slide is, is really useful to look at. Okay. So let's

  28. Agentic Search vs Vector Search?

    The speaker introduces an eval comparing agentic search with vector search.

    Text in image
    Agentic Search vs Vector Search?
  29. 8:42

    go into a like interesting real world example of how you might use an eval. Um, in this one, I'm comparing agentic search to vector search. And the story behind this specific eval is, um, is that my CEO, Ankur, sometimes goes on Twitter and sends me articles of things he wants me to eval. Uh, so he sent me this, uh, tweet from Cursor, where Cursor talks about how they used semantic search, also known as agentic search, um, to significantly improve their coding

  30. The Search Debate

    Cursor says semantic search improves coding agents, while Boris Cherny and Kyle Corbitt favor agentic search. The competing claims prompted an evaluation.

    Text in image
    Cursor
    @cursor_ai
    
    Semantic search significantly improves coding agent performance.
    
    For very large codebases, Cursor's indexing process is now several orders of magnitude faster.
    
    Securely indexing large codebases - Cursor
    From cursor.com
    9:30 AM · Jan 27, 2026 · 254.3K Views
    
    Ethan Lipnik @EthanLipnik · Jan 31
    Does anyone know why Codex and Claude doesn't use cloud-based embeddings like Cursor to quickly search through the codebase?
    
    Boris Cherny @bcherny · 1h
    👋 Early versions of Claude Code used RAG + a local vector db, but we found pretty quickly that agentic search generally works better. It is also simpler and doesn't have the same issues around security, privacy, staleness, and reliability.
    
    Kyle Corbitt
    @corbtt
    Agentic RAG works better than semantic search RAG and it's not even close. Will post results soon.
    
    3:40 PM · May 7, 2025 · 136.6K Views
    
    Interface text:
    Ethan Lipnik post: 43, 1, 189, 51K
    Boris Cherny post: 25, 14, 384, 10K
    Kyle Corbitt post: 41, 29, 801, 681
    Relevant
    View quotes
  31. 9:12

    agent ex-- uh, performance. And he was like, "Jess, can you eval this for me?" And I was like, "Okay. I'm busy, but okay." Um, and so I kinda went on Twitter and I saw that there was a lot of, uh, discourse or discussion around this topic, so I thought it might be interesting to eval. So, uh, we're gonna eval a vector search and agentic search, so I just wanna give a quick, uh, summary of what each one is just so everyone's on the same page. So vector search essentially is the process of taking, uh, data like, uh, code or

  32. What Is Vector Search?

    Vector search embeds code chunks as numbers and returns the top N closest matches to a query. The plot illustrates semantic proximity: wolf, dog and cat cluster together, apart from apple and banana.

    Text in image
    What is vector search?
    
    1. Embed code chunks into vectors (numbers)
    2. Given a query, find chunks with similar embeddings
    3. Returns top N "semantically similar" chunks
    
    Plot labels: Wolf, Dog, Cat, Banana, Apple
  33. 9:42

    text and turning them into embeddings, where embeddings basically represent the semantic meaning of that chunk of text or code. So, uh, if you look at the graph here, it's a very good visual example where, um, the embeddings, uh, wolf, dog, and cat are very close to each other 'cause semantically they all are animals. And then, uh, the embeddings banana and apple are also close to each other 'cause they're fruit, but then, uh, they're far apart from each other because fruit and animals are different things. Um, and so what happens

  34. 10:12

    is in, you know, um, in a real vector search implementation, you would take these embeddings, uh, and store them in a vector database, so something like Qdrant or Pinecone or something like that. And if you come up with a query like, uh, for example, where does the database logic in my code base live? Uh, what would happen is the vector database would return back the chunks of, um, embeddings that most closely semantically match the words in your query. So the, the chunks that are closest to things

  35. 10:42

    like database or logic. So that's how vector search works. Agentic search is slightly different. Agentic search works more like a human would. So essentially with agentic search, uh, you give an LLM tools like, uh, grep, find, ls, cat, um, bash commands, and it basically explores, explores your code base like a human would. So it would, uh, look up a function name, open a file, read the file, follow that function call to another file, and then open that file and read that file, and then continue

  36. What Is Agentic Search?

    An LLM explores a codebase with tools, reading files and following function calls until it has enough evidence. The diagram illustrates a loop using semantic search, graph queries and node context.

    Text in image
    What is agentic search?
    
    1. LLM uses traditional dev tools: grep, find, ls, cat
    2. Iteratively explores like a human developer
    3. Reads code, follows references, builds understanding
    4. Claude Code's approach
    
    AGENTIC RETRIEVAL LOOP
    
    User Question
    LLM Agent
    SemanticSearch(query)
    GraphQuery(filter)
    Contextualize(node)
    Sufficient evidence?
    No
    Yes (or Max Steps/Full)
    Generate Answer
    
    Example Iteration:
    Question: “What controls address encryption?”
    → Step 1: SemanticSearch('encryption controls') → [5 results]
    → Step 2: Contextualize(node[23]) → [expands to 12 related nodes]
    → Step 3: Agent marks 8 as relevant → Done
  37. 11:12

    until it's found what it's ne- what it needs to. So this is, uh, much more similar to how a human would kind of go through a code base and, and look up-- look for certain pieces of logic. Okay. So then how did we eval this? So the first part of creating eval is creating your dataset, right? So to do this, we basically used, uh, Microsoft's TypeScript Go repo, uh, which is open source. And what we did is we basically found all the PRs, um, the merged PRs with the title fix in

  38. Which One Works Better?

    The talk turns to evaluating which works better for coding agents: agentic search or vector search.

    Text in image
    Which one works better?
  39. Experiment Design Overview: Dataset

    The team used roughly 20 merged PRs from Microsoft’s TypeScript Go repo. Claude turned each fix’s diff into a bug task, then an LLM used RAG or agentic search to find the bug in the parent commit.

    Text in image
    Experiment Design Overview: Dataset
    
    1. Found PR’s with word “fix”
    2. Checkout out parent commit, aka “buggy” state
    3. Generated a bug task based on diff
    4. Fed that task into LLM to fix (using either RAG or Agentic search to find the buggy code)
  40. 11:42

    them. And, uh, we basically checked out the parent commit. So essentially we checked out the commit to the point where it still has the bug in it. And then we used Claude to generate a, like a bug task or like a linear task based on the diff, so based on the diff between the buggy code and the fixed code. And then we fed that into an LLM, uh, and had that LLM either use RAG search or agentic search to find the buggy code, to locate where the logic, the buggy logic lives.

  41. 12:12

    So that's how we created our dataset. We had like maybe We, we found like 20 different PRs, um, and, and ran the eval on that. Uh, in terms of our task, uh, we actually had to implement vector search and agentic search obviously. Uh, implementing agentic search was really easy because Claude Code uses agentic search by default, so we just set Claude Code on these tasks. Um, implementing vector search was slightly more complicated because we still wanted to use the Claude Code

  42. 12:42

    harness, um, to execute the vector search just to keep the experiment consistent, but we had to basically prevent, uh, Claude Code from defaulting to agentic search. So we did two things. Uh, the first thing is that we explicitly said in the prompt instructions not to use agentic search. Um, but if you've ever done this before, you know that prompting is never enough. So what we also had to do is use the, uh, disallowed tools flag to prevent, uh, Claude Code from calling certain things, uh, that it would normally use in agentic search.

  43. 13:12

    So that's how we implemented, uh, vector search and agentic search, both using the Claude Code harness. Um, another kind of interesting thing that we ran into is, um, when we were trace, uh, running the traces, we ran the Claude Code, uh, runs as subprocesses, but it essentially mean, meant that the traces were orphaned. Um, and, uh, our solution was basically passing the parent span IDs as environment variables. So if that doesn't make sense, that's fine because I'll show

  44. Tracing Setup: Before

    The original trace shows the Claude subprocess running but hides its internal calls. Passing parent span IDs through environment variables nests those calls in the experiment trace.

    Text in image
    Tracing Setup
    
    Problem: Claude Code runs as subprocess, traces are orphaned
    Solution: Pass parent span IDs via environment variables
    Result: Full visibility into every tool call, nested in our experiment
    
    Interface text:
    Trace  Timeline  Thread  Views
    Trace tree  + Dataset  Flag for review  Tag
    
    eval  29.14s
    task  29.13s
    traced_eval  29.13s
    reset_repo  1.26s
    run_claude_agent  27.04s
    apply_test_files  0s
    run_tests  0.77s
    check_fix_applied  0.05s
    test_passed  100%, 0s
    fix_applied  100%, 0s
    agent_success  100%, 0s
    
    replaceAll  false
    type  assistant
    message
    model  claude-sonnet-4-5-20250929
    id  [illegible]
    type  message
    role  assistant
    content
      type  text
      text  Perfect! I've fixed the bug by adding a nil check before accessing the `ImportClause()` properties. The fix follows the same pattern already used elsewhere in the same file (line 5139).
    
    Summary
    Fixed: Language server crash when requesting completions after invalid import statements like `import super` or `import this`.
    Root Cause: At line 5110 in `internal/ls/completions.go`, the code called `candidate.ImportClause().IsTypeOnly()` without checking if `ImportClause()` returns nil. When the parser encounters invalid import statements, it creates an ImportDeclaration node with a nil ImportClause, causing a nil pointer dereference. Solution: Added a nil check before accessing ImportClause properties:
  45. 13:42

    you via pictures. So this picture that you see here is what the trace looks like when it's running as a orphaned subprocess. So you can see in the highlighted on like the left panel where it says, "Run Claude Agent," um, that's basically in the trace saying, "Okay, it's running the Claude subprocess," but you can't... You don't actually get any visibility into what happens when it's running that Claude process. With the fix that we did, uh, this is what you see now in the trace. So you can see that it's, uh,

  46. Tracing Setup: After

    Passing parent span IDs through environment variables nests Claude Code’s subprocess traces inside the experiment, exposing its turns, model calls, and tool commands for debugging.

    Text in image
    Tracing Setup
    
    Problem: Claude Code runs as subprocess, traces are orphaned
    
    Solution: Pass parent span IDs via environment variables
    
    Result: Full visibility into every tool call, nested in our experiment
    
    Interface text:
    Trace · Timeline · Thread · Views
    Dataset · Run · Flag for review · Tag
    
    Trace tree:
    run_tests
    check_fix_applied
    check_fail_to_pass
    Claude Code: dj...
    Turn 1
    AI: claude-son...
    Terminal: find /...
    Glob
    AI: claude-son...
    AI: claude-son...
    Read: autodete...
    AI: claude-son...
    Grep
    AI: claude-son...
    Terminal: find /...
    AI: claude-son...
    Grep
    
    Assistant
    I'll analyze this bug and fix it. The issue is that when renaming a primary key field, Django's migration autodetector generates a migration that includes an `AlterField` operation for the ForeignKey that still references the old field name in the `to_field` parameter.
    
    Let me first explore the codebase to understand how migrations are generated.
    
    Bash
    Tool
    Output
    LLM
    Assistant
    Glob
    Expected
    YAML
    null
    Metadata
    Pretty
  47. 14:12

    calling the Claude Code subprocess, but you can also see everything that's being run in that subprocess. So you can see all the turns, all the LLM calls, uh, every single terminal command that's being called, like grep, bash, ls, find, things like that. Uh, and it gives you visibility into what's happening in this actual run. Uh, and implementing this fix was really important because being able to have transparency into what's happening, um, is, is important for debugging, uh, later on. And scoring was really simple. Uh,

  48. Tracing Setup: After

    Passing parent span IDs through environment variables nests Claude Code’s subprocess traces inside the experiment, exposing its turns, model calls, and tool commands for debugging.

    Text in image
    Tracing Setup
    
    Problem: Claude Code runs as subprocess, traces are orphaned
    
    Solution: Pass parent span IDs via environment variables
    
    Result: Full visibility into every tool call, nested in our experiment
    
    Interface text:
    Trace · Timeline · Thread · Views
    Dataset · Run · Flag for review · Tag
    
    Trace tree:
    run_tests
    check_fix_applied
    check_fail_to_pass
    Claude Code: dj...
    Turn 1
    AI: claude-son...
    Terminal: find /...
    Glob
    AI: claude-son...
    AI: claude-son...
    Read: autodete...
    AI: claude-son...
    Grep
    AI: claude-son...
    Terminal: find /...
    AI: claude-son...
    Grep
    
    Assistant
    I'll analyze this bug and fix it. The issue is that when renaming a primary key field, Django's migration autodetector generates a migration that includes an `AlterField` operation for the ForeignKey that still references the old field name in the `to_field` parameter.
    
    Let me first explore the codebase to understand how migrations are generated.
    
    Bash
    Tool
    Output
    LLM
    Assistant
    Glob
    Expected
    YAML
    null
    Metadata
    Pretty
  49. Scoring

    The evaluation used binary test-pass scoring: 100% if the Microsoft TypeScript Go test suite passed, 0% if it failed. It also tracked duration, total tokens, and cost.

    Text in image
    Scoring
    
    Scores
    • test_passed: Did the test pass?
    
    Metrics
    • Duration, total tokens, cost
    
    Interface text:
    Trace tree
    Score span
    
    eval
     task
      traced_eval
       reset_repo
       run_claude_agent
       apply_test_files
       run_tests
       check_fix_applied
       test_passed — 100%, 0s
       fix_applied — 100%, 0s
       agent_success — 100%, 0s
    
    test_passed
    + Dataset
    Flag for review
    
    Metrics
    Start: Yesterday 11:12:20 PM
    Duration: 0.0007s
    Offset: 29.1351s
    
    Scores
    test_passed
    100%
    
    Input
    Pretty
    expected (1)
    test_passed
  50. 14:42

    for our scoring, we basically said, uh, because we're using Microsoft- Microsoft's TypeScript Go repo, we basically said if the test, uh, passed the, uh, t- uh, Microsoft TypeScript Go test suite, then it gets 100%, and if it fails, it gets a 0%. So it was very binary scoring here. Uh, okay, so in terms of our results, uh, the summary is basically vector search and agen- agentic search both got the same level of accuracy, but essentially vector search cost, uh, four

  51. Results

    On 10 ts-go rows, both methods reached 70% accuracy. Vector search averaged 2.9M tokens and $4.40, versus 946k tokens and $1.58 for agentic search.

    Text in image
    Results
    
    Ts-go (10 rows)
    
    Accuracy | Avg tokens | Avg cost
    Vector | 70% | 2.9M | $4.40
    Agentic | 70% | 946k | $1.58
  52. 15:12

    times more than agentic search. So when we looked at the actual traces and, uh, kind of manually like went through to try to understand what happened, we had a couple of learnings. So the first thing is that vector search, uh, returns back chunks of code, but these chunks of code often miss things like, um, imports or tool calls or the calling code above it. Um, and so as a result, it's not enough. It doesn't give enough context for how the agent should actually solve the bug. Uh, so one example is in

  53. Takeaways

    In pr-2532, agentic search traced callers to a targeted fix; in django-11910, 26 vector searches missed how three functions interact. Across ts-go tasks, vector used 3.1x more tokens and cost 2.8x more per task.

    Text in image
    Takeaways
    
    • Vector search returns chunks, not files.
    The agent gets fragments without surrounding context. In django-11910, the vector agent made 26 searches and still couldn't piece together how three functions interact across file.
    
    • Agentic search enables chain-of-thought exploration.
    In pr-2532 (ts-go), the agentic agent worked like a developer: grepped for the function name, read the full function, spotted a flaw in the cycle detection logic, then followed callers to confirm its theory before applying a targeted fix.
    
    • More searches ≠ better results.
    Across ts-go tasks, vector used 2.8x more LLM calls, 3.1x more tokens, and cost 2.8x more per task — while performing the same or worse.
  54. 15:42

    one of the rows, we saw that the vector agent made 26 searches and still couldn't piece together how three functions interacted across the file. In contrast, agentic search was actually able to like, as I said, work more like a human would. So grep the function name, read the full function, uh, spot the flaw in the logic, and then follow the calling, um, calling logic, uh, into another file. Um, and the way that I kind of like to think about it when I was just going through the traces is it felt like,

  55. 16:12

    um, vector search gave a lot of proximity to the correct code, but agentic search had more of the connective tissue to connect the actual logic of those chunks of code. Uh, and then tying that into the third learning I had is, um, the reason why vector search was so much more expensive than agentic search is because it made more, um, searches. 'Cause it was o- um, c- constantly searching, like returning a chunk of code and then searching again, returning a chunk of code, searching again. And as a result, um, all

  56. 16:42

    of those LLM calls, uh, piled up and made it a lot more expensive, uh, to execute. Um, and this is the last slide, but essentially, uh, you might be sitting here thinking, "Oh, there's so many holes in this eval," which is very fair. Like, there's lots of things I could've done. Uh, I, uh, you know, there's lots of best practices when it comes to running evals, like running multiple trials per task. Uh, especially because LLMs are so non-deterministic, it's good to run multiple trials to be able to trust the score that you're getting back a lot

  57. How to improve eval

    The speaker proposes multiple trials to make scores more trustworthy, a stronger vector search implementation, and a larger dataset. The eval covered roughly 20 rows.

    Text in image
    How to improve eval
    
    • Run multiple trials per task
    • Improve vector search implementation
    • Expand the dataset
  58. 17:12

    better. Um, my vector search implementation was relatively weak. Uh, I could've done a better implementation. Um, also expanding the data set. Um, I think we only ran this on like 20 different rows, so it would've been better to expand this, uh, to even different, um, different repos or things like that. Um, but the, the point of this talk is not to create the best, uh, off- like the best eval ever, but it's more to illustrate to you the concept of h- the kinda how to create a eval end to end.

  59. 17:42

    So hopefully I've done that, um, and that is the end of my talk. Um, so hopefully you learned a little bit of what evals are, why they're important, and how you might do one in real life. Um, and yeah, I think that's it. So thank you for listening.

  60. Questions?

    The speaker closes the talk and opens the floor for questions.

    Text in image
    Questions?