Skip to main content
Glama

Onsa

Fetch search results

fetch_leads
Read-onlyIdempotent

Returns the status and any results of a find_leads or continue_campaign job, by jobId. Status values are "pending", "completed" and "stalled", and leads can hold a partial list while "pending". For a find_leads job: "pending" while it has no leads, the agent has not answered and it is under about 15 minutes old, and also while it has leads, until a reply carrying leads completes it; "completed" once the agent posts a reply carrying leads while this is the oldest open job on its campaign, usually its final report (total can still change afterwards); "stalled" as soon as the agent answers without any leads (a question, or none found), or when no lead has arrived after about 15 minutes - derived on each read, so a lead that lands later turns it back to "pending". For a continue_campaign job: "pending" while newLeads is 0 and it is under about 15 minutes old, even after the agent has replied (if that reply confirms a settings-only change, the request is done), and while newLeads is above 0, until a reply carrying leads completes it; "completed" once a reply carrying leads arrives on the campaign while this is the oldest open job there (possibly a late reply from an earlier search), or after about 15 minutes with newLeads 0 when an agent reply was confirmed; "stalled" after about 15 minutes with newLeads 0 when no agent reply was confirmed (agentMessage can still hold one). A reply carrying leads completes only the oldest open job on a campaign, so a newer job stays "pending" meanwhile, even with newLeads above 0. A pending search keeps running when the conversation ends, and a later call with the same jobId returns what it found. First leads arrive within 5 minutes in half of searches and within 9 minutes in 9 of 10. More can arrive until the final report, typically about 10 minutes after the start (9 of 10 within 15). Also returns total (for a find_leads job, the leads the campaign holds now, skipped and deleted ones excluded; for a continuation, equal to newLeads), newLeads (continuations only: leads added to the campaign since the continuation started - a count by time, which can include a late batch from an earlier search), returned (how many this response carries), campaignId (accepted by get_campaign, get_campaign_leads and get_campaign_stats) and campaignUrl, a deep link to the prospects tab for this search in Onsa. agentMessage is the latest agent text in this campaign's chat. For a continuation it is filtered to what was said after the continuation started, though it can be a late message from an earlier search; for a find_leads job it is not filtered, so after a later continue_campaign on the same campaign it can be that request’s reply. A null agentMessage does not mean the agent is silent: artifact-only messages carry no text, and an agent that errored writes nothing there at all. The agent cannot be replied to through this API. While a search is running, one call can wait up to 35 seconds for its first leads or its next batch before answering, so a call can take that long; other calls answer at once. progress carries startedAt, elapsedSeconds and a note on where the search stands, whether the next call will wait, and when results are likely. Each lead carries name, companyName, linkedInUrl, position, headline, location, industry, companyUrl, email (often null), and score (1-5) with scoreExplanation, the reasoning for why this person matches the ICP.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
jobIdYesThe jobId returned by find_leads
limitNoHow many leads to return (default 100)

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
jobIdYes
leadsYes
totalYes
statusYesOne of "pending", "completed", "stalled"; more values may be added later. `leads` can hold a partial list while "pending". For a find_leads job: "pending" while it has no leads, the agent has not answered and it is under about 15 minutes old, and also while it has leads, until a reply carrying leads completes it; "completed" once the agent posts a reply carrying leads while this is the oldest open job on its campaign, usually its final report (`total` can still change afterwards); "stalled" as soon as the agent answers without any leads (a question, or none found), or when no lead has arrived after about 15 minutes - derived on each read, so a lead that lands later turns it back to "pending". For a continue_campaign job: "pending" while `newLeads` is 0 and it is under about 15 minutes old, even after the agent has replied (if that reply confirms a settings-only change, the request is done), and while `newLeads` is above 0, until a reply carrying leads completes it; "completed" once a reply carrying leads arrives on the campaign while this is the oldest open job there (possibly a late reply from an earlier search), or after about 15 minutes with `newLeads` 0 when an agent reply was confirmed; "stalled" after about 15 minutes with `newLeads` 0 when no agent reply was confirmed (agentMessage can still hold one). A reply carrying leads completes only the oldest open job on a campaign, so a newer job stays "pending" meanwhile, even with `newLeads` above 0.
newLeadsYes
progressYes
returnedYes
campaignIdYes
campaignUrlYes
agentMessageYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changed
    • changedInput schema / properties / jobId / description
      Previous value: -"The jobId returned by find_leads — never invent one"New value: +"The jobId returned by find_leads"
    • changedOutput schema / properties / status / description
      Previous value: -"One of: \"pending\" (search still running), \"completed\" (a batch of leads arrived — not a promise that no more will), \"stalled\" (no leads after ~15 minutes; read agentMessage for the reason and stop polling). Treat an unrecognised value as pending."New value: +"One of \"pending\", \"completed\", \"stalled\"; more values may be added later. `leads` can hold a partial list while \"pending\". For a find_leads job: \"pending\" while it has no leads, the agent has not answered and it is under about 15 minutes old, and also while it has leads, until a reply carrying leads completes it; \"completed\" once the agent posts a reply carrying leads while this is the oldest open job on its campaign, usually its final report (`total` can still change afterwards); \"stalled\" as soon as the agent answers without any leads (a question, or none found), or when no lead has arrived after about 15 minutes - derived on each read, so a lead that lands later turns it back to \"pending\". For a continue_campaign job: \"pending\" while `newLeads` is 0 and it is under about 15 minutes old, even after the agent has replied (if that reply confirms a settings-only change, the request is done), and while `newLeads` is above 0, until a reply carrying leads completes it; \"completed\" once a reply carrying leads arrives on the campaign while this is the oldest open job there (possibly a late reply from an earlier search), or after about 15 minutes with `newLeads` 0 when an agent reply was confirmed; \"stalled\" after about 15 minutes with `newLeads` 0 when no agent reply was confirmed (agentMessage can still hold one). A reply carrying leads completes only the oldest open job on a campaign, so a newer job stays \"pending\" meanwhile, even with `newLeads` above 0."
  2. Changed2 schema fields changed
    • addedOutput schema / properties / progress
      Added value: +{
      +  "additionalProperties": {},
      +  "properties": {
      +    "elapsedSeconds": {
      +      "anyOf": [
      +        {
      +          "maximum": 9007199254740991,
      +          "minimum": -9007199254740991,
      +          "type": "integer"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ]
      +    },
      +    "note": {
      +      "type": "string"
      +    },
      +    "startedAt": {
      +      "anyOf": [
      +        {
      +          "type": "string"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ]
      +    }
      +  },
      +  "required": [
      +    "startedAt",
      +    "elapsedSeconds",
      +    "note"
      +  ],
      +  "type": "object"
      +}
    • changedOutput schema / required
      Previous value: -[
      -  "jobId",
      -  "status",
      -  "total",
      -  "returned",
      -  "newLeads",
      -  "campaignId",
      -  "campaignUrl",
      -  "agentMessage",
      -  "leads"
      -]New value: +[
      +  "jobId",
      +  "status",
      +  "total",
      +  "returned",
      +  "newLeads",
      +  "campaignId",
      +  "campaignUrl",
      +  "agentMessage",
      +  "progress",
      +  "leads"
      +]
  3. Changed2 schema fields changed
    • addedOutput schema / properties / status / description
      Added value: +"One of: \"pending\" (search still running), \"completed\" (a batch of leads arrived — not a promise that no more will), \"stalled\" (no leads after ~15 minutes; read agentMessage for the reason and stop polling). Treat an unrecognised value as pending."
    • removedOutput schema / properties / status / enum
      Removed value: -[
      -  "pending",
      -  "completed"
      -]
  4. First observed

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes far beyond the readOnly/idempotent annotations, detailing the exact status state machine, partial lead results, 35-second poll waits, agentMessage filtering quirks, and the fact that the agent cannot be replied to through this API. This is rich behavioral disclosure that materially helps an agent use the tool correctly.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is very long, but the length is justified by the complexity of the job-state semantics. It is front-loaded with a clear one-sentence purpose and organized into status, output fields, and timing behavior. It could be tightened with headers, but every sentence carries meaningful information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with this much behavioral nuance, the description is remarkably complete: it covers status transitions, timing distributions, output fields, edge cases, polling behavior, and caveats like null agentMessage. Even with an output schema present, the description adds indispensable context an agent needs to interpret results correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds some context by explaining that jobId can come from either find_leads or continue_campaign, but it does not substantially add meaning to the limit parameter beyond what the schema already states.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Returns the status and any results of a find_leads or continue_campaign job, by jobId.' This clearly identifies what the tool does and differentiates it from the sibling launch tools find_leads and continue_campaign.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description makes it clear that fetch_leads is the polling/status tool for find_leads and continue_campaign jobs, and explains the job lifecycle and wait behavior. It does not explicitly state 'use this instead of X' the way the calibration high example does, but the context strongly implies when it is appropriate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources