Skip to main content

study_add_iteration

Tier: long-running · Tags: dispatch, study Add a NEW iteration - a content version (the URL / media / endpoint participants experience) - to a study. Pick modality and supply only that modality’s fields. A study has 1..N iterations; study_run defaults to the latest. This creates a version; it does NOT re-run the study (study_run), edit an existing iteration in place (study_update_iteration), or change study-level metadata (study_revise). Concept: docs_get("concepts/iteration").
  • interactive: url, platform (browser / android / figma / code), screen_format (mobile_portrait / desktop). Optional locale, flow_name. platform="figma" also needs file_key + start_node_id. The url is reached by ish’s cloud testers, so it must load WITHOUT your session: use a published / share-preview link, not a login-gated editor preview (Lovable / Replit / Bolt / v0 previews are session-gated) - localhost needs ish connect. You set this once per study; later runs reuse the iteration. Credentialed pages: register a login once with site_access_set. Builder clients get a tailored notes hint on the response.
  • video / audio / document: content_url (local path or hosted URL). Optional segmentation, content_config, copy_content (video/audio), title, mime_type.
  • text: content_text (inline, or @path for a local file). Optional content_html, sender_name / sender_email, featured_image_url, segmentation, content_config, title.
  • image: image_urls (non-empty; local paths and/or hosted URLs). Optional copy_content, segmentation, content_config, title.
  • chat, two mutually-exclusive sub-modes:
    • external_chatbot - pass chatbot_endpoint_id (saved) OR an inline endpoint dict.
    • participant_pair (AI ↔ AI) - pass chat_pair=ChatPairConfig(...). Drive each side from role_criteria_a / role_criteria_b (backend resolves pools at create time) or from explicit group_a / group_b (equal counts zip 1:1, or one side of 1 broadcasts). Scenarios on scenario_a/scenario_b. RoleCriteria enum/accessibility fields: docs_get("guides/chat-pair"). chat_pair with endpoint/chatbot_endpoint_id is a validation error. Optional max_turns, early_termination on both sub-modes.
Local uploads: content_url / image_urls accept local paths (uploaded and resolved to hosted URLs); content_text accepts @path. study_id: UUID or alias (e.g. s-b2c) of the study. Returns an IterationCreateResponse envelope discriminated by ok; branch on it and read error_kind / suggestions on failure. Media pre-flight and argument errors come back as ok=False (not exceptions) - same shape as chatbot_test.

Parameters

study_id
string
required
UUID or short alias (e.g. ‘w-6ec’, ‘tp-abc’)
name
string
required
 
modality
"interactive" | "video" | "audio" | "text" | "image" | "document" | "chat"
required
 
description
string
 
url
string
 
platform
"browser" | "android" | "figma" | "code"
 
screen_format
"mobile_portrait" | "desktop"
 
file_key
string
 
start_node_id
string
 
locale
string
 
flow_name
string
 
content_url
string
 
content_text
string
 
content_html
string
 
image_urls
string[]
 
title
string
 
mime_type
string
 
sender_name
string
 
sender_email
string
 
 
segmentation
object
 
content_config
object
 
copy_content
object
 
endpoint
object
 
chatbot_endpoint_id
string
 
max_turns
integer
 
early_termination
boolean
 
chat_pair
object
 

study_analyze

Tier: long-running · Tags: dispatch, study Trigger an AI analysis run for a study and optionally wait for it. Synthesizes a narrative summary plus a categorised KeyInsight list (friction / confusion / blocker / observation / positive). Read prior runs via study_get(view="insights"). Prerequisites (server-enforced): modality in {interactive, video, audio, text, image, document} (chat ineligible) and a minimum-completions floor. If it errors on the floor, wait for more completions or fall back to study_get(view='summary', group_by='segment'|'frame'). Credit cost: first analysis per study is free; each subsequent run costs 10 credits from the workspace’s plan pool. Empty pool → [insufficient_credits]. Model: docs_get("reference/credits"). study_id: UUID or alias (e.g. s-b2c) of the study. wait / timeout: blocking contract - docs_get("reference/long-running-jobs"). wait=True polls to completed/failed (raises ToolError on failed); default returns the pending envelope with a poll hint. timeout defaults to 300s. Returns a StudyResult - pending when wait=False, else the terminal completed envelope (summary + key_insights populated).

Parameters

study_id
string
required
UUID or short alias (e.g. ‘w-6ec’, ‘tp-abc’)
wait
boolean
Default: false.
timeout
number
Default: 300.0.

study_benchmark

Tier: long-running · Tags: dispatch, study Clone a source study (name, description, assignments, interview questions) to one or more competitor brand workspaces for cross-read. Clones are draft - this DOES NOT run them; study_run each yourself, then study_get(study_ids=[source, *clones]). Iterations, participants, and frames are not copied. Brands (brand_create) and the source must share a parent workspace. Each clone is born with an empty placeholder iteration A, surfaced as placeholder_iteration_ids[<cloned_study_alias>]. Fill it with study_update_iteration (PATCH the placeholder), NOT study_add_iteration (which would append a second iteration B and leave A empty). Skipped clones appear in skipped with a reason - handle before assuming a clean cohort. source_study_id: UUID or alias (e.g. s-b2c) of the source study. brand_ids: list of brand workspace UUIDs / aliases (w-...). Returns {"cloned": [<Study>, ...], "placeholder_iteration_ids": {<alias>: <iteration_id>}, "skipped": [{"brand_id", "reason", "existing_study_id?"}]}. Reasons: "no_access" or "already_cloned" (existing_study_id points at the prior clone).

Parameters

source_study_id
string
required
UUID or short alias (e.g. ‘w-6ec’, ‘tp-abc’)
brand_ids
string[]
required
 

study_create

Tier: write · Tags: study, write Create a study in a workspace. modality picks the artifact kind. Returns a StudyCreateResponse - study (id / alias / workspace_id / status all ride on it) plus notes naming the next steps: add content with study_add_iteration, then dispatch with study_run. To clone for benchmarking, see study_benchmark. Concept: docs_get("concepts/study"). assignments (the tasks participants attempt) accepts:
  • strings or Assignment dicts ({name, instructions, test_context?}). Bare strings ≤255 chars become {name, instructions}; longer strings auto-split at the first sentence boundary (name capped at 255, full string → instructions). Use for single-task non-chat and external_chatbot chat.
  • Assignment objects - required for participant_pair chat: two side-tagged rows (side="a"/"b") with name (role), instructions (scenario), optional test_context (goal).
Assignment may carry a steps checklist (steps=[AssignmentStep(...)])
  • atomic actions an LLM verifier grades per participant, rolled up into Assignment.step_completion on study_get(view='full'). Steps are interactive / external_chatbot-chat only. See docs_get("concepts/assignment").
chat_mode (required when modality="chat"): external_chatbot (talk to a bot endpoint) or participant_pair (AI ↔ AI). For participant_pair defer iteration creation to study_add_iteration. Each questions entry becomes a free-text post-sim interview question; for richer questionnaire shapes refine via study_revise. See docs_get("concepts/questionnaire"). workspace_id: UUID or alias (e.g. w-6ec) of the workspace. name: human-readable study name. modality: interactive | text | video | audio | image | document | chat. content_type: refines media modalities only (e.g. modality=“video”, content_type=“ad”); raises a preflight error for interactive / chat. chat_mode: external_chatbot | participant_pair; required iff modality=“chat”. assignments: see above. questions: free-text interview questions.

Parameters

workspace_id
string
required
UUID or short alias (e.g. ‘w-6ec’, ‘tp-abc’)
name
string
required
 
modality
"interactive" | "text" | "video" | "audio" | "image" | "document" | "chat"
required
 
content_type
string
 
chat_mode
"external_chatbot" | "participant_pair"
 
assignments
object | string[]
 
questions
string[]
 

study_delete

Tier: destructive · Tags: delete, study Permanently delete a study and all its iterations + simulations. DESTRUCTIVE. study_id: UUID or alias (e.g. s-b2c) of the study to delete. Returns {"deleted": True, "study_id": <id>} on success.

Parameters

study_id
string
required
UUID or short alias (e.g. ‘w-6ec’, ‘tp-abc’)

study_get

Tier: read-only · Tags: read, study Read studies - browse a workspace’s studies or read one study’s results. Pass exactly one of workspace_id (browse/list) / study_id (one study) / study_ids (benchmark cross-read). Read modes:
  • workspace_idbrowse: paginated list of every study in that workspace, each row carrying id, alias, name, modality, status / runtime_status, and participant counts - this is how you discover study IDs and inspect what exists (the browse layer for studies, mirroring workspace_get for workspaces). view / participant_id / lean ignored.
  • study_id → single-study results, shaped by view: summary (default; counts + sentiment + per-participant rows), full (typed Study; iterations + flat participant graph, each participant carries iteration_id), per_participant (one participant’s run; needs participant_id), transcripts (chat-only; all transcripts, or one when participant_id set), insights (AI summary + KeyInsight list from study_analyze runs; {latest, history} newest-first).
  • study_ids → benchmark cross-read; list of per-study results in order, each shaped by view (pass source + study_benchmark clones).
Slicing (single-study only): filters=StudyResultsFilter(...) narrows to matching interactions; group_by reprojects into per-group rollups. Axes by modality - interactive→frame/step; video/audio/text/document→ segment; chat→turn (side on participant_pair, step on graded external_chatbot); image→none; iteration/assignment/sentiment apply to all. Off-modality filters warn via modality_warnings and are ignored; off-modality group_by hard-errors. Filtered responses carry totals_unfiltered for coverage checks. See docs_get("guides/slicing-results"). Text-field provenance: summary’s participants[].summary_highlight is AI-synthesized (not a quote); per_participant’s interactions[].comment and participant_summary.comment are verbatim persona text. Drill into per_participant for source quotes. Navigation / decision trace: per_participant’s interactions[] IS the step-by-step clickstream - ordered by timestamp, each step carries url (page URL), location (page/screen template), actions[] (taps / typing / scrolls), and screenshot_id (the frame seen at that step). For interactive studies that is the visited-pages / decision-path record; graded step outcomes roll up via group_by='step'. Screenshots and transcripts are also exposed as ish:// resources, with inline screenshots_resource / transcripts_resource pointers on the summary view so clients that can’t read resources still reach them. study_id: UUID or alias (e.g. s-b2c). Exclusive with the other two. study_ids: list of UUIDs/aliases for benchmark cross-read. Exclusive. workspace_id: UUID or alias (e.g. w-6ec). Exclusive. view: summary (default) | full | per_participant | transcripts | insights. Ignored in list mode. participant_id: required for per_participant; optional scope for transcripts; ignored otherwise. lean: view="full" only - null iterations AND skip the participants fetch for a metadata-only payload (also the fix if full times out on a draft study). filters: StudyResultsFilter (see that model). Only with study_id + view in {summary, full}. group_by: iteration | frame | segment | turn | assignment | step. Reprojects onto the axis; returns a SliceResponse. Only with study_id + default view="summary". Returns PaginatedList[Study] (list), Study (full), StudyResultsSummary (summary), dict (per_participant), TranscriptsResponse or ChatTranscript (transcripts), SliceResponse (group_by set), or a list of these (benchmark). Slice / transcripts envelopes expose rows on response.rows.

Parameters

study_id
string
 
study_ids
string[]
 
workspace_id
string
 
view
"summary" | "full" | "per_participant" | "transcripts" | "insights"
Default: "summary".
participant_id
string
 
lean
boolean
Default: false.
filters
object
 
group_by
"iteration" | "frame" | "segment" | "turn" | "assignment" | "step"
 
limit
integer
Default: 50.
offset
integer
Default: 0.

study_revise

Tier: write · Tags: study, write Update study-level metadata (name / description / status / modality / assignments / questions). Only fields you pass change; None leaves a field untouched, assignments=[] / questions=[] clear the list. Does NOT touch iterations - study_update_iteration edits an existing iteration, study_add_iteration appends a new one. Changing modality invalidates prior runs (rare). study_id: UUID or alias (e.g. s-b2c) of the study. name, description, status: study-level fields. modality: interactive | text | video | audio | image | document | chat. content_type: media modalities only; omit for interactive / chat. assignments: as in study_create (strings, or Assignment objects for test_context / side / steps). questions: free-text interview questions.

Parameters

study_id
string
required
UUID or short alias (e.g. ‘w-6ec’, ‘tp-abc’)
name
string
 
description
string
 
status
string
 
modality
"interactive" | "text" | "video" | "audio" | "image" | "document" | "chat"
 
content_type
string
 
assignments
object | string[]
 
questions
string[]
 

study_run

