Skip to main content
Glama

Track Prospects

track_prospects

A person belongs to exactly one campaign, so someone already tracked in another campaign is reported in skipped rather than added twice; pass move_existing=True to move them into this agent instead. A durable contact left without a campaign (its campaign was deleted) is instead adopted straight in and reported in adopted. Someone already on THIS campaign whom the user stopped pursuing (a 'skipped' stage) is reported in removed, not re-enrolled and not sent to — clear the skip with update_prospect first if the user explicitly wants them back. Someone with no usable identifier (no LinkedIn profile URL, username slug, provider ID or email — say, only a company page URL) is reported in unrecognized and not added; the rest of the batch is.

On an agent with a define_sequence flow, tracking IS enrollment — the flow fires each prospect's first touch itself (see the returned flow field); never queue a first send for prospects you just tracked. Dict with created and updated counts; moved, adopted, removed, skipped and unrecognized details, plus unrecognized_note naming anyone not added; and total, the number of items.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
itemsYesPeople to add (see ProspectItem). Each carries a `person` with the identifiers you already hold (LinkedIn URL / slug, email, or provider_id) copied verbatim from the tool result that surfaced them — never a slug rebuilt from a display name, which resolves to the wrong person. The display name goes on `person.display_name`, taken from the same row as the identifier — a name that shares no token with the LinkedIn name already on file for its ID rejects the whole call. Optional freeform `data` per item.
agent_idYesID of the agent to add prospects to
on_behalf_ofNoAn 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.
move_existingNoMove people tracked in another campaign into this one instead of skipping them. Destructive — it cancels whatever was still queued for them, so only pass it on an explicit user request.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • addedInput schema / properties / on_behalf_of
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "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."
      +}
  2. Changed2 schema fields changed
    • changedInput schema / properties / items / description
      Previous value: -"People to add (see ProspectItem). Each carries a `person` with the\nidentifiers you already hold (LinkedIn URL / slug, email, or\nprovider_id) copied verbatim from the tool result that surfaced them —\nnever a slug rebuilt from a display name, which resolves to the wrong\nperson. Junk like a company URL or 'N/A' is rejected. The display name\ngoes on `person.display_name`, taken from the same row as the identifier\n— a name that shares no token with the LinkedIn name already on file for\nits ID rejects the whole call. Optional freeform `data` per item."New value: +"People to add (see ProspectItem). Each carries a `person` with the\nidentifiers you already hold (LinkedIn URL / slug, email, or\nprovider_id) copied verbatim from the tool result that surfaced them —\nnever a slug rebuilt from a display name, which resolves to the wrong\nperson. The display name goes on `person.display_name`, taken from the\nsame row as the identifier — a name that shares no token with the\nLinkedIn name already on file for its ID rejects the whole call.\nOptional freeform `data` per item."
    • changedInput schema / properties / items / items / properties / person / description
      Previous value: -"The person to track. Pass the identifiers you already hold (LinkedIn URL / slug, provider_id, email) copied verbatim from the tool result that surfaced them — never a slug rebuilt from a display name, which resolves to a different real person. A company URL, domain, free text, or 'N/A' is rejected."New value: +"The person to track. Pass the identifiers you already hold (LinkedIn URL / slug, provider_id, email) copied verbatim from the tool result that surfaced them — never a slug rebuilt from a display name, which resolves to a different real person. A company page URL, free text, or 'N/A' isn't an identifier: a person with nothing else isn't added and comes back in `unrecognized`. A bare company domain such as acme.com, by contrast, rejects the whole call."
  3. Changed1 schema field changed
    • changedInput schema / properties / items / description
      Previous value: -"People to add (see ProspectItem). Each carries a `person` with the\nidentifiers you already hold (LinkedIn URL / slug, email, or\nprovider_id) copied verbatim from the tool result that surfaced them —\nnever a slug rebuilt from a display name, which resolves to the wrong\nperson. Junk like a company URL or 'N/A' is rejected. The display name\ngoes on `person.display_name`; optional freeform `data` per item."New value: +"People to add (see ProspectItem). Each carries a `person` with the\nidentifiers you already hold (LinkedIn URL / slug, email, or\nprovider_id) copied verbatim from the tool result that surfaced them —\nnever a slug rebuilt from a display name, which resolves to the wrong\nperson. Junk like a company URL or 'N/A' is rejected. The display name\ngoes on `person.display_name`, taken from the same row as the identifier\n— a name that shares no token with the LinkedIn name already on file for\nits ID rejects the whole call. Optional freeform `data` per item."
  4. Changed3 schema fields changed
    • addedInput schema / properties / agent_id
      Added value: +{
      +  "description": "ID of the agent to add prospects to",
      +  "type": "integer"
      +}
    • removedInput schema / properties / task_id
      Removed value: -{
      -  "description": "ID of the task to add prospects to",
      -  "type": "integer"
      -}
    • changedInput schema / required
      Previous value: -[
      -  "task_id",
      -  "items"
      -]New value: +[
      +  "agent_id",
      +  "items"
      +]
  5. First observed

TDQS

A4.9/5.0
Behavior5/5

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

With annotations readOnlyHint=false and destructiveHint=false, the description still adds substantial behavioral context: cross-agent dedup, skipped/adopted/removed/unrecognized buckets, identifier requirements, move_existing behavior, and automatic enrollment on define_sequence flows. This tells the agent what happens to a batch beyond a simple write operation.

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

Conciseness5/5

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

The description is front-loaded with a summary, then structured into compact paragraphs for dedup behavior, item requirements, and return shape. Despite its length, every sentence carries a distinct rule or edge case, and the returns block is necessary because there is no output schema.

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?

Given four parameters, nested item objects, no output schema, and minimal annotations, the description covers the missing pieces: return buckets, dedup outcomes, identifier validity, move_existing effects, and sequence enrollment. An agent has enough information to invoke it correctly in complex scenarios.

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

Parameters4/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 cross-cutting meaning for items and move_existing by explaining campaign membership, dedup outcomes, and adoption/removal behavior, though it does not add new syntax or formatting details for parameters already documented in the schema.

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: "Bulk-add people (prospects) to an agent's outreach list with cross-agent dedup." It explicitly differentiates from the sibling tool by saying "For companies to monitor, call track_monitored_companies instead," so an agent can select it correctly without opening schemas.

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

Usage Guidelines5/5

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

It names when to use this tool versus the alternative, then gives explicit conditions for edge cases: when people are skipped, adopted, removed, or unrecognized, and when to pass move_existing=True. It also warns not to queue a first send after tracking on a define_sequence flow, which is actionable invocation guidance.

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