Best practices
Search
Write focused queries, choose the providers and the tier, filter at the source, and run many searches fast and for less.
These practices help you get better results from Telem, faster and for less. Every option here is described in full on Search parameters.
Write focused queries
Section titled “Write focused queries”Ask one thing per query
Section titled “Ask one thing per query”Telem sends your query, unchanged, to each provider. A query that asks several things at once is hard for every provider to match. Split it into focused queries, and send them together as a batch:
{ "user_input": [ {"query": "Acme Corp competitors"}, {"query": "Acme Corp financial results 2026"}, {"query": "Acme Corp news October 2026"} ]}Keep queries under 400 characters
Section titled “Keep queries under 400 characters”Telem sets no length limit, but providers do. Brave refuses a query longer than 400 characters or 50 words. When a provider refuses a query, its run fails and the other providers still answer.
Choose the providers
Section titled “Choose the providers”Each provider that runs a query is one charge. So the providers you choose decide both the recall and the price of a search.
| What you set | Providers for each query | Use it when |
|---|---|---|
| Nothing | All the default providers | You want the widest recall, and the cost is less important |
auto_routing: "accuracy" |
The ones Telem chooses for that query | Most searches. Telem sends each query to the providers that answer it best |
providers.include |
Only the ones you name | You know which provider fits, or you want a fixed cost |
providers.exclude |
The default set, without these | A provider does badly on your queries |
{"search": {"auto_routing": "accuracy", "providers": {"include": ["exa", "tavily", "brave", "parallel"]}}}With auto-routing and an include list, Telem chooses from your list. Some providers run only when you name them, such as the social, video and shopping platforms. See Auto-routing and Pricing.
Choose a tier
Section titled “Choose a tier”The tier decides how much each result includes, and what Telem asks each provider
for. A higher tier can cost more and take longer. The default is default.
| Tier | Each result adds | Cost | Time | Use it when |
|---|---|---|---|---|
minimalist |
url, title, rank |
The base price | Fastest | You only need links, to fetch or to show |
default |
summary |
The base price | Fast | Most searches: your agent reads the summaries and picks pages |
extended |
excerpt, publish_date, usage, and full_content when you ask for it |
More on tavily and parallel |
Slower on parallel |
You need longer snippets or the publish date |
max |
thumbnail, favicon, source, enrichments, and the query’s answer, entities, related and verticals |
More on exa, and with full content on linkup and you |
Slowest: Telem waits up to 90 seconds | You need everything a provider can give |
Every tier also has latency_ms and warnings. When a provider cannot fill a field,
the field is null and a capability_gap warning says why. The provider still
answers. For the exact fields, see Tier.
What each tier changes for each provider
The tier changes the request that Telem sends to some providers. That is where the price and the time change:
| Provider | At extended |
At max |
|---|---|---|
brave |
Extra snippets. Same price | Page metadata. Same price |
exa |
No change | An LLM summary of each result (about $0.005 more for five results, and about 4 seconds instead of under 1), longer highlights, links and images |
linkup |
No change | With include_full_content: a deep search, $0.05 instead of $0.005 |
parallel |
Advanced mode: $0.005 instead of $0.001, and about 3 seconds instead of 0.2 | Longer excerpts. Same price |
perplexity |
More context in each result. Same price | The same as extended |
tavily |
Advanced depth: 2 credits ($0.010) instead of 1 ($0.005) | A generated answer, favicons and images |
you |
No change | With include_full_content: a live crawl of each page, $0.001 more for each page |
ceramic, seltz, serpapi, tinyfish |
No change | No change. tinyfish adds thumbnails, at the same price |
fields is the alternative to a tier: name the exact fields you want. You cannot
send both. Asking for excerpt or full_content in fields turns on the paid
max options, and each run that does says so in a paid_knob_engaged warning.
The hosted MCP server stops waiting after about 60 seconds, so a
max search through it can time out before it finishes.
Filter at the source
Section titled “Filter at the source”- By date:
published_afterandpublished_beforekeep the results published in that window. Every result then haspublish_date, at every tier. A result with no known date is kept. - By website:
include_domainskeeps the results from 1 to 20 websites. Write the host name only, such assec.gov. Subdomains are included. - By platform: to search a social, video, review or shopping site, name its provider. See Supported platforms.
{"search": {"published_after": "2026-09-01", "include_domains": ["sec.gov", "reuters.com"]}}Ask only for what you read
Section titled “Ask only for what you read”Results per provider
Section titled “Results per provider”num_results is the number of results from each provider, not for the whole search.
Three providers at 10 give you thirty results. The default is 5, and the maximum
is 20.
Search, then fetch the pages you keep
Section titled “Search, then fetch the pages you keep”include_full_content asks the providers for the whole page instead of a snippet. It
works only at the extended and max tiers, and on some providers it costs more and
takes longer. Usually it is better to do it in two steps:
- Search, and read the summaries.
- Send the URLs you decide to keep to Fetch.
Run many searches
Section titled “Run many searches”Send related queries as one batch
Section titled “Send related queries as one batch”A batch is one call with up to 32 queries. Its queries run at the same time, up to 16
provider calls at once, and each run says which query it answers. The number of
queries times num_results can be at most 160: for example, 32 queries at 5 results,
or 8 queries at 20. Every query in a batch uses the same tier and num_results. Each
query is charged for each provider that runs it, the same as separate calls.
Run calls in parallel, with a limit
Section titled “Run calls in parallel, with a limit”For more than one batch, run calls at the same time, but limit how many run at once. Retry the calls that fail for a reason that can pass:
429: you reached the per-minute limit of your account or your key. Wait for the seconds inRetry-After(up to 60). See Rate limits.503withall_providers_failed: every provider failed. Retry only when the response hasRetry-After.504withdeadline_exceeded: Telem had too little time left to start any provider. Nothing was charged. Retry with backoff.
Give each query its own result, so that one failure does not stop the others:
import asynciofrom telem import APIStatusError, AsyncTelem, TelemConnectionError
async def search_one(client, limit, query): async with limit: for attempt in range(4): try: return {"query": query, "ok": True, "data": await client.search(query)} except (APIStatusError, TelemConnectionError) as error: status = getattr(error, "status_code", None) if status not in (None, 429, 504) or attempt == 3: return {"query": query, "ok": False, "error": str(error)} await asyncio.sleep(60 if status == 429 else 2 ** attempt)
async def search_all(queries, at_once=8): limit = asyncio.Semaphore(at_once) async with AsyncTelem() as client: return await asyncio.gather(*(search_one(client, limit, q) for q in queries))
results = asyncio.run(search_all(queries))The Python SDK does not retry, so the loop retries a 429, a 504 and a lost connection. It does not retry a 503, because every provider has just failed.
import Telem from "@telemai/sdk"
const telem = new Telem({ maxRetries: 3 }) // retries 429, 5xx and network errors
async function searchAll(queries: string[], atOnce = 8) { const out = [] for (let i = 0; i < queries.length; i += atOnce) { const wave = queries.slice(i, i + atOnce) const settled = await Promise.allSettled(wave.map((query) => telem.search(query))) settled.forEach((r, j) => out.push(r.status === "fulfilled" ? { query: wave[j], ok: true, data: r.value } : { query: wave[j], ok: false, error: String(r.reason) })) } return out}The JavaScript SDK retries for you, and waits for Retry-After.
Merge the results
Section titled “Merge the results”Telem keeps each provider’s results apart. When three providers find the same page,
it comes back three times, each time with that provider’s rank. There is no score
that compares results across providers. Merge them by URL before you pass them on,
so your agent does not read the same page twice:
def merge(response): pages = {} for result in response.results: url = result.url.split("#")[0].rstrip("/") page = pages.setdefault(url, {"url": url, "title": result.title, "providers": [], "best_rank": 99}) page["providers"].append(result.provider) page["best_rank"] = min(page["best_rank"], result.rank or 99) # Pages that more providers found first, then the best rank. return sorted(pages.values(), key=lambda p: (-len(p["providers"]), p["best_rank"]))function merge(response) { const pages = new Map() for (const result of response.results) { const url = result.url.split("#")[0].replace(/\/+$/, "") const page = pages.get(url) ?? { url, title: result.title, providers: [], bestRank: 99 } page.providers.push(result.provider) page.bestRank = Math.min(page.bestRank, result.rank ?? 99) pages.set(url, page) } // Pages that more providers found first, then the best rank. return [...pages.values()].sort((a, b) => b.providers.length - a.providers.length || a.bestRank - b.bestRank)}Expect some providers to fail
Section titled “Expect some providers to fail”A provider that fails does not fail the search, and it is not charged. Its run has an
error, and the other runs keep their results, so read the results from the runs that
succeeded. When every
provider fails, you get a 503 (all_providers_failed). When a field you expected is
null, look in the run’s warnings: capability_gap means the provider cannot give
that field, and count_clamped means it returned fewer results than you asked for. See
Errors.
Keep a task’s searches together
Section titled “Keep a task’s searches together”When your agent makes several searches for one task, send the session_id of the first
response with the next ones (session in the SDKs). The console then shows them as one
session. An agent
integration does this for you, with query lineage.
Checklist
Section titled “Checklist”- One question per query, under 400 characters, and related queries in one batch.
- Auto-routing or a provider list, unless you want every default provider.
- The lowest tier that has your fields.
defaultfor most agents. - Filter by date and website at the source, not after.
- Search, then fetch the pages you keep.
- Limit parallel calls, and retry only
429,503withRetry-After, and504. - Merge results by URL before your agent reads them.
Next steps
Section titled “Next steps”- Search parameters: every search option in full
- Fetch best practices: read the pages you keep
- Auto-routing: how Telem chooses the providers
- Pricing: what each provider costs