Guides
Reading search results
How a search tells you what it understood, what it suggests, how exact the count is, and what limited the answer.
Every search response explains itself. These fields tell you how your request was interpreted and how far to trust the answer, and they are the same on every category.
resolved_search — what we decided you meant#
Every search response echoes the interpretation the engine actually ran:
filters— the effective filters. Render these, especially on zero results.filters_source—caller(yours),parser(inferred byauto),caller+parser(both; yours win on conflict), ornone.parser_version— the extraction agent's version when it ran,"none"when it didn't. Log it: when result quality shifts after a parser retune, this is the field that explains it.sort— the ordering actually applied: yours, or one inferred from the question when you sent none.[]when the engine chose the order itself.overrides— where your explicit filter overrode an inferred one.
suggestion — a better way to have asked#
null on most responses. When it is set, the search you asked for still ran and
these results still came from it. The suggestion is advice about the next
request, not a warning about this one:
{ "kind": "search", "category": "job_opening", "message": "Hiring questions are answered better in the job-opening corpus." }kind | Meaning | What to do |
|---|---|---|
search | A plain search still answers this, in the category named | Drop that value straight into the next request body |
agentic | No single search answers this, whatever the category: it needs several steps or several corpora joined. category is null | Start an agent run (POST /v1/agents/runs) with the same question |
message is one ready-to-show sentence. Surfacing it is what turns a
disappointing result set into a next step.
total and total_is_estimate#
| Situation | total | total_is_estimate |
|---|---|---|
| Filter/keyword search | Exact, at any size | false |
| Semantic search where a count is unavailable | The rows in hand — a floor | true |
| Semantic company/person search that hit the counting cap | Exactly 10000 | true |
degradation[] — what we could not do#
An empty array means the API checked and nothing degraded. It never means "unknown". Each entry is {reason, detail, impact, source_corpus} with impact one of recall | precision | freshness | fields.
reason | What happened | What to do |
|---|---|---|
vector_coverage_incomplete | Part of this corpus has no embedding; some records were unreachable for reasons unrelated to your query | Note that some records couldn't be searched semantically |
mode_downgraded | Impact recall: vector retrieval was unavailable, so this ran as keyword matching. Impact precision: the records searched have no embeddings (people today), so the description in your query could not be ranked semantically and the order doesn't reflect fit. In deep mode: the search ran at a lower effort than deep mode asks for, or its enumeration stopped before the full set was reached | Treat results as literal matches, not semantic ones. For precision, don't read the order as a ranking by fit. In deep mode, read coverage for what was reached |
pagination_truncated | A full page arrived with no further page — more matches exist than can be paged to | Don't render "end of results"; narrow the search instead |
field_not_indexed | Some requested fields don't exist in this corpus and were dropped | Note which fields are missing |
corpus_unavailable | A corpus could not be reached (coverage responses) | Report the corpus as missing, not empty |
corpus_timeout | A corpus did not answer in time | Offer a retry |
lexical_scoring_unavailable | A field is mapped such that it cannot be scored lexically | Rarely actionable; log it |
billing_bypassed | The work was done and nothing was charged for it | Say so. It is a test credential, or a deployment configured to run on an empty wallet — the second is a v1 testing posture, not a gift |
axis_not_applicable | Part of the question names something this corpus does not carry | Say which half was dropped. The answer is real, just broader than what was asked |
anchor_list_capped | More anchors were named than the question shape can hold — a relationship is pairwise, so five companies become two | Name the two that were used. Distinct from pagination_truncated: the question was narrowed, not the paging |
planner_step_incomplete | One interpretation step did not finish, so its axis was not applied | Report the axis as missing. The steps run in parallel, so one failing leaves a wider answer rather than none |
upstream_advisory | The upstream said something about this answer that we cannot classify | Show detail, which carries the upstream's own words. You cannot branch on this one — that is the point of it not being force-labelled as something else |
Why the last four reasons come mostly from relationship routes
The last four arrive mostly from the relationship routes, where a question can be
answered wider than it was asked. axis_not_applicable is the common one: the
affiliation graph holds no firmographics at all, so "directors at Series-B
fintechs who know anyone at Acme" is answerable only with the firmographic half
dropped. Saying which half was dropped is the difference between a wider
answer and a wrong one.