# ICSS: agent guide

ICSS (Intent-Conditioned Silicon Sampling) samples synthetic respondents from intent states observed in search behavior (CEP, nano intent, KBF, constraint, avoidance, consideration, journey stage) instead of demographics, and runs surveys, FGDs and 1:1 chats with them. Marketers and researchers use it to test hypotheses before real fieldwork. Data comes from ListeningMind search data (DaaS, SERP) plus stored CEP Finder and Intent KG runs, for Korea, Japan and the US. It also includes a distinctive brand asset (DBA) recognition test.

## Connect
- MCP: `https://daas-icss.listeningmind.ai/mcp` (Streamable HTTP). Start with `app_guide`.
- Browser agents: tools are registered on every page through WebMCP (`document.modelContext`).
- REST: `https://daas-icss.listeningmind.ai/.well-known/openapi.json`

## Approval
- read and action tools run at once.
- run and delete tools need a person's approval. Over MCP the tool returns `confirm_url`; show it to the person, then call `confirmation_status` with the token until state is done.
- In the browser the page shows the person a confirm box.

## Workflow
1. `get_config` (read): Check that the LLM and data back-ends are on.
2. `analyze_topic` (run): Get search-behavior data for each keyword; merge several keywords yourself.
3. `find_cep_run` (read): Look for a stored CEP Finder run for the topic (free).
4. `get_cep_states` (read): Load that run as the intent-state distribution P(IntentState).
5. `start_cep_build` (run): Only if none exists, start a new CEP analysis (spends credits, needs confirmation).
6. `get_cep_job` (read): Poll until done, then load the result with get_cep_states.
7. `get_grounding_pack` (read): Check for a stored grounding pack.
8. `build_grounding_pack` (action): If missing, build one from stored runs only (0 credits).
9. `get_grounding_job` (read): Poll the grounding job until done.
10. `get_evidence` (read): Get the CEP and KG evidence summary for persona grounding.
11. `probe_ai_overview` (run): Probe AI Overviews to fill category-specific avoidance and criteria.
12. `get_cluster_serp` (run): For a custom panel on one cluster, collect that cluster's SERP evidence.
13. `get_keyword_info` (run): Add gender/age and volume for the chosen keywords.
14. `ask_llm` (run): Generate question ideas, survey batches, FGD turns and summaries with state-first persona prompts.
15. `save_run` (action): Save the snapshot on the server so it opens at #run=ID.
16. `list_runs` (read): Find saved stories to reopen.

## Inputs
Brand or category keyword(s), market (kr/jp/us); optional: 2-5 comparison brands, panel conditions (market distribution or one cluster, size), survey questions. For the asset test: target brand, aliases, competitors, masked asset descriptions or images.

