Record Search Results
record_search_resultsThe discovery tools (exa_find_people, search_linkedin_people,
fetch_post_engagers, theirstack_search, find_companies_by_tech_stack,
exa_search_news, search_news_events) already save and link their own matches
when run in an agent. Use this tool on their rows to filter them (a verdict
on each screened row, below) or to add to a saved row — columns, signals,
evaluations, or people nested under a company — always under the same
identifier and list_name the discovery tool saved it with; a different
list_name makes a second row.
Dedup per (agent, identifier, list_name). Existing rows: data['signals']
accumulates across runs (union by URL); other fields are last-writer-wins.
Unset fields preserve existing values. Cross-list duplicates of the same
identifier are allowed (intentional — two lists may track the same entity
for different reasons).
Identifiers are stored canonical — the registrable domain (eTLD+1) for
companies (https://www.Acme.com/ and news.acme.com both → acme.com),
bare slug for LinkedIn (https://linkedin.com/in/JohnDoe/ → johndoe).
Match the canonical form when querying via query_search_results.
Empty-list semantics: signals: [] preserves accumulated signals (the
cross-run contract); evaluations: [] REPLACES (LLM-rewritten per run).
Put every user-requested display attribute — a metric, a person's email,
any column the user asked to see — in data.columns as {label: value},
one entry per column under the label the user asked for. columns merges
by key-union across runs (new values win). The Output tab and CSV render
these as columns; a value written to a top-level extra key instead is not
surfaced.
Set each result's source to the discovery tool that surfaced that
candidate — per row, so a batch merged from several tools keeps each row's
origin. Leave it at 'agent' only for rows no discovery tool surfaced.
This is also how you filter what you screened: give each screened row a
verdict — 'qualified' for one you keep, 'rejected' with a verdict_reason
for one you drop — under the identifier and list_name it was saved with, so
the verdict lands on that row. To mark a row already saved, re-record it with
its identifier, display_name and list_name plus the verdict; the data you
leave out stays as stored. A rejected row stays saved but drops out of the
list the user sees by default; the table counts what you filtered out, and
the user reviews those rows, with their reasons, by filtering it on Verdict.
query_search_results / query_task_people leave it out the same way unless
you ask for rejected rows. A row recorded without a verdict keeps whatever
verdict it already has.
{created, updated, total, created_identifiers} — created_identifiers are
the canonical identifiers of the rows this call added (not ones it merged into).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| results | Yes | The people/company rows to upsert; each SearchResult carries its identifier, display_name, source, any signals/columns to store, and optionally its verdict and verdict_reason. | |
| agent_id | Yes | The agent these rows belong to. | |
| list_name | Yes | short kebab slug naming the bucket these rows belong to (e.g. 'oil-gas-operators', 'fintech', 'companies'). Required. Distinct slugs are separate lists on the agent's People and Companies tabs; reuse the same slug across calls to accumulate into one list. For uncategorized runs, pick a single descriptive slug (e.g. the entity_type plural — 'companies' / 'people') and use it consistently. | |
| entity_type | No | Whether `results` are companies or people ('company' by default). | company |