Preview, then Activate
A worked agent session for the frequency filter: confirm the audience is
ready, preview exactly what a frequency range would export, then activate
exactly that range - with the server proving the two match. Every call below
is a plain MCP tools/call; the argument objects are shown as the agent sends
them and the results as excerpts of what comes back.
The numbers are from a real run. The only thing that changes between runs is the ids.
Before you start: a connected agent (Getting started)
and a 104 Completed audience that was built with a frequency analysis:
analyses: {"frequency": true} (POI), {"apps_frequency": true} (Apps) or
{"web_frequency": true} (WebDomain) on create_audience, or the matching
toggle in the Audience Manager. Audiences built without one carry no frequency
distribution and are refused by the preview - the filter is never
approximated, and no analysis can be added after the build.
1. Confirm the audience is ready
get_audience {"id": 88}{
"id": 88,
"name": "Kubota Test Audience US L30",
"status": { "id": 104, "name": "Completed" },
"is_activation_allowed": true,
"results_count": 205188
}status.id must be 104 and is_activation_allowed should be true - the
frequency filter does not change the eligibility gates, so an audience that is
blocked here stays blocked whatever range you pick.
2. Preview the range
Ask for the range you intend to export. The response is the exact device count
the Audience Manager shows as Limit Audience for the same Freq. Range:
the audience’s stored frequency histogram (distinct visit days -> devices)
summed over the inclusive [freq_min, freq_max] range, which is the same
predicate the export applies. Nothing is created, queued, exported, scheduled
or billed, so preview as many ranges as the conversation needs.
preview_activation {"audience_id": 88, "freq_min": 2, "freq_max": 31}{
"audience": { "id": 88, "status": { "id": 104, "name": "Completed" }, "is_activation_allowed": true },
"dataset_type": "POI",
"analysis_type": "frequency",
"recency": [ { "dataset_type": "POI", "start_date": "07/01/2026", "end_date": "07/31/2026" } ],
"source_count": 205188,
"histogram_total": 208389,
"filtered_count": 21656,
"frequency_bounds": { "min": 1, "max": 31 },
"histogram": [ { "index": 1, "counts": 186733 }, { "index": 2, "counts": 12904 }, "..." ],
"applied_filters": { "freq_limit": true, "freq_min": 2, "freq_max": 31 },
"filter_hash": "sha256:d6c9da3215a0f9d8902bab24c5e1b579f52cb11b6cbb76ca7ab8a032e0e1151b",
"method": "histogram_sum",
"as_of": "2026-08-20 23:18:11"
}How to read it:
filtered_countis exact - 21,656 devices were seen on 2 or more distinct days. This is the number to tell the user.- An open-ended “N+” range is
freq_min: Nwithfreq_maxset tofrequency_bounds.max. “1+” therefore returnshistogram_total. source_countis the audience total shown on the audience itself (an approximate distinct count) andhistogram_totalthe exact histogram sum, so the two can differ slightly. Quotefiltered_count, not a difference.recencyis the audience’s own date window, echoed read-only. It is not a preview input: to count against another window, build (orestimate_audience_size) a new audience.- Keep
filter_hash- it is the proof for step 3. Onlyaudience_id,freq_minandfreq_maxare accepted; any other field is rejected rather than ignored.
3. Activate exactly that range
Discover the destination as usual - lookup_reference with dataset common
and catalogs endpoint-connections, then pricing-models and datastreams
for that connection’s partner_id (see the
Tools Reference). Then send the same
audience_id, freq_min and freq_max you previewed, with freq_limit: true
and the filter_hash unchanged:
create_activation {
"audience_id": 88,
"endpoint_connection_id": 12,
"pricing_model_id": 3,
"datastreams": [ { "id": 7, "status": true } ],
"description": "Kubota 2+ visit days",
"freq_limit": true,
"freq_min": 2,
"freq_max": 31,
"filter_hash": "sha256:d6c9da3215a0f9d8902bab24c5e1b579f52cb11b6cbb76ca7ab8a032e0e1151b",
"idempotency_key": "kubota-2plus-2026-08-25"
}{
"id": 501,
"status": { "id": 100, "name": "Initiating" },
"audience": { "id": 88, "name": "Kubota Test Audience US L30" },
"filters": { "freq_limit": true, "freq_min": 2, "freq_max": 31 },
"filter_hash": "sha256:d6c9da3215a0f9d8902bab24c5e1b579f52cb11b6cbb76ca7ab8a032e0e1151b"
}The server recomputes the hash for the requested range on the audience as it
is stored now. A different range, or an audience that was rebuilt since the
preview, is rejected - the activation never applies anything other than what
was previewed. When that happens, run preview_activation again and use the
fresh hash.
4. Poll and read back
get_activation {"id": 501}Poll until data[0].status.id is 104 (Completed) - 105 DataStreaming
comes first and means delivery is still in progress. The read echoes filters
and filter_hash, so any later reader can see which range the export applied.
Delivered data lands at the destination configured on the endpoint connection.
In this run the delivered file held exactly 21,656 device ids - the previewed
count.
Rules for the agent
- Never send
freq_min/freq_maxwithout an explicitfreq_limit; the request is rejected.freq_limit: falsewith bounds is an explicit “export the whole audience”. - A preview refusal (“not supported for this audience”) means the audience has
no usable frequency distribution - it was built without the Frequency
analysis, is a lookalike or cohort, uses a day-part frequency, or carries
more than one frequency analysis. Say so; do not estimate a count. If it
was built without one, the fix is a new
create_audiencewith theanalyseskey that matches its dataset. - Recency is fixed by the audience definition. Do not try to pass dates.
- Preview is a read (120 requests/min per token); create is a write
(30 requests/min). Pass an
idempotency_keyon the create so a retry can never activate twice.