Skip to content

Instantly share code, notes, and snippets.

@laisbsc
Last active September 1, 2026 13:27
Show Gist options
  • Select an option

  • Save laisbsc/47426a4445eb963aec38ab9052917167 to your computer and use it in GitHub Desktop.

Select an option

Save laisbsc/47426a4445eb963aec38ab9052917167 to your computer and use it in GitHub Desktop.
Lean vs thorough You.com retrieval in a Pydantic AI agent, traced with Logfire
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "pydantic-ai-harness[youdotcom,anthropic]>=0.27.0",
# "pydantic-ai-slim[logfire]>=2.36.0",
# ]
# ///
"""Two agents, one question, very different bills.
Both agents answer the same question and return the same two fields. The lean
one surveys excerpts and stops. The thorough one reads full pages, keeps a
second search scoped to trusted domains, and sends the write-up through
You.com's research pass with a schema attached. Both runs nest under one Logfire
span, so the token counts sit side by side in a single trace.
Across five paired runs the thorough agent used a median 65,987 input tokens
against the lean agent's 7,937, and the `research` call alone was 62% of its
wall time.
Run it:
export YDC_API_KEY='...'
export PYDANTIC_AI_GATEWAY_API_KEY='...' # or ANTHROPIC_API_KEY, see MODEL
uv run youdotcom_demo.py
`uv run` reads the dependency block above, so this file needs no project around
it. The first run also prompts you to authenticate with Logfire.
"""
import logfire
from pydantic import BaseModel, ConfigDict, Field
from pydantic_ai import Agent
from pydantic_ai.capabilities import PrefixTools
from pydantic_ai.messages import ToolReturnPart
from pydantic_ai_harness import YouResearch, YouSearch
logfire.configure(service_name='youdotcom-tuning-demo')
logfire.instrument_pydantic_ai()
# Drop the `gateway/` prefix and set ANTHROPIC_API_KEY to call the provider
# directly. The prefix and the key have to change together.
MODEL = 'gateway/anthropic:claude-sonnet-5'
QUESTION = 'What is the latest price of silver per troy ounce?'
class SilverBrief(BaseModel):
"""The shape both runs have to produce.
`extra='forbid'` is what puts `additionalProperties: false` in the generated
JSON schema. You.com rejects a research `output_schema` without it.
"""
model_config = ConfigDict(extra='forbid')
spot_price_usd_per_oz: float
as_of: str = Field(description='The date and source the quoted price is from.')
def print_sources(result) -> None:
"""Citations come back as data, so the UI never parses them out of prose."""
seen: set[str] = set()
for message in result.all_messages():
for part in message.parts:
if isinstance(part, ToolReturnPart) and part.metadata:
for source in part.metadata.get('sources', []):
url = source['url']
if url not in seen:
seen.add(url)
print(f' {source["title"]}\n {url}')
# The lean setup: excerpts only, three results, a hard cap on any page it reads.
# num_results=3 and max_text_chars=2_000 put a 6,000 character ceiling on
# everything this agent can see in a call, whatever the question is.
lean_agent = Agent(
MODEL,
instructions='Answer with the spot price and its date only. Do not explain what moved it.',
output_type=SilverBrief,
capabilities=[
YouSearch(
num_results=3,
extraction_mode='highlights',
max_text_chars=2_000,
freshness='week',
)
],
)
# The thorough setup: full page markdown, a wider survey, a second search that
# only ever returns the two domains this desk trusts, and a research pass that
# must come back in the shape of SilverBrief.
#
# The instructions are what make `research` run. With softer wording the model
# skipped it on some runs and the whole agent cost 12,377 input tokens, close to
# the lean one. `research_effort` only sets how long the pass runs once it does.
thorough_agent = Agent(
MODEL,
instructions=(
'You must call `research` exactly once and base the brief on what it '
'returns; do not answer from search results alone. Use '
'`trusted_web_search` only to confirm the number you quote as the spot '
'price, and `web_search` to survey context before the research pass.'
),
output_type=SilverBrief,
capabilities=[
YouSearch(
num_results=8,
extraction_mode='full_page',
max_text_chars=20_000,
freshness='week',
),
PrefixTools(
wrapped=YouSearch(
num_results=3,
include_domains=['lbma.org.uk', 'kitco.com'],
guidance='',
),
prefix='trusted',
),
YouResearch(
research_effort='deep',
output_schema=SilverBrief.model_json_schema(),
),
],
)
def main() -> None:
# One parent span, so both runs land in a single trace and the token counts
# sit next to each other in one view.
with logfire.span('silver brief: lean vs thorough'):
with logfire.span('lean: highlights only') as lean_span:
lean = lean_agent.run_sync(QUESTION)
lean_span.set_attribute('input_tokens', lean.usage.input_tokens)
lean_span.set_attribute('output_tokens', lean.usage.output_tokens)
print(f'LEAN: ${lean.output.spot_price_usd_per_oz:.2f}/oz as of {lean.output.as_of}')
print(' sources:')
print_sources(lean)
print(' usage:', lean.usage, '\n')
with logfire.span('thorough: full pages and a research pass') as thorough_span:
thorough = thorough_agent.run_sync(QUESTION)
thorough_span.set_attribute('input_tokens', thorough.usage.input_tokens)
thorough_span.set_attribute('output_tokens', thorough.usage.output_tokens)
print('THOROUGH\n', thorough.output.model_dump_json(indent=2), sep='')
print(' sources:')
print_sources(thorough)
print(' usage:', thorough.usage)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment