Skip to main content
A coding agent can know Pydantic well and still suggest a migration that no longer matches the current documentation. The edit may look right until a test reaches an API that changed between releases. This cookbook turns migration research into a small Python program. It runs five focused searches, limits results to official documentation, extracts relevant passages, and writes one Markdown file for your coding agent. You can rerun the same search plan when the target version changes instead of relying on a browser transcript or copied links. Search as Code is useful when search is a stage in a program. Your code controls the queries, source policy, result limits, failure handling, and output format. The web results stay current, while the process stays reviewable.
The script collects migration evidence. It does not prove that a migration is correct or complete. Your coding agent still needs to inspect your repository and run its tests.

Choose the Perplexity product

This example uses the Search SDK because another program will consume the result.

Set up

You need Python 3.12 and a Perplexity API key. The commands below assume Bash on macOS or Linux.
Keep the key in your environment. Do not put it in your input file, agent context, prompt, or repository.

Describe the upgrade

Save this as upgrade.json:
The target version appears in every query. The code signals tell your agent which repository APIs may need attention.

Build the evidence collector

Save this as upgrade_research.py:

How the collector works

The collector separates search from the decisions your coding agent will make later. Build the query plan. TOPICS defines five independent migration questions and the official documentation host allowed for each one. research combines each topic with the target version from upgrade.json. Changing the target version changes every query without changing the rest of the pipeline. Run the searches together. search.web_many sends the five requests with a concurrency limit of three. Each result has its own success or failure state, so one failed query does not erase the other results. The script keeps at most two HTTPS results from the exact host assigned to that topic. Extract focused passages. Search results help you find pages. content.snippets takes the selected URLs and returns passages relevant to the original query. Mapping results by URL keeps each passage attached to its page even if the order changes. A failed snippets call records a gap for that topic and continues. An errored or empty result affects only its URL. Write the handoff. render groups the passages by topic and records missing evidence under Retrieval gaps. Every usable item keeps its query, title, URL, and passage. The script writes the file before checking coverage, then exits with status 1 when any topic lacks evidence. You can inspect the gaps, while CI or another agent can stop before treating the file as complete. The Search SDK handles discovery and passage extraction. Your code owns the query plan, domain policy, result limits, failure policy, and output contract.
The command writes agent-context.md. It exits with status 0 when every topic has evidence and status 1 when one or more topics have no usable evidence. A missing API key or another top-level error stops the run without leaving an older context file in place. Live results vary as documentation and search results change. Review the generated URLs and passages before using them.

Give the context to your coding agent

Reference agent-context.md from the AI coding tool you already use:
Your repository tells the agent what your application does. The generated file tells it what the selected official documentation currently says. Keeping those inputs separate lets you refresh the research without changing application code.

Why put search in code?

Interactive browsing works for a one-off question. Search as Code fits work you need to repeat, inspect, or feed into another program. In this example, the query plan, allowed domains, concurrency, result limits, passage budget, gaps, and output format are all visible in Python. Rerun the script when the target version changes and hand the refreshed artifact to the next stage. See the Search SDK overview for the full API.