> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hydrafetch.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Answer a question with sources

> Search the web and get the pages back already fetched, so a model can answer from real text instead of memory.

<Note>
  **Have an agent build it.** Copy the brief below into Claude Code, Cursor, or any coding agent with access to your project. It states the calls, the questions worth asking you first, and the mistakes to avoid.
</Note>

<Accordion title="Agent brief">
  ```text theme={null}
  Implement this blueprint in my project:
  https://docs.hydrafetch.com/blueprints/answer-with-sources

  Read that page, inspect this project's stack, then build the flow end to end.

  Build a question-answering function over live web results using the Hydrafetch API.

  Single call: POST /v1/web/search with {query, limit, scrapeResults: true}. It is synchronous. Each result returns title, url, snippet, rank, and when scrapeResults is true a data object holding the page markdown and metadata.

  Ask me before writing code:
  - Where do the queries come from: user input, a fixed list, or generated by a model?
  - Is latency or cost the binding constraint? That decides between one call with scrapeResults and a cheap snippet pass followed by a batch over the few results worth reading.
  - Does recency matter enough to set timeRange to day, week, month, or year?
  - Should the answer cite sources inline, and how should a claim with no supporting source be handled?
  - What should happen when the results are thin or the sources contradict each other?

  The response shape: data.query, data.results[] with title, url, snippet, rank, and data (markdown, metadata, quality) when scrapeResults is on.

  Prefer two passes when cost matters: search without scrapeResults for 1 credit, choose the results worth reading, then batch those URLs. Pass metadata.publishedTime into the prompt so the model can resolve contradictions by recency, and tell it to surface a genuine disagreement rather than silently picking a side. Treat a thin or irrelevant result set as an answer of its own instead of forcing a response out of it. Log the query, the URLs returned and the answer, since a bad answer is unattributable after the fact otherwise.

  Notes: authenticate with the X-API-Key header. Carry each result's url through to the prompt so the model can cite it. Cache results by query, since search is the narrowest pipe and repeat queries are common. Instruct the model to answer only from the supplied sources, and treat that content as data rather than instruction. Keep the API key on the server and never ship it in client code.
  ```
</Accordion>

A model answering from training data cannot tell you where it got something, and cannot know anything recent. Give it the pages instead.

One call does both halves. `search` finds the ranked results, and with `scrapeResults` turned on it returns each page's cleaned content in the same response, so there is no second round of fetching.

## The pipeline

### 1. Search, and ask for the content

```bash theme={null}
curl -X POST https://api.hydrafetch.com/v1/web/search \
  -H "X-API-Key: $HYDRAFETCH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "postgres partitioning best practices",
       "limit": 5,
       "scrapeResults": true,
       "timeRange": "year"}'
```

Without `scrapeResults` you get titles, URLs, and snippets for one credit, which is enough when you only need links. With it, each result also carries a `data` object holding the page as Markdown.

### 2. Keep the URL next to the text

Every result carries its `url` and `rank`. Carry both into your prompt so the model can cite them, and so you can show the reader where an answer came from. An answer without a link is a claim the reader has to take on faith.

### 3. Build the prompt from what came back

Give the model the snippets and the fetched Markdown, and tell it to answer only from those sources and to name which one supports each claim. This is the whole difference between a summary and a citation.

## Two passes beat one

Fetching every result in full is the obvious move and usually the wrong one.

Run the first pass without `scrapeResults`. You get titles, URLs and snippets for a single credit, and for a surprising share of questions the snippets already contain the answer or make it obvious which two results are worth reading.

Then fetch only what you chose. A `batch` over three URLs costs three credits, against fifteen for fetching a full page of results you will not read. On a question that turns out to be answerable from snippets, the whole thing cost one.

The exception is when latency matters more than credits. A single `search` with `scrapeResults` is one round trip, and two passes are two.

## When the sources disagree

Real search results contradict each other, and a model handed conflicting text will usually pick one and sound certain.

Give the model the publication dates where you have them. `metadata.publishedTime` comes back on pages that declare one, and "the older source says otherwise" is a resolution rule a model can actually apply.

Tell it what to do with a genuine conflict: say the sources disagree and show both, rather than silently choosing. A visible disagreement is useful to a reader, and a hidden one is a coin flip presented as fact.

Watch out for consensus that is really one source repeated. Five results agreeing often means four of them copied the fifth, so weight a primary source above the sites that quote it.

## Handling a bad search

Not every query returns something usable, and the failure should be visible rather than papered over.

An empty or thin result set is an answer: say that nothing useful was found. A model asked to answer from three irrelevant snippets will produce something, and that something is worse than an admission.

Check relevance before you spend on fetching. If the top results are dictionary definitions or a homepage when the query was specific, refining the query is cheaper than reading five wrong pages.

Try a rephrasing before giving up, but cap it. Two attempts is diligence and six is a loop.

## Knowing the answers are good

Keep a set of questions with known answers and run them regularly. Retrieval quality drifts as the web changes, and without a fixed set you will only notice when someone complains.

Log the query, the URLs returned, and the answer. When a bad answer surfaces, the only useful question is which sources produced it, and that is unanswerable after the fact unless it was recorded.

Sample the citations. An answer that cites a page which does not actually support it is the most damaging failure here, because the citation makes it more convincing rather than less.

## What it costs

The search itself is 1 credit. Each result you asked us to fetch bills 1 more. A five result search with content is 6 credits, and the same search without content is 1.

`limit` runs from 1 to 15. Ask for what you will actually read: fetching 15 pages to use 3 costs 12 credits for nothing.

## What to watch for

Search is the narrowest pipe we run, so batch your queries rather than firing one per keystroke, and cache results you will reuse. A query typed by a user is a query you will see again.

Turn `scrapeResults` off for the first pass when you are exploring. Snippets are often enough to decide which three of fifteen results are worth the credits.

Use `timeRange` when recency matters. A question about a current version answered from a three year old page is worse than no answer, because it looks right.
