Research with sources

Search the web, read the pages behind the best sources, and write a summary that quotes them, on one Flux key, from your agent or your own code.

Give your agent a question and get back a short answer that quotes its sources, with links you can check. The recipe has three steps, each on the same Flux key:

  1. Search with web_search (or POST /v1/search) to get an answer and its source URLs.
  2. Read the best few sources in full with web_fetch (or POST /v1/fetch).
  3. Write the summary with flux-auto, quoting the pages you read.
StepStatus
SearchRolling out
Read a pageLive

Both are paid abilities. You need a paid, cleared plan; see Plans.

From your agent

Add the Flux tools server to your agent. Pick yours:

Built into Murage, which decides which abilities it uses. Nothing to set up here. See murage.ai.

Then give it the whole job in one message:

Research this question: "What changed in the latest Node.js LTS release?" First call the Flux web_search tool. From its citations, pick the three most authoritative pages and read each with the Flux web_fetch tool. Then answer in five bullet points. Every bullet must quote a sentence from one of the pages you read and give its URL. If the pages disagree, say so. Do not read more than three pages.

The last line is the budget: each page read is billed, so tell the agent how many to read.

From your own code

The same three steps in Python, with requests. The TypeScript version follows the same shape with fetch.

python
import requests

BASE = "https://api.fluxrouter.ai/v1"
HEADERS = {"Authorization": f"Bearer {FLUX_API_KEY}"}
MAX_PAGES = 3  # your budget: each page read is billed

question = "What changed in the latest Node.js LTS release?"

# 1. Search: an answer plus the URLs it drew on.
search = requests.post(f"{BASE}/search", headers=HEADERS, json={"query": question})
search.raise_for_status()
result = search.json()
print("Search cost (USD):", result["cost_usd"], "searches:", result["searches"])

# 2. Read the first few sources in full. Skip any page that will not read.
pages = []
for url in result["citations"][:MAX_PAGES]:
    page = requests.post(f"{BASE}/fetch", headers=HEADERS, json={"url": url})
    if page.status_code != 200:
        continue  # blocked, social network or failed: not billed
    pages.append((url, page.json()["markdown"][:20000]))
print("Pages read:", len(pages))

# 3. Write the summary, quoting only what was read.
sources = "\n\n".join(f"SOURCE {url}\n{text}" for url, text in pages)
chat = requests.post(
    f"{BASE}/chat/completions",
    headers=HEADERS,
    json={
        "model": "flux-auto",
        "messages": [
            {
                "role": "system",
                "content": "Answer in five bullet points. Every bullet quotes one sentence "
                "from a SOURCE below, in quotation marks, followed by its URL. "
                "Use nothing that is not in the sources. Say so if they disagree.",
            },
            {"role": "user", "content": f"Question: {question}\n\n{sources}"},
        ],
    },
)
chat.raise_for_status()

print(chat.json()["choices"][0]["message"]["content"])

The [:20000] trims each page so a long one cannot crowd the others out of the model's context. Trim to suit the model you route to.

Budgeting each step

StepBilledWhere the cost shows
Searchpriced per call, plus the tokens that write its answercost_usd in the response
Read a pagepriced per call; a repeat within 6 hours is freeCount the pages you read; each read is on your usage page
Write the summaryChat tokensYour usage page

Ways to keep a run cheap:

  • Cap the pages. The biggest lever is how many sources you read. Three is usually enough.
  • Skip the read when the answer will do. The search answer already cites its sources. Read pages only when you need exact quotes.
  • Let failures be free. Blocked URLs, social networks and failed reads are not billed, so skipping them costs nothing.
  • Set a spend cap on the key for unattended runs. See Spend caps.

If a step fails