Exa Find People
exa_find_peopleUse AFTER companies have been identified (company-find step in the same agent, user named a target, CRM lookup, etc.) to surface specific decision-makers. Results are always LinkedIn URLs.
Before composing a search, call get_skill_guide('exa_find_people') —
it owns the query vs system_prompt split that decides whether
results come back useful or noisy (exclusions in query backfire;
they belong in system_prompt).
results holds only people who matched your query + system_prompt;
non-matches come back in rejected as {name, reason} with no URL.
Put exclusions and preferences in system_prompt and act on what
returns — don't re-filter the results yourself.
Pass company_domain or company_linkedin_url whenever you have one. A
search carrying either is answered by a people database that filters on
that identifier, so it cannot return someone at a same-named company.
Without one, the search falls to a name-matched provider and everything
below applies.
On that name-matched path, a search naming a company drops anyone whose
indexed record places them at a differently-named employer — a check the
match verdict does not perform, since it weighs the whole search intent at
once and passes near-namesakes, returning a founder of 'Acmely' for an
'Acme' search. The check reads the indexed employer, not
summary.current_company, which is a model's reading of profile prose and
routinely echoes the company you searched for back at you; it also ignores
roles known to have ended, so a job someone left is not current.
That path judges against a profile snapshot (refreshed ~weekly), not live reality, so someone who changed jobs since the last crawl can still pass. Two shapes slip through: a longer name that starts with the one you searched ("Acme" admits "Acme Robotics"), and a profile resolved to no indexed record, which falls back to the extracted name. Nothing downstream re-checks — which is why an identifier is worth passing.
Accepts a list of ExaPeopleSearch — pass one for a single-company
lookup, or N for a batch, fanned out in parallel (max 5 concurrent, since
the name-matched provider has shown 5xx instability under bursty load).
Each search routes on its own, so one batch can be served by both
providers. Each call retries once on 5xx inside the HTTP client.
An identifier-pinned search matching more people than can be returned at
once comes back in its own slot as {error, query} asking you to narrow
by titles (and locations, at a multinational); the rest of the batch
is unaffected. Re-send that one search narrowed.
Costs 0.5 Sliq credits per search that returns without error, whichever
provider served it, so an empty result set still charges (the call was
made). Free on BYO Exa (a connected Exa key). Soft-fails on insufficient
credits: the data is returned and the charge is capped at the remaining
balance.
List of per-search result dicts in input order. Each is either
{results: [...], rejected: [...]} on success, or
{error: '...', query: '...'} on failure (after the in-client
retry). results entries are {name, url, score, summary} with
url always linkedin.com and summary holding name,
current_title, current_company. rejected entries are
{name, reason} only.
A search pinned by company_domain / company_linkedin_url is
filtered on the employer and on titles, so it returns no score,
no ordering, and no seniority_level / match_reasoning — those
come from the per-profile read that only the unpinned path runs, and
are absent rather than guessed. Don't infer seniority from position
in the list; read the titles.
On insufficient Sliq credits the batch is refused before running: it
raises InsufficientCreditsError rather than returning per-search slots.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| persist | No | Default True — in an agent, matched people are saved and linked as person rows automatically (see `list_name`). Pass False only for a read-only lookup the user doesn't want on a list. | |
| agent_id | No | Optional — a specific agent to save the matched people into. Omit it to use the running agent, which is the usual case. Only a throwaway lookup outside any agent returns results without saving. | |
| searches | Yes | List of `ExaPeopleSearch` objects. Each has its own `query` + optional `system_prompt`. For a single-company lookup, pass a list of one. | |
| list_name | No | Short kebab slug naming the Output-tab list bucket (e.g. 'acme-execs'). When this runs in an agent, matched people are saved and linked as `agent_search_results` person rows automatically — deduped by profile, re-runs update in place; `list_name` names their list, and absent it they land in the 'default' list. Query them by reference with `query_search_results` instead of re-typing URLs from `results`. The `results` return is unchanged either way. | |
| num_results | No | Candidates Exa retrieves and ranks per search before the match filter runs. Default 10; max 100. Matches cluster at the top of Exa's ranking, so 10 usually holds the right people for a well-formed query; the returned `results` are shorter after filtering. If `results` is thin and `rejected` is long, reword the query (the reject reasons say how) rather than raising this — the tail ranks are lower-relevance anyway. |