A research agent, three ways Pydantic AI's research agent can be built in three ways: a ten-line agent using native web search for simple lookups, a production-grade agent powered by Exa's semantic search API that returns page contents in one call, and a hosted Exa Agent API that runs multi-step research passes with structured outputs. Exa's search API already powers Cursor and Devin, making it the retrieval backbone for agents that need deep research capabilities. Midweek, with an agent that writes code and gets it reviewed, someone asks a different kind of question: "before we commit to the migration, can it research the vendor options?" And the reflex says no, wrong agent. The reflex is thinking in agents. This week is about thinking in parts. The basic thing you can build Ten lines gets you a working research agent. Pydantic AI's core ships WebSearch https://ai.pydantic.dev/api/capabilities/ , a capability that turns on the model's own native web search — Anthropic, OpenAI, Google, and Groq all have one: python import logfire from pydantic import BaseModel from pydantic ai import Agent from pydantic ai.capabilities import WebSearch logfire.configure logfire.instrument pydantic ai class Finding BaseModel : claim: str source url: str class Report BaseModel : summary: str findings: list Finding agent = Agent 'anthropic:claude-opus-4-7', output type=Report, capabilities= WebSearch allowed domains= 'docs.aws.amazon.com' , result = agent.run sync 'What HA options does RDS for Postgres offer today?' For a factual lookup with a small blast radius, this is enough, and output type=Report means the answer already comes back as validated data. But the ceiling is low: native web search returns links and snippets scored by the provider's index and doesn't give you a page-contents step, deep-research mode, or the kind of retrieval control a research agent needs when the question earns more than a lookup. Which is when the fastest path to a production-grade research agent stops passing through the shelf. The fastest path to production A research agent is only as good as its retrieval, and the retrieval most agents get, scrape ten blue links and hope, is the bottleneck that makes "deep research" shallow. The agents that make their living reading the web have all quietly settled on the same eyes. Exa https://exa.ai 's tagline is the literal spec: "web search, built for AI agents." Semantic search over the live web with page contents returned in the same call, no scraping step, and a range they describe as low-latency to deep research in one API https://exa.ai/docs/reference/search-api-guide : an instant mode for the quick lookups, auto for balanced retrieval, and deep / deep-reasoning for questions that earn a multi-step pass with structured outputs. Coding agents live on that range: Exa powers Cursor's search across docs and repos, and Cognition co-founder Walden Yan is on record that "Exa powers all parts of Devin." https://exa.ai/ If the agent that ships production code trusts Exa for its web-facing brain, the research agent you assemble today can too. Hand the whole thing to Exa The superpower version is one capability. When research is the whole question — plan, sub-searches, page reads, synthesis, citations — Exa runs it as a hosted service, the Exa Agent API https://exa.ai/docs/reference/agent-api-guide , and the harness ships it as a one-line wrapper: python import logfire from pydantic ai import Agent from pydantic ai harness.exa import ExaAgent logfire.configure logfire.instrument pydantic ai agent = Agent 'anthropic:claude-opus-4-7', capabilities= ExaAgent , result = agent.run sync 'Which managed Postgres should we migrate to? Compare pricing, HA, ' 'and migration path from RDS across the main contenders. Cite every claim.' ExaAgent adds one tool, exa agent . The parent hands over the question, the Exa Agent API runs a multi-step research pass on their infrastructure up to an hour if the question earns it , and the tool call defers until the run finishes with a cited answer. Follow-ups keep the run's context via previous run id , so a second question about the shortlisted vendors doesn't restart from zero. Want structured output? Pass a Pydantic model as output schema=Report and the completed run's result is validated on the way back; a mismatch surfaces as a retry instead of silently landing. This is the parts-list punchline for research: the parent agent gets a researcher on staff, context isolation included, and the hundred thousand tokens spent reading sources land on Exa's side of the API call. That's the sub-agent pillar of "deep agents" delivered as a capability import — no assembly required. Compose when the pillars pay off Sometimes you do need to build: sources you allowlist, a citation bar the model has to clear, notes that accumulate across runs, a research process that fits how your team actually works. Then the harness's shelf earns its keep. Same Exa retrieval, exposed as individual tools this time via ExaSearch https://github.com/pydantic/pydantic-ai-harness/tree/main/pydantic ai harness/exa — web search returns each hit with its most relevant excerpts so surveys stay cheap and get page reads a chosen URL in full, both with the research strategy that turns two tools into one shipped inside the capability — plus the harness parts that give a long run its spine: python import logfire from pydantic import BaseModel from pydantic ai import Agent from pydantic ai harness import CodeMode from pydantic ai harness.exa import ExaSearch from pydantic ai backends import ConsoleCapability filesystem from pydantic ai summarization import ContextManagerCapability compaction from pydantic ai todo import TodoCapability planning logfire.configure logfire.instrument pydantic ai class Finding BaseModel : claim: str source url: str class Report BaseModel : summary: str findings: list Finding agent = Agent 'anthropic:claude-opus-4-7', output type=Report, capabilities= CodeMode , TodoCapability , ConsoleCapability , ContextManagerCapability max tokens=180 000 , ExaSearch include deep search=True, include domains= 'docs.aws.amazon.com', 'planetscale.com', 'neon.tech' , , , include deep search=True exposes a third tool, deep search , Exa's multi-step deep mode as a single call for the questions that deserve it, and the capability's guidance grows one sentence to teach the model when to escalate. include domains narrows retrieval to the vendors' own docs — a rule the model can't reword its way around. The todo list keeps a three-hour run pointed at the question, files hold the notes and the draft between compactions, and every claim in the report traces to a URL Exa actually returned. Instrument the whole thing with Logfire https://pydantic.dev/logfire and one trace shows the plan, each sub-search, and the synthesis — which is how you debug a researcher. Why this matters Because it's the week's argument in miniature, told in three lines of imports. Start with what ships. Level up when the ceiling gets in the way. Compose when the shape of the problem needs to be yours. Same agent from Monday all the way down, picking up one capability at each step, always answering to the same public API. That's what a standard library is : the point where "build a research agent" stops meaning "start a project" and starts meaning "compose an afternoon." It also composes forward. When agents build agents /articles/when-agents-build-agents ends on loops that run, learn, and re-arm; a research loop that keeps its notes in files and its plan in todos re-arms with everything it learned yesterday, and Exa is the part that keeps its eyes fresh — live search each cycle, not a crawl that ages. The report you commission next is the worst one it will ever write. Agents Week opened with an argument about herds: you'll run more agents than you can hand-raise. The reason that's survivable is the recomposition you just watched: agents assembled from shared, swappable, inspectable parts are cattle by construction. The bespoke agent, the one built from scratch around a private framework, was always the pet. Getting started pydantic-ai-slim already carries WebSearch , so the native version costs nothing more than the model provider you're already paying. uv add "pydantic-ai-harness exa " puts both ExaAgent and ExaSearch on the shelf, and an Exa API key https://dashboard.exa.ai in EXA API KEY connects them — the free credits cover all three agents in this post. Layer in codemode and the community packages pydantic-ai-backend , summarization-pydantic-ai , pydantic-ai-todo when you're ready to compose the deeper build. The capability matrix https://github.com/pydantic/pydantic-ai-harness capability-matrix tracks the rest of the parts list, first-party and community, and every row is an issue or PR where your vote steers what gets built next. A research agent for the cost of an import — a lookup, a hosted researcher, or an afternoon spent composing the loop you actually want. The rest of the week is the same move on harder ground: real compute Thursday, then a cloud the agent is allowed to break Friday.