Respondent Pool Tools — MCP Tool Reference¶
Pool tools manage reusable groups of respondents for campaigns. Pools can be created manually or generated from a sampling strategy for representative samples. Strategy-generated pools track quality scores, record the draw settings they were generated with (requested size, oversample factor, selection algorithm, email requirement, exclusions), and can be refreshed with those same settings as the respondent base changes. The strategy itself carries no draw settings, so one strategy can feed pools of different sizes.
list_respondent_pools¶
List all respondent pools, optionally filtered by project or name.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
project_id |
string |
No | — | Filter by project ID |
name |
string |
No | — | Case-insensitive substring filter |
limit |
integer |
No | 100 |
Maximum results to return |
Returns: { data: [...], count, limit }. Each item includes source_type, source_strategy_id, respondent_count, quality_score, and the five draw settings (requested_size, oversample_factor, selection_algorithm, require_email, exclude_respondent_ids) — all null on a pool with no recorded draw (manual, merged or split pools).
get_respondent_pool¶
Get a respondent pool by ID, including full respondent list and quality details.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
pool_id |
string |
Yes | — | Pool UUID |
Returns: Full pool object with id, name, description, project_id, source_type, source_strategy_id, respondent_ids, respondent_count, the five draw settings (requested_size, oversample_factor, selection_algorithm, require_email, exclude_respondent_ids; null when no draw is recorded), quality_score, quality_details, generated_at.
requested_size is what the draw asked for; respondent_count is how many members the pool actually has. They legitimately differ — oversampling, a shortfall of eligible respondents, or later manual edits.
create_respondent_pool¶
Create a new respondent pool (manual source type).
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
name |
string |
Yes | — | Pool name |
description |
string |
No | — | Pool description |
project_id |
string |
No | — | Project for organization |
respondent_ids |
string[] |
No | — | Initial respondent IDs |
Returns: { id, name, description, project_id, respondent_count }
add_respondents_to_pool¶
Add respondents to an existing pool. Duplicates are silently skipped.
A pool holds only its own project's respondents, so everyone who can read the pool can read every member. A respondent of another project is refused, even when you can read them. In an organization that shares its respondent panel, and for a pool with no project, any respondent of the organization can be added.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
pool_id |
string |
Yes | — | Pool UUID |
respondent_ids |
string[] |
Yes | — | Respondent IDs to add |
Returns:
remove_respondents_from_pool¶
Remove respondents from a pool.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
pool_id |
string |
Yes | — | Pool UUID |
respondent_ids |
string[] |
Yes | — | Respondent IDs to remove |
Returns:
generate_pool_from_strategy¶
Draw a new respondent pool from a sampling strategy. The selection algorithm picks respondents matching the strategy's target demographic distributions. The draw settings are inputs here, not properties of the strategy, and the new pool stores them so every refresh redraws the same way.
An advanced strategy cannot generate a pool
A strategy that carries outcome factors — factors built from survey response columns, appended by Advancing a Strategy — is refused here, and by preview_pool_generation and refresh_pool_from_strategy too. The error names the offending factors. An outcome factor's value comes from an answer, and pool selection runs before anyone has answered, so there is nothing to select on. Advanced strategies exist to grade a fielded sample; use a strategy whose factors are all respondent attributes to build one.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
strategy_id |
string |
Yes | — | Sampling strategy UUID |
pool_name |
string |
Yes | — | Name for the new pool |
description |
string |
No | — | Pool description |
project_id |
string |
No | — | Project ID. Defaults to the strategy's project |
requested_size |
integer |
Yes | — | Respondents this draw is for, before oversampling (> 0) |
oversample_factor |
float |
No | 1.0 |
Non-response buffer on requested_size (≥ 1; e.g. 1.2 = 20% extra) |
selection_algorithm |
string |
No | "greedy" |
"greedy" or "random_constrained" |
require_email |
boolean |
No | false |
Only respondents with an email address are eligible |
exclude_respondent_ids |
string[] |
No | [] |
Respondent UUIDs never eligible for this draw (e.g. an earlier wave) |
Invalid settings (a size of 0, an oversample below 1, an unknown algorithm, an exclusion that is not a respondent UUID) are refused before any respondent is read.
The draw considers only the respondents of the project the new pool belongs to, so a pool never takes in respondents that the project's other owners cannot see. The same holds when the pool is refreshed, whoever refreshes it. In an organization that shares its respondent panel, and for a pool with no project, the draw considers the whole panel.
Example:
{
"strategy_id": "...",
"pool_name": "Urban Millennials — main wave",
"requested_size": 200,
"oversample_factor": 1.2
}
Returns:
{
"pool_id": "...",
"pool_name": "Urban Millennials — main wave",
"strategy_id": "...",
"respondent_count": 240,
"requested_size": 200,
"effective_size": 240,
"quality_score": 0.94,
"quality_details": { },
"computation_time_ms": 145,
"warnings": []
}
effective_size is requested_size × oversample_factor (rounded down), the count the draw aims for. When too few respondents are eligible, the pool gets fewer members and warnings carries a shortfall message naming both sizes, for example Could not fill the draw: 90 of 120 drawn (requested 100 x oversample 1.2); only 90 candidates eligible.
The created pool has source_type: "strategy" and stores the source_strategy_id and the draw settings for later refresh. To draw at a different size, generate another pool from the same strategy.
preview_pool_generation¶
Preview pool generation without creating the pool. Runs the same draw as generate_pool_from_strategy and returns quality metrics.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
strategy_id |
string |
Yes | — | Sampling strategy UUID |
project_id |
string |
No | — | The project the pool would belong to, as for generate_pool_from_strategy. Defaults to the strategy's project |
max_preview |
integer |
No | 100 |
Max respondent IDs to include in preview |
It also takes the same draw settings as generate_pool_from_strategy: requested_size (required), oversample_factor, selection_algorithm, require_email, exclude_respondent_ids.
Returns:
{
"eligible_count": 500,
"requested_size": 200,
"effective_size": 200,
"selected_count": 200,
"quality_score": 0.94,
"quality_details": { },
"sample_respondent_ids": ["..."],
"computation_time_ms": 130,
"warnings": []
}
refresh_pool_from_strategy¶
Redraw a strategy-generated pool in place against the current respondent base. Only works for pools with source_type: "strategy". Refresh takes no draw settings: it redraws with the requested size, oversample factor, algorithm, email requirement and exclusions the pool stored when it was generated, against the strategy's current factors. To change the size, generate a new pool and assign it to the campaign.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
pool_id |
string |
Yes | — | Pool UUID (must be strategy-generated) |
Returns:
{
"pool_id": "...",
"previous_size": 195,
"new_size": 200,
"added": 10,
"removed": 5,
"requested_size": 200,
"effective_size": 200,
"quality_score": 0.96,
"quality_details": { },
"warnings": []
}
delete_respondent_pool¶
Delete a respondent pool.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
pool_id |
string |
Yes | — | Pool UUID |
Returns: { pool_id, deleted }
Error Handling¶
Common Errors¶
| Scenario | Response |
|---|---|
| Pool not found | {"error": "Pool {id} not found"} |
| Strategy not found, or in a project the caller cannot read (generate, preview) | {"error": "Strategy {id} not found"} |
| No eligible respondents | {"error": "No eligible respondents available for this strategy"} |
| Not strategy-generated | {"error": "Pool was not generated from a strategy — cannot refresh"} |
| Source strategy deleted, or in a project the caller cannot read (refresh) | {"error": "Source strategy {id} not found"} |
| Strategy pool with no recorded draw (refresh) | Conflict: the pool records no draw settings, so it cannot be refreshed. Generate a new pool from the strategy at the size you want and assign it to the campaign instead. |
| Not an owner of the pool's project | {"error": "forbidden", "detail": "caller is not an owner of this project and lacks an admin role"} |
Duplicate Handling¶
add_respondents_to_pool uses set operations to detect duplicates. Duplicates are silently skipped and reported in the duplicates_skipped count — no error is raised.
Source Type Tracking¶
| Source Type | Created By | Can Refresh |
|---|---|---|
"manual" |
create_respondent_pool |
No |
"strategy" |
generate_pool_from_strategy |
Yes, with the pool's stored draw settings |
Eligibility Filtering¶
Every draw (generate, preview, refresh) starts from the respondents you can see: the whole panel in a private organization or for an administrator, otherwise the respondents of the projects you own. This holds for the organization's default strategy too, so a draw never names a respondent list_respondents would not show you.
It then filters them before selection, using the draw's settings:
- If
require_emailis set, respondents without email are excluded - Respondents in
exclude_respondent_idsare excluded - If no eligible respondents remain, generate and refresh return an error (a refresh never empties a pool); preview reports
eligible_count: 0
A member removed from a pool by hand is not added to exclude_respondent_ids, so the next refresh can draw them again.