--- name: run-a-study description: Design and run a new LLMEKNOW study end to end. Use when the person wants to measure how AI models describe a brand, product, topic or issue, set up a market, segments or campaign, or start, retry or resume a wave. Covers the brief, setup tools, showing the cost, getting explicit agreement, waves_run with confirm_estimate_cents, and polling waves_status. --- # Run a study A study is a campaign: questions asked of several AI models, as a baseline and as members of audience segments. Running a wave spends from the organisation's prepaid wallet. **Never start spend without the person's explicit yes to the cost you showed them.** Run `getting-started` first if you have not called `account_status` this session. ## 1. Brief Agree these with the person in one short exchange before creating anything: - **Subject**: the brand, product, topic or issue, and any competitors or alternatives that matter. - **Market**: who and where, for example "adults in South Africa considering a new car". - **Segments**: two to four audience groups worth comparing, for example by age or region. The baseline (no segment) is always included. - **Questions**: three to eight questions a real person might ask an AI assistant. Keep them neutral and unbranded when the aim is to see who the AI names unprompted ("Which banks are best for a first account?"), and name the subject only when the aim is to see how it is described. - **AI models**: leave `selected_providers` unset unless the person names models. ## 2. Set up 1. `markets_list`. Reuse a market that already fits (check with `markets_inspect`); otherwise `markets_create` with `name`, `description`, `geography`, `category` and an `idempotency_key`. 2. `segments_list` for the market. Reuse fitting segments. For a new one, read an existing segment with `segments_inspect` to see the attribute keys this market uses, then `segments_create` with `market_id`, `name`, `attribute_constraints` and an `idempotency_key`. Constraint shapes: `{constraint: fixed, value}`, `{constraint: range, min, max}`, `{constraint: set, values}`, `{constraint: open}`, `{constraint: excluded}`. 3. `campaigns_create` with `market_id`, `name`, `description`, `questions` as `[{question_text, question_order}]`, `segments` as `[{segment_id, individual_count}]`, and an `idempotency_key`. Set `citation_mode: true` if the person wants sources and the organisation has that feature (see `account_status`). - If `campaigns_create` has no `segments` argument, create the campaign, then call `campaigns_update` with `segments`. If neither tool takes segments, tell the person the campaign will be baseline only and that segments can be linked in the web app. - Audience members for each segment are generated when the wave runs. Do not call `individuals_generate` unless the person asks to see members before a wave; it spends without an estimate, so ask first. Use one `idempotency_key` per create and reuse it on a retry, so a timeout never creates a duplicate. ## 3. Show the cost and get agreement 1. `campaigns_estimate` with `campaign_id`. It spends nothing. 2. Show the person `estimate_cents` converted to their currency (divide by 100, use `currency`), the wallet balance, and one line on what drives the figure (models, questions, segments). 3. Ask a direct question: "Shall I start this wave for that amount?" 4. Continue only on a clear yes in reply to that question. An instruction given before the cost was shown ("set it up and run it") is not agreement. Silence, a change of subject or "maybe" is not agreement. ## 4. Run Call `waves_run` with `campaign_id` and `confirm_estimate_cents` set to the exact `estimate_cents` the person agreed to. - `confirmation_required` or `estimate_mismatch` (409): the cost moved. Show the new `estimate_cents` and ask again. Never echo a figure the person has not seen. - `billing_gate`, `spend_cap_exceeded`, `slot_required`: human-only. Relay `fix` and `url`, then stop. - `data.replayed: true`: a wave was already queued or running; nothing new was charged. Poll it. - If the call times out, call `waves_status` before trying again. ## 5. Wait Poll `waves_status` with `campaign_id` about every 60 seconds, never more often than every 30 seconds; every poll is an audited call. Give the person a short progress note now and then, not after every poll. - Done when `analysis_ready` is true. Check `extraction_status` first: `failed` means no extracted responses are coming, so say so instead of reading metrics. - `paused_reason` set by the spend breaker: call `waves_resume` with `campaign_id` and `wave_id`. Its 409 `confirmation_required` body carries the remaining cost: show it, get a new yes, then call again with `confirm_estimate_cents`. - Failed responses: `waves_list_failed_runs` explains them. `waves_retry` re-runs only the failed ones; call it without `confirm_estimate_cents`, show the cost from its 409 body, get a yes, then call again with the echo. - The person wants to stop: `campaigns_pause`. ## 6. Read Hand over to the `read-the-results` skill with the campaign id and `default_analysis_wave_id` from `waves_status`.