List people
list_peopleEach row: id (the person id query_people uses), display_name, spine (title, company,
location, headline), current_roles (every role the person holds now in LinkedIn's order, each
{position, company, start}; the spine's title and company are only the first of them, and an
empty list means no role in their history is dated as ongoing, not that they have no job),
company_profile_id (their company's list_companies id, or null),
linkedin_slug, linkedin_provider_id, email, outreach_stage and removed. Removing
someone from a campaign leaves their outreach_stage as it was.
With include_signals it also has signal_entries, the signals the person's profile shows,
newest first and the same with or without agent_id: their company's, and the one each of
their campaigns enrolled them on. Each entry's company_id and company_name are the company the
signal belongs to, which can differ from the person's own; they are null for an enrollment
signal no company row holds. They cost a few database reads per person, so ask for them on a narrow read (a
q, one bucket, or a small limit).
Without agent_id, each row also has:
outreach_stage: the person's most advanced lead-funnel bucket across the campaigns of the user and every teammate, '' when they're in none.removed: true when they were removed from every one of those campaigns they're in.activity: those campaigns' prospect rows on the person, newest first, each {owner_email, owner_display_name, agent ({id, title}, or null), stage, removed, last_touch_at}, whereremovedis whether they were removed from that campaign.
With agent_id, each row also has:
degree: the user's LinkedIn degree to the person, '1', '2', '3' or 'out_of_network'; null when unknown. A person the user is connected to reads '1'.intro: the warm-intro check.stateis one of not_checked, checking, queued, found, cold, connected, unresolved.connectorslists the user's 1st-degree connections who know the person (name, headline, identifier, provider_id).mutual_connections_truncatedtrue meansconnectorsis a sample of a longer list.shared_connections_countis LinkedIn's total.result_idis the search row the check read, null when the person has none.outreach_stage: the person's lead-funnel bucket on this agent, '' when not in outreach here.prospect_id,email_stageandlinkedin_stageare their prospect row on this agent, null when not enrolled.removedis true when they were removed from the agent's campaign, andremoval_reasonsays why, '' when they weren't or no reason was recorded.listsandsources: the search lists and discovery tools that surfaced the person.columnsholds the researched [label, value] pairs.verdict,verdict_reasonandrejected_on: the curation recorded on the person's search rows, as the Verdict column shows it. 'rejected' when every row is rejected, 'qualified' when any row is qualified, else 'unclear' (screened but too thin to judge) when any row is, else null, with the reason from the latest row carrying it. On agroup_by='list'bucket page, or under a "run" filter whose runs all saved to one list, it's the verdict on that list's row.rejected_onis {lists, reason}: the lists whose own verdict is 'rejected' while the person'sverdictisn't, with the latest rejected row's reason; itslistsis empty otherwise and on those two reads. A person rejected on every row is left out unless a "verdict" filter asks for 'rejected', a "run" filter is set orinclude_rejectedis set — the same as the user's default view — though a tracked prospect always shows.criteria, only withinclude_criteria: why the person matched, as their opened row shows it. Per list they're in, {list_name, evaluations}; each evaluation is acriterionwith thereasoning, a verdict (satisfied'yes', 'no' or 'unclear', or a numericscorewhere 7 and up is met) and http(s)references. Criteria run about 2KB per person, so ask for them on a narrow read (aq, one bucket, or a smalllimit) or from run_code. A list where all of the person's rows are rejected is left out unless the read includes rejected people.
The "list", "source", "degree" and "connector" groupings, the "list", "source", "degree",
"verdict" and "run" filters, include_criteria and include_rejected read one agent, so they
need agent_id.
To count people per group, pass group_by alone. To list one group's people, pass group_by
plus a bucket key taken from those counts. Otherwise you get everyone, sorted by name. Page
until next_cursor is null by passing it back as cursor. A direct call returns 25 rows by
default; for a wide pull, call this from run_code with limit up to 200 (nothing truncates
there) and print only the fields you need.
A dict. A group_by without a bucket returns group_counts, a list of
{key, count} with the largest group first and the '' group last ("degree" keeps
closest-first order and "segment" its group's tag order then 'No match'; "connector"
entries add label), and total, the matching people
each counted once. With group_by="list", each group also carries criteria: the search
criteria a Websets list screens its people against, '' for any other list. Every other
call returns results (rows shaped as above) and next_cursor, plus total (every matching person) when
group_by is omitted. With agent_id, every call also returns filtered_out_count: how
many people this same call matches once a "verdict" filter on 'rejected' is added to
filters, with the same q, group_by and segment_group_id and no bucket, each person
counted once. Only under the same search, filters and grouping as the user's People table
does it equal the number that table shows as "didn't match".
Tool call template
This tool declares no required parameters. Add optional parameters from the input schema as needed.
{
"id": 1,
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"arguments": {},
"name": "list_people"
}
}Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| q | No | A substring matched against name, title, headline and company. | |
| limit | No | Rows per page (default 25, max 200). | |
| bucket | No | One key from `group_counts` for the same `group_by`; returns that group's people. Needs `group_by`. | |
| cursor | No | The `next_cursor` from the previous page; omit for the first page. | |
| filters | No | Clauses that must all match. For "degree", "outreach_stage", "list" or "source", use {"column_key": <dimension>, "operator": "is_any_of", "values": [keys]} with keys as group_counts returns them ('' matches no value). For "reached", use the same shape with funnel rungs ('contacted', 'replied', 'interested', 'meeting_booked'): it matches everyone the rung counts in the lead funnel's `reached` (everyone who got at least that far), so list a rung's people with it; "outreach_stage" matches only the people at that one stage. For "removed", use the same shape with 'removed' (the people removed from the agent's campaign, or without `agent_id` from every campaign they're in) or 'not_removed' (the people in the agent's campaign who weren't removed, at any stage, finished and replied included; without `agent_id`, the people in at least one campaign they weren't removed from); people not in the agent's campaign (without `agent_id`, in none) match neither. For "segment", use the same shape with the segment keys above. For "verdict", use the same shape with any of 'rejected' (the people the user's default view filters out, labelled "Didn't match" in their table), 'qualified' and 'unclear'; it matches each person's `verdict`, or with group_by="list" their verdict on each list, and 'rejected' brings the rejected people in without `include_rejected`. For "run", use the same shape with run ids from `query_search_runs` as strings; it matches the people those search runs found, rejected ones included. When those runs all saved to one list and group_by isn't "list", a "verdict" filter reads that list alone, as on its group_by="list" bucket page. For "name", "title", "headline", "company" or "location", use {"column_key": <column>, "operator": "contains", "text": <substring>}. | |
| agent_id | No | The agent whose People tab to read. Omit it to read everyone in the account. | |
| group_by | No | The dimension to count or to pick a bucket from. "degree" keys are '1', '2', '3', 'out_of_network'; "connector" keys are a connector's provider_id (else their identifier or name) and carry the connector's name as `label`; "outreach_stage" keys are funnel buckets; "list" and "source" keys are list names and discovery tools; "segment" keys are tag names in `segment_group_id`'s group, plus 'No match' for people the classifier couldn't place; "title", "company" and "location" key on the person's own value. A '' key is the group with no value (for "segment", people the group hasn't classified). A person with several lists, sources, connectors or tags counts in each. | |
| company_id | No | Only the people at this company (a company `id` from list_companies or query_companies). | |
| on_behalf_of | No | A teammate's email, or an agency client's from list_agency_clients, to run this call in that account: their agents, settings, connected accounts, and credits. Omit it to act on your own account. | |
| include_signals | No | Also return each row's `signal_entries`. Default False. | |
| include_criteria | No | Also return each row's `criteria`. Default False. | |
| include_rejected | No | Also return (and count) the people left out as rejected. Default False. | |
| segment_group_id | No | The segment group (from list_segment_groups or get_segment_funnel) a "segment" filter or group_by reads. With it, each row also carries `segment`, its tag names in that group. |