## Outputs
Search data summary (demand, gender/age, journeys, clusters), CEP state distribution with evidence labels, grounding pack with sufficiency verdict, synthetic panel roster (7-element state vectors), survey result distributions and open-answer themes, FGD transcript and summary, a saved story (#run=ID), per-asset fame and uniqueness quadrant.

## Cost and time
Topic analysis, comparison and SERP collection use the Data API and are cached 12 h on the server (exact credits are not reported by the app). Reusing stored CEP and KG runs costs 0 credits. A new CEP build costs about 30k-40k (standard) or a measured 66k-133k (deep) credits; a KG build 38k-46k. Surveys and FGDs make one LLM call per respondent batch (Gemini 2.5 Flash by default). The asset test uses LLM calls only (assets x models x repeats).

## Limits
Markets: kr, jp, us only. Panel sampling (state vectors, individual-difference axes), survey prompt construction, aggregation, the hallucination gate and CSV/Excel export run in browser code; the HTTP API provides data and a raw LLM call. To reproduce a UI result an agent must write the state-first prompts itself and call ask_llm. Results are kept in browser localStorage and on the server (/api/runs); the UI uploads automatically after a survey, an agent must call save_run itself. Synthetic and AI answers are not consumer responses and need calibration with a real panel. Builds spend credits; call them only after human confirmation.

## Method (how the analysis works)
1. Pull search-behavior data per keyword (demand, gender and age, journeys, clusters, SERP) and compare brands side by side if given.
2. Load a stored CEP Finder run as the intent-state distribution P(IntentState), building a new one only when none exists.
3. Ground personas with the CEP Finder and Intent KG evidence summary and probe AI Overviews for category-specific avoidance and criteria.
4. Sample a synthetic panel from intent states (CEP, nano intent, KBF, constraint, avoidance, consideration, journey) instead of demographics.
5. Run surveys, FGDs or 1:1 chats with state-first persona prompts, aggregate the answers and save the story.

## Reading the result
- results holds the answer distribution per question and the open-answer themes; respondents and panel_size tell how many synthetic answers they rest on.
- The panel roster shows each respondent's 7-element state vector, so you can trace an answer back to a CEP and its constraints.
- cepStates and the grounding pack's sufficiency verdict show how well the panel is grounded in search evidence.
- In the asset test, each asset gets fame, uniqueness and a quadrant.
- Synthetic and AI answers are not consumer responses; treat them as hypotheses to calibrate with a real panel.

## Requests this app answers well
- Run a price sensitivity survey on a 300-person synthetic panel of sunscreen buyers split by search intent
- Run a 6-person FGD on protein drinks in Japan and summarize why people hesitate to buy
- Test whether AI can name our brand from a masked description of our pack
- Before real research, check which of these 3 concept lines a panel prefers, as a hypothesis

## Continue in another app
- [Prompt Builder](https://daas-prompt.listeningmind.ai/llms.txt) (MCP `https://daas-prompt.listeningmind.ai/mcp`): When the panel shows which situations and criteria drive choice and you want to see whether AI answers recommend the brand there. Carry: The keyword, own brand and comparison brands, and the CEPs and KBF that mattered in the answers.

## Using the screens (browser agents)
- `describe_screen`: menus, tabs, fields and buttons of the current screen, and what the page is for
- `go_to`: open a menu or page of this app by its label or path
- `fill_field`: type a value into a field by its label (never presses run; runs go through the run tools, which ask the person)
- `read_this_page`: the text and ids of what the person is looking at

## The ListeningMind apps (same account, same tools, call any of them)
Each app has `/mcp`, `/llms.txt`, `/agents.md` and WebMCP on its pages. `family_apps` and `recommend_app` return this list with addresses.
- [ACO](https://daas-aco.listeningmind.ai/llms.txt): Diagnoses whether a product detail page can be cited by AI answers and used by shopping agents (MCP `https://daas-aco.listeningmind.ai/mcp`)
- [AOO](https://daas-aoo.listeningmind.ai/llms.txt): Measures whether AI agents can get real tasks done on a website (MCP `https://daas-aoo.listeningmind.ai/mcp`)
- [Brand Finder](https://daas-brand.listeningmind.ai/llms.txt): Which brands lead search by generation or field, and what their brand assets are (MCP `https://daas-brand.listeningmind.ai/mcp`)
- [Brand Naming Agent](https://daas-naming.listeningmind.ai/llms.txt): Creates and checks brand name candidates grounded in search data (MCP `https://daas-naming.listeningmind.ai/mcp`)
- [Brand Wiki](https://daas-wiki.listeningmind.ai/llms.txt): Turns a brand website into the entities, wiki pages and evidence AI assistants read (MCP `https://daas-wiki.listeningmind.ai/mcp`)
- [CEP Finder](https://daas-cep.listeningmind.ai/llms.txt): In which situations do people start looking for this category (category entry point map) (MCP `https://daas-cep.listeningmind.ai/mcp`)
- [Creative Finder](https://daas-creative.listeningmind.ai/llms.txt): Finds purchase situations (CEP) in search data and drafts a creative, an image and a video for each (MCP `https://daas-creative.listeningmind.ai/mcp`)
- [Demand Forecast](https://daas-forecast.listeningmind.ai/llms.txt): What category demand looks like in the next 3-6 months and when to launch or campaign (MCP `https://daas-forecast.listeningmind.ai/mcp`)
- [Funnel Leak Finder](https://daas-funnel.listeningmind.ai/llms.txt): Where category search journeys leak to competitors (MCP `https://daas-funnel.listeningmind.ai/mcp`)
- [GEO Audit](https://daas-geo.listeningmind.ai/llms.txt): Checks whether a web page is ready to be read and cited by search engines and AI answer engines (MCP `https://daas-geo.listeningmind.ai/mcp`)
- [Intent KG](https://daas-intent.listeningmind.ai/llms.txt): What people look for about a topic, why, and how they choose (Intent Knowledge Graph) (MCP `https://daas-intent.listeningmind.ai/mcp`)
- [Prompt Builder](https://daas-prompt.listeningmind.ai/llms.txt): Finds what consumers ask AI and builds managed brand prompts with AI visibility (MCP `https://daas-prompt.listeningmind.ai/mcp`)
- [Pulse Finder](https://daas-pulse.listeningmind.ai/llms.txt): What is rising in search for a gender and age segment right now (MCP `https://daas-pulse.listeningmind.ai/mcp`)
- [Smart Store Suite](https://daas-store.listeningmind.ai/llms.txt): Which Smart Store products to grow, and how to rewrite their titles and detail pages in searchers' words (MCP `https://daas-store.listeningmind.ai/mcp`)
- [Taste Finder](https://daas-taste.listeningmind.ai/llms.txt): In what sensory and emotional words do people choose this (consumer taste report from search data) (MCP `https://daas-taste.listeningmind.ai/mcp`)
- [ListeningMind Data API](https://daas.listeningmind.ai/llms.txt): the search data behind every app (MCP `https://daas.listeningmind.ai/mcp`) · [glossary](https://daas.listeningmind.ai/en/glossary) · [all apps](https://daas.listeningmind.ai/en/apps)

## Run stages
- `start`: Start
- `cep`: Looking up CEP Finder runs
- `kg`: Looking up Intent KG
- `related`: Collecting related topics
- `assemble`: Assembling the pack

## All tools
### get_config
Returns which back-ends are switched on: llm (bool), provider, chain, model, daas (bool), maistro (bool). Call first; if llm is false the survey, FGD and question generation cannot run. Read only, free. Usually followed by: analyze_topic.
`GET /api/config`

### analyze_topic
Pulls the full search-behavior analysis for one keyword (demand, gender/age audience, search journeys, behavior clusters, SERP) from the maistro-lmpipe analyze service. This is the first data step of the app; the UI calls it once per keyword and merges the results in the browser. Cached on the server for 12 hours. Returns the raw analysis JSON. Spends ListeningMind Data API credits or paid model calls. Over MCP a person approves it first (you get a confirm link); in the browser the page asks the person. Cost: ListeningMind Data API usage through maistro-lmpipe (amount not reported by the app); free when cached. Time: about 10-60 seconds. Usually followed by: get_evidence, find_cep_run, get_grounding_pack.
`POST /api/analyze`
- `q` (required): Keyword or brand/category to analyze.
- `locale`: Market code.
- `language`: Optional output language passed through to the analyzer (e.g. ko, ja, en).

### get_keyword_info
Calls the ListeningMind keyword_info endpoint through the app proxy: monthly volume, trend, competition, CPC, gender/age demography and intents for a list of keywords. The UI uses it to add demography and volume to the chosen cluster keywords. Cached 12 hours. Spends ListeningMind Data API credits or paid model calls. Over MCP a person approves it first (you get a confirm link); in the browser the page asks the person. Cost: ListeningMind Data API credits (keyword_info, per keyword).
`POST /api/daas/keyword_info`
- `keywords` (required): Keywords to look up.
- `gl` (required): Market code.
- `data_type`: keyword_info data type; the server uses 'all' when omitted.

### get_evidence
Looks up existing CEP Finder runs and Intent KG runs that match the topic and returns a short evidence summary (top CEPs with keywords, KBF, constraints, brands; KG nodes such as KBF, CEP, heuristics, pitfalls). Reads stored runs only, never builds. Returns {topic, locale, cep, kg, cep_error, kg_error}. Read only, free.
`POST /api/evidence`
- `q` (required): Topic label or keyword.
- `locale`: Market code.
- `alt`: Alternative topic names to try when matching stored runs.

### compare_brands
Runs the maistro-lmpipe compare analysis for 2 to 5 brands or items in one market (search demand, audience and intent side by side). The UI starts it when the user enters comparison items. Cached 12 hours. Spends ListeningMind Data API credits or paid model calls. Over MCP a person approves it first (you get a confirm link); in the browser the page asks the person. Cost: ListeningMind Data API usage through maistro-lmpipe (amount not reported).
`POST /api/compare`
- `items` (required): 2 to 5 brand or item names.
- `locale`: Market code.
- `language`: Optional output language (ko, ja, en).

### get_category_journey
Calls the maistro-lmpipe category scope analysis that the UI uses as the substrate for the 5-stage consumer decision journey (CDJ) view. Returns the top_n category keywords with stage signals. Cached 12 hours. Spends ListeningMind Data API credits or paid model calls. Over MCP a person approves it first (you get a confirm link); in the browser the page asks the person. Cost: ListeningMind Data API usage through maistro-lmpipe (amount not reported).
`POST /api/cdj`
- `q` (required): Topic label or keyword.
- `locale`: Market code.
- `top_n`: How many category keywords to return (UI sends 40).

### get_analysis_prompt
Fetches a purpose-specific analysis prompt template from maistro-lmpipe (first 4,000 chars of analysis_prompt). The UI uses it to build insight prompts. Returns {id, analysis_prompt, version}. Read only, free.
`GET /api/prompts/{prompt_id}`
- `prompt_id` (required): Prompt id (lowercase letters and underscores only).
- `language`: Prompt language.
- `audience`: Audience of the prompt (UI sends marketer).

### probe_ai_overview
Collects Google AI Overview and People Also Ask text for the keyword plus probe queries such as 'keyword + downsides / side effects / caveats' in the market language. The UI uses it to fill category-specific avoidance and decision criteria in the intent state vector. Returns {keyword, gl, queries, aio:[{text, from}], paa:[{q, from}]}. Spends ListeningMind Data API credits or paid model calls. Over MCP a person approves it first (you get a confirm link); in the browser the page asks the person. Cost: ListeningMind SERP Data API credits, 4 queries by default (keyword + 3 probes). Time: about 10-40 seconds.
`POST /api/aio-probe`
- `keyword` (required): Topic keyword.
- `gl`: Market code.
- `probes`: Optional probe words (max 5). Default: the first 3 market-language probes.

### get_cluster_serp
For up to 6 keywords of the chosen search cluster, collects AI Overview text, People Also Ask, people-also-search-for and top organic titles, merged and de-duplicated. The UI uses it when a custom panel is built from one cluster. Returns {aio, paa, pasf, organic, per_keyword, n_keywords}. Spends ListeningMind Data API credits or paid model calls. Over MCP a person approves it first (you get a confirm link); in the browser the page asks the person. Cost: ListeningMind SERP Data API credits, one SERP per keyword.
`POST /api/cluster-serp`
- `keywords` (required): 1 to 6 cluster keywords.
- `gl`: Market code.

### find_cep_run
Searches the CEP Finder run history for a run that matches the topic in the same market (prefers deep over standard over quick, and the market language). Free. Returns {found, run, candidates:[{run_id, topic, keyword, gl, depth, score}]}. Read only, free. Usually followed by: get_cep_states, start_cep_build.
`POST /api/cep/find`
- `q` (required): Topic or keyword.
- `gl`: Market code.

### get_cep_states
Converts a CEP Finder run (cep_map) into the ICSS intent-state distribution: per CEP weight, volume, nano intents, KBF, constraints, avoidances, alternatives, thresholds, brands, journey, demography with evidence labels. This is P(IntentState) used to sample the synthetic panel. Free. Read only, free.
`POST /api/cep/states`
- `run_id` (required): CEP Finder run id from find_cep_run or get_cep_job.

### start_cep_build
Starts a new CEP Finder analysis for the keyword when no stored run exists. Returns {job_id}; poll get_cep_job, then call get_cep_states with the finished run_id. Spends Data API credits. Spends ListeningMind Data API credits or paid model calls. Over MCP a person approves it first (you get a confirm link); in the browser the page asks the person. Cost: Data API credits: standard about 30,000-40,000; deep measured 66,000-133,000. Time: several minutes. Usually followed by: get_cep_job.
`POST /api/cep/build`
- `keyword` (required): Seed keyword.
- `topic`: Optional topic label.
- `gl`: Market code.
- `depth`: Analysis depth: quick = about 6 CEPs, standard = about 10 CEPs, deep = about 25 CEPs with more nano intents and KBF per CEP. Deeper runs give richer intent states and cost more.
- `focal_brand`: Optional brand to focus on.
- `lang`: Output language.
- `ui_lang`: UI language of the CEP report.

### get_cep_job
Returns the CEP Finder job state: status, progress [{pct, msg, stage}] and run_id when finished. Repeat until status is done, completed or error. Read only, free. Waits up to about 45 s for 'status' to reach done, completed, error, failed; call again if not done. Usually followed by: get_cep_states.
`GET /api/cep/job/{job_id}`
- `job_id` (required): Job id from start_cep_build.

### get_grounding_pack
Reads the stored deep-grounding pack for a topic and market (CEP map states, related CEP runs, KG nodes and sentences with evidence grades, sufficiency verdict, credits). Returns {found:false} when none exists. Use full=1 for the whole pack as the UI does. Read only, free.
`GET /api/icss/grounding`
- `q` (required): Topic label.
- `gl`: Market code.
- `full`: '1' returns the full pack including sentences; otherwise a summary.

### list_grounding_packs
Lists all stored grounding packs: {items:[{topic, gl, built_at, sufficiency, stats, credits}]}. Read only, free.
`GET /api/icss/grounding/list`

### build_grounding_pack
Builds and saves a grounding pack from existing CEP Finder and Intent KG runs for the topic and related topics, without starting any new build (0 credits). Returns {job_id}; poll get_grounding_job. Changes saved data in the app; no credits. Time: about 10-60 seconds. Usually followed by: get_grounding_job.
`POST /api/icss/ground`
- `q` (required): Topic label.
- `gl`: Market code.
- `alt`: Up to 5 alternative names of the topic.
- `related`: Up to 12 related topics (cluster labels, top keywords, CEP seeds) to pull in as well.
- `related_max`: Max related topics to pull in (1-20). Server default 8 when omitted; the UI sends its field value (default 10). 0 is treated as 8.

### build_grounding_pack_new
Same as build_grounding_pack but also starts a new CEP Finder build (cep_build) and/or a new Intent KG build (kg_build) when stored runs are missing. Requires confirm_credits=true, which this tool sends. Returns {job_id}; poll get_grounding_job. Spends ListeningMind Data API credits or paid model calls. Over MCP a person approves it first (you get a confirm link); in the browser the page asks the person. Cost: Data API credits: CEP deep 66,000-133,000, standard about 30,000-40,000; KG 38,000-46,000. Time: several minutes to tens of minutes. Usually followed by: get_grounding_job.
`POST /api/icss/ground`
- `q` (required): Topic label.
- `gl`: Market code.
- `alt`: Up to 5 alternative names of the topic.
- `related`: Up to 12 related topics.
- `cep_build`: Depth of a new CEP build when no stored run exists; omit to reuse only. The UI offers standard and deep.
- `kg_build`: Start a new Intent KG build when no matching KG exists.
- `related_max`: Max related topics to pull in (1-20). Server default 8 when omitted; the UI sends its field value (default 10). 0 is treated as 8.

### get_grounding_job
Returns the grounding job: status (running, done, error), stage (start, cep, kg, related, assemble), steps log, and a pack summary when done. Repeat until done or error, then call get_grounding_pack with full=1. Read only, free. Waits up to about 45 s for 'status' to reach done, error; call again if not done. Usually followed by: get_grounding_pack.
`GET /api/icss/ground/job/{job_id}`
- `job_id` (required): Job id from build_grounding_pack.

### ask_llm
Sends one prompt to the server LLM chain (Gemini first, then OpenAI on failure; 75 s limit per provider) and returns {text, provider}. The UI builds every synthetic-respondent prompt in the browser (state-first persona: CEP, nano intent, KBF, constraint, avoidance, consideration, journey, then demography as reference) and calls this for question suggestions, survey batches, open-answer theming, FGD turns and summaries. An agent must build those prompts itself. Spends ListeningMind Data API credits or paid model calls. Over MCP a person approves it first (you get a confirm link); in the browser the page asks the person. Cost: one paid LLM call (Gemini 2.5 Flash by default). Time: 5-75 seconds.
`POST /api/llm`
- `prompt` (required): Full prompt text.
- `nothink`: Disable Gemini thinking tokens (UI sets true for jp and us markets so long batches are not cut off).

### save_run
Saves a full session snapshot (data, panel, questions, results, FGD log, chats) on the server so it opens at /#run=<id> on any PC. The UI does this automatically after a survey finishes. The id must match run_<letters/digits/_ 6-64>. Body limit 25 MB. Returns {ok, id, bytes}. Changes saved data in the app; no credits.
`PUT /api/runs/{run_id}`
- `run_id` (required): New id like run_<timestamp>_<random6>.
- `cur` (required): Current dataset object; must contain q (topic) and locale.
- `q`: Topic shown in the archive.
- `locale`: Market code.
- `label`: Panel label shown in the archive.
- `n`: Number of respondents.
- `mode`: Result mode, 'llm' or 'sim'.
- `at`: ISO time of the results.
- `savedAt`: ISO time saved.
- `panel`: Synthetic respondents with state vectors.
- `panelMeta`: Panel conditions: {source (market|icss|group...), label, groupName, groupCtx, cond:{target: market|group, method: random|enumerate, n (random mode), tau (enumerate threshold as a fraction, 0.01 = 1%), depth (extra respondents per state), seed, groupId, groupLabel}}. These are the browser-side run settings; record them so stories can be compared.
- `questions`: Survey questions.
- `results`: Survey results.
- `fgd`: FGD state {participants, log, round}.
- `chatLogs`: 1:1 chat logs by respondent id.
- `gateLog`: Hallucination gate log.
- `dba`: Ids of brand-asset tests linked to this story.

### list_runs
Lists stories saved on the server, newest first: {runs:[{id, q, locale, label, n, mode, at, panelMeta, hasResults, fgdN, chatN, bytes}], total}. Read only, free. Usually followed by: get_run.
`GET /api/runs`

### get_run
Returns the full saved snapshot of a story (cur, panel, questions, results, fgd, chatLogs, gateLog, dba). Read only, free.
`GET /api/runs/{run_id}`
- `run_id` (required): Story id (run_...).

### delete_run
Moves a saved story to the server trash; it disappears from every PC's archive. Returns {ok, id}. Deletes data. A person approves it first.
`DELETE /api/runs/{run_id}`
- `run_id` (required): Story id (run_...).

### check_asset_masking
Brand asset test (DBA) step 1: checks that each asset description contains no target or competitor brand name and, for images, transcribes visible text with a vision model to detect brand names. Returns {assets:[{id, img}], checks:[{id, ok, textLeaks, imageText, imageLeaks, note}]}. Uploaded data-URL images are stored and replaced by /api/dba/img paths. Spends ListeningMind Data API credits or paid model calls. Over MCP a person approves it first (you get a confirm link); in the browser the page asks the person. Cost: one vision LLM call per image asset; text-only assets are free. Usually followed by: start_dba_ai_test.
`POST /api/dba/mask-check`
- `category`: Product category shown as context, e.g. 'coffee chain' (max 60 chars).
- `locale`: Market of the test.
- `brand` (required): Target brand: {name (required), aliases: [string] up to 10, parents: [string] up to 5 (parent company names, coded separately, not counted as fame)}.
- `competitors`: Competitor brands, up to 30: [{name, aliases: [string]}]. Needed when prompted=true.
- `catHint`: Tell the respondent the category (default true).
- `prompted`: Show the brand list as answer options (prompted recall). Default false (unprompted).
- `assets` (required): Masked brand assets, 1 to 20: [{id, type (colour|shape|logo|character|celebrity|tagline|sound|font|pack|other), label, desc (text description without brand names, max 600 chars), img (data URL png/jpeg/webp/gif up to 5 MB, or a stored /api/dba/img/<name> path), control (true for the placebo baseline asset)}]. Each asset needs desc or img.

### start_dba_ai_test
Brand asset test, AI-response mode: asks Gemini and OpenAI directly (no persona) 'which brand is this?' for every masked asset, reps times per model, then scores fame and uniqueness on first-mentioned brand and saves the test. This is a GEO metric, not consumer response. Returns {job}; poll get_dba_job. Spends ListeningMind Data API credits or paid model calls. Over MCP a person approves it first (you get a confirm link); in the browser the page asks the person. Cost: paid LLM calls = assets x models x reps (e.g. 6 x 2 x 5 = 60); no Data API credits. Time: 1-5 minutes. Usually followed by: get_dba_job.
`POST /api/dba/ai-test`
- `category`: Product category shown as context, e.g. 'coffee chain' (max 60 chars).
- `locale`: Market of the test.
- `brand` (required): Target brand: {name (required), aliases: [string] up to 10, parents: [string] up to 5 (parent company names, coded separately, not counted as fame)}.
- `competitors`: Competitor brands, up to 30: [{name, aliases: [string]}]. Needed when prompted=true.
- `catHint`: Tell the respondent the category (default true).
- `prompted`: Show the brand list as answer options (prompted recall). Default false (unprompted).
- `assets` (required): Masked brand assets, 1 to 20: [{id, type (colour|shape|logo|character|celebrity|tagline|sound|font|pack|other), label, desc (text description without brand names, max 600 chars), img (data URL png/jpeg/webp/gif up to 5 MB, or a stored /api/dba/img/<name> path), control (true for the placebo baseline asset)}]. Each asset needs desc or img.
- `providers`: Models to ask.
- `reps`: Repeats per model per asset (1-20). More repeats give more stable fame and uniqueness.
- `force`: Run assets that failed masking too (marked maskOverride).

### get_dba_job
Returns {id, status (running, done, error), done, total, error, testId} and, when done, the full scored test. Repeat until done or error. Read only, free. Waits up to about 45 s for 'status' to reach done, error; call again if not done.
`GET /api/dba/job/{job_id}`
- `job_id` (required): Job id from start_dba_ai_test.

### ask_dba_llm
One vision-capable LLM call used by the synthetic-panel asset test: the UI sends a batch prompt built from ICSS personas plus up to 4 images and parses brand answers. Returns {text, provider, model}. Spends ListeningMind Data API credits or paid model calls. Over MCP a person approves it first (you get a confirm link); in the browser the page asks the person. Cost: one paid LLM call. Usually followed by: score_dba_synthetic.
`POST /api/dba/ask`
- `prompt` (required): Prompt text.
- `images`: Up to 4 images as data URLs or /api/dba/img/<name> paths.
- `temperature`: Sampling temperature.
- `provider`: Force one provider; default tries gemini then openai.
- `json`: Ask the model for JSON output.

### score_dba_synthetic
Scores synthetic-panel answers (fame, uniqueness, quadrant, baseline) and saves the test. Send the same test fields plus responses collected with ask_dba_llm. Returns {test}. Changes saved data in the app; no credits.
`POST /api/dba/score`
- `category`: Product category shown as context, e.g. 'coffee chain' (max 60 chars).
- `locale`: Market of the test.
- `brand` (required): Target brand: {name (required), aliases: [string] up to 10, parents: [string] up to 5 (parent company names, coded separately, not counted as fame)}.
- `competitors`: Competitor brands, up to 30: [{name, aliases: [string]}]. Needed when prompted=true.
- `catHint`: Tell the respondent the category (default true).
- `prompted`: Show the brand list as answer options (prompted recall). Default false (unprompted).
- `assets` (required): Masked brand assets, 1 to 20: [{id, type (colour|shape|logo|character|celebrity|tagline|sound|font|pack|other), label, desc (text description without brand names, max 600 chars), img (data URL png/jpeg/webp/gif up to 5 MB, or a stored /api/dba/img/<name> path), control (true for the placebo baseline asset)}]. Each asset needs desc or img.
- `responses` (required): Answers: [{asset (asset id), rid (respondent id), brands: [up to 3 brand names, first = first mentioned], provider, model}].
- `meta`: Panel info: {runId, topic, panelLabel, panelSource, panelN, respondents, failedBatches, models}.

### list_dba_tests
Lists saved brand-asset tests with per-asset fame, uniqueness and quadrant. Filter by brand (exact name or alias), locale and kind. Returns {tests, total, providers}. Read only, free.
`GET /api/dba/tests`
- `brand`: Brand name or alias.
- `locale`: Market code.
- `kind`: Respondent type.

### get_dba_test
Returns one saved test in full: brand, assets, responses, per-asset results, baseline, disclaimer. Read only, free.
`GET /api/dba/tests/{test_id}`
- `test_id` (required): Test id like dba_ai_<ts>_<hex6> or dba_syn_<ts>_<hex6>.

### get_dba_image
Downloads a stored stimulus image referenced by a test asset (img field /api/dba/img/<name>). Read only, free.
`GET /api/dba/img/{name}`
- `name` (required): File name: 24 hex chars plus .png, .jpg, .webp or .gif.