Tier: long-running · Tags: dispatch, study Run a study: resolve an audience (or reuse an existing panel), create participants on an iteration if needed, and dispatch the modality-appropriate simulation batch. Verb choice (study vs ask): docs_get("concepts/run-verbs"). Credit cost: each successfully-completed participant debits the workspace’s plan credit pool - subscription-funded, so no per-dispatch approval is needed; pre-flight failures (CSP refusals, NXDOMAIN, chatbot smoke-test failures, etc.) cost zero and are retryable. Confirm the pool via workspace_get(...).credits (empty → [insufficient_credits]). Model: docs_get("reference/credits"). Three modes:
  1. Materialize + dispatch (default): audience + dispatch=True.
  2. Stage only: audience + dispatch=False - creates participants but does NOT dispatch (review checkpoint before drawing credits). Run later with audience=None.
  3. Reuse panel: audience=None - dispatches whatever participants already exist on the iteration.
study_id: UUID or alias (e.g. s-b2c) of the study. iteration_id: UUID or alias (e.g. i-d4e); defaults to the latest. audience: AudienceFilter (person_ids, or sample=N / all_matching=True + demographic filters). None reuses the iteration’s panel. See docs_get("concepts/people"). config_id: simulation-config override (alias c-...). Required for media and chat studies unless every resolved person has a simulation_config_id. For participant_pair chat, omitting it auto-infers from the first group_a person; missing → validation_error. Optional for interactive. dispatch: see modes above. max_interactions: per-participant step cap (interactive / media). Defaults to 20; caps runaway spend on a stuck participant. Ignored for chat. Must be ≥1. max_turns: per-participant turn cap (chat / chat_pair). Omitted → backend uses request > iteration’s stored value > 14. Ignored otherwise. Must be ≥1. wait / timeout: blocking contract - docs_get("reference/long-running-jobs"). wait=True polls every participant to terminal or timeout; default returns the post-dispatch snapshot with a next_action poll hint. Caveat - client transport ceiling: many MCP clients cap a single tool call at ~30s (e.g. Cursor/Replit), and that ceiling overrides timeout: wait=True, timeout=300 still aborts at the client’s ~30s with no result. Interactive/media runs take 1-5 min, so they routinely exceed it. Prefer the default wait=False and poll via the next_action hint; reserve wait=True for fast jobs or clients with no short transport cap. Locally-served iterations (platform="code" or a localhost URL) need an active ish connect tunnel; absent one, fails fast with error_kind="TunnelInactive". A public but session-gated URL (an app-builder editor preview - Lovable / Replit / Bolt / v0) passes this check yet still fails for ish’s cloud testers: point the iteration at a published / share-preview link, or register a login with site_access_set. See docs_get("concepts/site-access"). participant_pair chat rejects audience (audiences live in the iteration’s mode_details). Returns a RunStudyResponse envelope discriminated by ok. Success → response.dispatch (SimulationDispatchResult); dispatch=False leaves it None with participant_ids populated. Failure → error_kind + error_message; a wait that runs out of budget gives error_kind="wait_timeout" with participant_ids set so you can resume via study_get(view="summary").

Parameters

study_id
string
required
UUID or short alias (e.g. ‘w-6ec’, ‘tp-abc’)
iteration_id
string
 
audience
object
 
config_id
string
 
dispatch
boolean
Default: true.
wait
boolean
Default: false.
timeout
number
Default: 600.0.
max_interactions
integer
 
max_turns
integer
 

study_update_iteration

Tier: write · Tags: study, write Patch an EXISTING iteration’s content in place (cheap edits: rename, re-description, partial details patch). For a full re-spec, or to ADD a new content version, prefer study_add_iteration (its typed signature guides every modality’s fields); for study-level metadata use study_revise. details is the modality-specific nested payload; the type discriminator is required on every shape and must match the iteration’s modality (omitting it → [validation_error] Unable to extract tag using discriminator 'type'):
  • interactive - {type: "interactive", url, platform, screen_format, ...}
  • media (video/audio/document) - {type: "media", content_url, title, ...}
  • image - {type: "image", image_urls, title, ...}
  • text - {type: "text", content_text, content_html, title, ...}
  • chat - {type: "chat", endpoint, chatbot_endpoint_id, max_turns, ...}
study_id: UUID or alias of the parent study (alias hydration only). iteration_id: UUID or alias (e.g. i-d4e) of the iteration. details: modality-specific patch (see above). name, description: iteration-level fields.

Parameters

study_id
string
required
UUID or short alias (e.g. ‘w-6ec’, ‘tp-abc’)
iteration_id
string
required
UUID or short alias (e.g. ‘w-6ec’, ‘tp-abc’)
details
object
 
name
string
 
description
string