Skip to content

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.

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"}
]
}

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.

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.

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.

  • By date: published_after and published_before keep the results published in that window. Every result then has publish_date, at every tier. A result with no known date is kept.
  • By website: include_domains keeps the results from 1 to 20 websites. Write the host name only, such as sec.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"]}}

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.

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:

  1. Search, and read the summaries.
  2. Send the URLs you decide to keep to Fetch.

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.

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 in Retry-After (up to 60). See Rate limits.
  • 503 with all_providers_failed: every provider failed. Retry only when the response has Retry-After.
  • 504 with deadline_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 asyncio
from 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.

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"]))

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.

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.

  • 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. default for 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, 503 with Retry-After, and 504.
  • Merge results by URL before your agent reads them.
Was this page helpful?