Field notes

Publication dates are metadata, not a search-quality score

Date coverage varied from 33% to 100% in our Search API run. Here is why that matters for some agent tasks and misleads in others.

In our Search API benchmark, publication-date coverage ranged from 33% to 100%. It is an eye-catching difference and an easy one to misuse.

A date field can help an agent reject stale release notes, order news results, or explain why it selected one source over another. It does not tell you whether the page is correct, whether the date describes publication or modification, or whether an undated page is old.

So we report date coverage, but we do not include it in the pass condition.

Three APIs, three date shapes

The providers in our run exposed dates differently:

// Perplexity Search
publishedAt: result?.date ?? null
updatedAt: result?.last_updated ?? null

// Exa
publishedAt: result?.publishedDate ?? null
updatedAt: null

// Parallel Search
publishedAt: result?.publish_date ?? null
updatedAt: null

After normalization, Perplexity Search had date metadata on 100% of results, Parallel Search on 49%, and Exa on 33%.

Those numbers describe field presence in one run. They do not establish that one provider knows the true publication time more often. We did not independently verify every date against page markup, HTTP headers, feeds, or repository history.

That verification would be a different benchmark.

null does not mean stale

Many of the best technical sources are living documents. A support-policy page may be updated in place without presenting a publication date. A GitHub repository page may describe the current state more accurately than a dated article. An API reference can be canonical and intentionally undated.

Treating publishedAt: null as “old” silently penalizes those sources.

The reverse error is just as easy. A page can carry a recent date while summarizing obsolete information, or expose an update timestamp caused by an unrelated template change. Date presence and content freshness are correlated in some collections, but they are not interchangeable.

The workload decides whether coverage matters

Consider three agent tasks:

TaskHow useful is a date?Why
Find the canonical PostgreSQL support policyHelpful, not requiredThe maintained first-party page is authoritative even without a date
Find Node.js releases published this monthRequiredThe task contains a time boundary
Monitor breaking API announcementsRequired and must be verifiedOrdering and alerting depend on reliable time semantics

For the first task, primary-source rank may matter more than date coverage. For the other two, a result without a trustworthy date may be unusable.

One benchmark score cannot express all three priorities without hiding the workload assumptions inside its weights.

Store more than the provider's date

An application consuming Search API results should separate provider metadata from its own observations:

type SearchRecord = {
  url: string
  title: string
  snippet: string
  providerPublishedAt: string | null
  providerUpdatedAt: string | null
  retrievedAt: string
  dateVerifiedAt: string | null
  dateSource: "provider" | "page" | "feed" | "repository" | null
}

retrievedAt answers when your system saw the result. It does not repair a missing publication date, but it gives caches, reruns, and incident reviews a stable reference point.

If the task depends on freshness, verify the date using a source appropriate to the content: structured page metadata, an official feed, a release record, or repository history. Preserve where the date came from. Do not overwrite a provider date with a derived date and then forget which one you are holding.

Null handling should be explicit

Sorting undated results to the bottom is a product decision, not a neutral implementation detail. Dropping them entirely is even stronger.

A safer default is to branch on task intent:

function canUseResult(result, task) {
  if (!task.requiresFreshness) return true
  if (!result.publishedAt && !result.updatedAt) return false
  return true
}

Real code will need date parsing, clock boundaries, and a maximum acceptable age. The important part is that the policy belongs to the task layer. It should not leak in through a generic sort((a, b) => b.date - a.date) that silently treats missing values as ancient history.

Why we kept dates out of the pass criteria

Our retrieval test asks whether an API returns enough valid results, enough snippets, and an expected primary source near the top. The three benchmark questions mention current information, but their canonical sources are maintained technical pages rather than a time-bounded news corpus.

Requiring date coverage would have rewarded a convenient response field without proving that it improved these tasks. We still publish the coverage because it may matter to the reader's workload.

This is a recurring benchmark design problem: a measurable field is not automatically a meaningful score. Sometimes the honest treatment is to leave it as a column and explain when to care.

The provider-level benchmark reports contain the normalized results and date fields for every published attempt. The protocol shows why date presence is reported but does not determine a pass.