Search Linkedin People
search_linkedin_peopleOne call runs one query, returning ~10 matches by default (one page). To go
deeper on a single query — "find people in my network matching my ICP" — pass
max_results (up to 100): the tool pages through the matches for you, each
~10-profile page counting as one search against the daily budget. For someone
whose profile URL or provider_id you already have, read their degree from
query_agent_people or a resolve look-up and pass the identifier straight
to setup_linkedin_sequence to queue outreach; a name search would only add
namesakes. To search different people — a list of names, or one filter per
company — loop this tool inside a run_code block, one call per name or
company (that's breadth; max_results is depth on one query). Searches are
paced a few seconds apart
and serialized across this user's LinkedIn work, so a deep search or a long
loop can take a couple of minutes; tell the user to expect a short wait before
a large run. If a search comes back paused or rate-limited, stop and tell the
user which searches remain — the account is paused and further calls won't run
until it lifts.
Scope filters combine with keywords and can be used alone for a single
filtered search:
connections_of— restrict to the first-degree connections of specific people, passed as theirprovider_ids (as returned by an earlier search or profile lookup). To work up to a buyer through someone the user just connected with, pass that person inconnections_ofand the target company inadvanced_keywords={'company': 'Acme Corp'}to surface who they know there.network_distanceis a separate filter on the user's own degree and combines with this — add [2] to keep just the connections the user isn't already directly linked to.advanced_keywords— native LinkedIn keyword sub-filters: a dict with any offirst_name,last_name,title,company,school(each a string).companymatches loosely, so its results can include people who don't work there now (a past employer, a similarly named organization).profile_language— ISO 639-1 codes (e.g. ['en']) that narrow any of the above to profiles written in those languages. A refinement, not a search on its own — pair it with keywords or another filter.
Each profile the search returns is then checked against criteria, one
profile at a time, and only the matches come back in profiles; the rest
come back in rejected as {name, reason}, with no profile URL, so they can't
be acted on. The check reads the name, headline and location, so a criterion
a headline can't show (company size, industry) doesn't reject anyone. It adds
a few seconds per ten profiles.
When this runs in an agent, the profiles are saved with their verdicts and
linked to the workspace Output tab automatically (deduped by profile), the
rejected ones hidden from the list's default view. Pass list_name (a short slug) to name their list — a
discovery search, the people connected to someone, prospects to work through;
reuse the same slug across a loop or follow-up searches to gather everything
into one list. Absent a slug, they land in the 'default' list. Outside an
agent, results are returned only.
Returns up to max_results profiles with provider_id, name, headline,
network_distance, location, and profile_url. Each match's headline is the
member's own tagline: often their current role and company (e.g. to see which
companies 2nd-degree matches work at), but frequently a title alone, so a
headline that omits a company is not evidence they work elsewhere. total_count is LinkedIn's full match count for the query when it
returns one, but LinkedIn now omits it on most Classic searches (so it's often
null): only say "showing N of ~M" when it's a number exceeding the profiles
returned, and never invent a total. Use has_more — True when more results
exist beyond those returned — to decide whether to offer to pull more.
Present the results to the user so they can pick the right person. An error
about being "heavily queued" is transient pacing back-pressure — retry shortly
rather than reporting it as not found.
That field list is the whole of it — a search result carries no current
employer, connection count, follower count, or employment history. Present
what comes back as it is; a search the user wanted to look at is finished at
that point. When the ask genuinely needs one of the missing fields — a
connection-count threshold, employment history to personalize from, or a
per-company verdict or count from company-filtered searches ("which of
these accounts do I have a path into") — pass the matches' profile URLs to
enrich_linkedin_profiles, which returns them for the whole list in one
paid call (connections_count is the field a connection-count filter reads;
company is the current employer) and spends no LinkedIn account budget. A
per-company verdict needs it because an answer summed over people hides the
headlines that would show a loose match. When the user will read a
company-filtered list themselves, present it and offer that enrichment to
confirm who works there now. When the decision also turns on
whether the user is already connected to them, use
setup_linkedin_sequence(action_type='resolve') instead; connection status
is the one thing enrichment cannot answer.
Rate-limited — shares one daily LinkedIn search budget with all other
LinkedIn people searches.
On success, a dict
{'success': True, 'profiles': [...], 'rejected': [...], 'total_count': int | None, 'has_more': bool, 'searches_remaining_today': int}. profiles holds the
matches among the up to max_results found, each with a verdict
('qualified', or 'unclear' when the profile says too little to judge) and
its verdict_reason, and a null verdict when the check couldn't run;
rejected holds the rest as {name, reason}. total_count is the query's full match count when
LinkedIn returns one (often null since its Aug-2026 Classic Search change),
so lean on has_more for whether more results exist; and
searches_remaining_today is the post-search budget, so you can size a
follow-up loop without re-checking. In an agent, also saved_to_list (the
list the profiles were saved to) and saved_count, how many of them the list shows; outside an agent, a
passed list_name yields a null saved_to_list with a persist_note. If
the account tripped its pause partway
through paging, the (still valid) partial results come back with
paused: True and a note — surface it: further searches won't run until
the pause lifts.
On a failed search: {'success': False, 'profiles': [], 'rejected': [], 'error': ..., 'searches_remaining_today': int}. On a pre-flight refusal (daily limit
reached or account paused), searches_remaining_today is omitted:
{'success': False, 'error': ...}.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| criteria | Yes | What a match is for this search, in plain words: the person you're looking for ("Jane Doe, currently at Acme Corp"), or the roles, seniority, region and employer that qualify someone ("Sales leaders, VP and above, based in the US"). Each returned profile is checked against it. | |
| keywords | No | A single search query, typically a person's name (e.g. "John Smith"). Omit when searching by `connections_of` / `advanced_keywords` alone. To search many names, loop the tool in `run_code`, one name per call. | |
| list_name | No | Optional short slug naming the Output-tab list the matches are saved under when this runs in an agent. Absent, they save to the 'default' list. Reuse the same slug across a loop or follow-up searches to gather them into one list (deduped by profile). | |
| max_results | No | Max profiles to return for this one query (default 10 = one page; capped at 100). The tool pages the search internally to reach this many, each ~10-profile page costing one search from the daily budget. Use it to go deep on a single ICP/network query; for many *different* queries, loop the tool instead. | |
| on_behalf_of | No | An agency client's email, from list_agency_clients, to run this call in that client's account: their agents, settings, connected accounts, and credits. Omit it to act on your own account. | |
| connections_of | No | Optional list of provider_ids; restricts results to people connected to those individuals. | |
| network_distance | No | Optional LinkedIn degree filter. Pass [1] for first-degree connections, [2] for second-degree, [3] for third-degree-or-more, or combinations like [1, 2]. | |
| profile_language | No | Optional list of ISO 639-1 codes (e.g. ['en']). | |
| advanced_keywords | No | Optional dict of native keyword sub-filters (first_name / last_name / title / company / school). |