Skip to main content
ish runs a thing you are making (a link, an ad, a video, a PDF, a chatbot) past simulated people and reports back what each one noticed, where they got stuck, and what they would do next. This page is about the people themselves: what a Person is, what a Participant is, how the panel for a run is chosen, and where a Person is visible. It is the mental model, not a command list. For exact flags and parameters, follow the links to the CLI and MCP reference.

A Person is a persistent record

A Person is a persistent record: a name, demographics, a trait-forward bio, and any workspace-specific custom fields. It is the description of who experiences your artifact, and it is reusable. One Person can take part in many studies and asks. Every Person is explicitly typed, ai or human, and the type is part of the record rather than something inferred from context:
  • An AI Person is generated. It has no real human behind it.
  • A HUMAN Person belongs to a real human who authorized it.
The type is a first-class filter on both surfaces. ish person list --type ai is the default; --type human and --type all are the other two. Each Person carries structured fields that shape how it reacts. Demographics (age, gender, country, occupation) sit alongside five universal enums: education level, household, locale type, income level, and employment status. There is also a versioned accessibility profile that records how the person actually experiences content (screen reader use, caption needs, reduced motion, high contrast). These are not decoration. Education level drives comprehension, vocabulary, and reading depth across every modality; the accessibility profile changes how a simulated person moves through your artifact. The full enum vocabularies live in the person reference.
You will see persona used to explain a Person on first contact, and profile used for a sub-record such as the accessibility profile. Neither word is the name of the thing. The record is a Person, it carries a type, and the type is what tells you whether anything real is behind it.

A Participant is one run

A Person is not the same thing as a Participant. The Person is the persistent record; a Participant is one run-scoped instance of it. Run the same Person across two studies and you get two Participants, both instantiated from the same Person record. A Participant is typed too, and the two types are separate axes. Participant type describes how participation happened in that one run. It is never inferred from the Person’s type: On the CLI the axis is ish study participant create --participant-type <ai|human>, defaulting to ai. Studies, asks, and API sessions created through the CLI and the MCP server dispatch AI Participants unless you say otherwise.
Always disclose which type a Participant is when you report a result. A HUMAN Participant produced observed evidence from a real person. An AI Participant produced simulated experience. Presenting the two as one kind of finding is the failure this typing exists to prevent, and it is not recoverable downstream: once the label is gone, nothing in the record distinguishes them.
When you write for a market research or insights audience, call the output of an AI Participant simulated people, not unqualified “participants”. In that register “participants” means humans who were actually there.

The contributor

A contributor is the real person who supplies authorized evidence, corrections, or outcomes, and who controls how that contribution may be used. It is a third role and not a synonym for either of the other two: a contributor’s persistent record is a HUMAN Person, and that Person may go into a run either as a HUMAN Participant (they take part themselves) or as an AI Participant (their simulated self takes part). Real evidence enters through sources, which a contributor authorizes. A Source is observed, never generated, which is what keeps the two kinds of evidence separable after the fact.

Two ways to get the people you need

You rarely start a run by hand-building a Person. You either pull from a pool that already exists or generate new people to fit a brief.

Sample from the pool

Filter the people available to your workspace by demographic and pick a sample. Good when the pool already covers who you are building for.

Generate to fit a brief

Describe who you are building for (and optionally ground it in real evidence) and ish builds matching AI People. Good when the pool is thin for your archetype.

Generating people

Generation turns a written brief, real research artifacts, or both into matching AI People. Hand it a description of who you are building for, point it at any sources (transcripts, emails, PDFs, images, audio) that capture how real people reacted, and it builds people grounded in that evidence. When sources are attached it can also produce grounded scenarios: recorded reactions the Person carries into a simulation as past context. Generation runs as an async job and blocks by default while it works (typically 30 to 60 seconds), then returns the resulting people. You can opt out of waiting and pick the results up later. A single generation is capped at 10 people; omit the count to let ish propose one. Generated people count toward your plan’s custom-person cap, which is separate from the per-run credit pool. When the pool has nothing that matches your filters, generating people that fit the brief is the right next move, regardless of what the pool happens to contain.

Sampling from the pool

When you select people for a run, two modes are available and they are mutually exclusive:
  • Explicit people. Name the people directly by id.
  • A demographic-filtered sample. Combine filters (country, gender, age range, occupation, name or bio substring, the extended enums, accessibility needs) and take a sample.
Within one dimension the filter values OR together: country = SE, NO matches either. Across dimensions they AND: adding an age range narrows the country match further. Occupation is a loose, case-insensitive substring match, so manager also catches hotel and retail managers; enumerate the whole-token variants you mean, or pair occupation with other filters, to recover the specificity you want.
Each run is capped at 20 participants by the backend. A filter that matches more than that, or an unbounded “all” against a large pool, needs a sample size or narrower filters. For a bigger panel, dispatch several runs against different slices (one country, then the next).

Where a person lives: visibility

Every Person has a visibility scope that decides who can see and use it. There are three, and a default list walks them in priority order: your own workspace first, then the platform pool, then community-shared.
The Person is private to its owning workspace. Only that workspace sees it. People you create or generate land here. A Person must be in your workspace before you can enrich it with new files or evidence.
Community-published, visible in every workspace’s people list, with attribution to whoever published it.
The admin-curated pool that every workspace can sample from. It is large (tens of thousands of people) and broad: it skews away from tech and Western defaults, so a narrow archetype may resolve to only a handful of matches. Sample from it freely, but you cannot delete a Person that lives here.
The list filter and the underlying stored row use slightly different words for the same idea. The agent-facing surface is workspace, shared, and platform; the stored person row records these as private, published, and platform. The older private and public filter values are still accepted as aliases for workspace and platform. When you read a Person, the visibility field reports the row value (private, published, platform).
Because the platform pool is so much larger than a typical workspace, an unscoped list can bury your own handful of people. Both surfaces default a no-filter list to your own workspace people and tell you how to widen it. Reach for the platform scope deliberately.

How people fit a run

Whichever way you build them, people feed a study run or an ask the same way: select the panel, dispatch, read the reactions. A run without people flags reuses the participants already on that iteration, which is what you want when you are re-running the same panel against a changed artifact. The selection vocabulary (the filters, the enums, the accessibility booleans) is shared across the run and ask surfaces, so what you learn here transfers. audience is the deprecated word for this set. It survives as the audience: parameter on study_run and ask_run, which is not renamed; in prose the word is panel.

Same model, both surfaces

The CLI and the MCP server expose the same person model: read, generate, enrich, delete. The verbs line up.
Both surfaces mint a short alias for each Person, and both use the same prefix: p- (for example p-d4e, as in --person p-795,p-af2). A Participant is pt- on both. An alias is accepted anywhere its own surface expects an id, alongside the full UUID. For full flags, parameters, and return shapes, see the CLI person reference and the MCP person tools.

Sources

The real evidence that grounds generated people.

Workspace

The container that owns your people, studies, and sources.

Study

Where a selected panel experiences your artifact.

Person reference

Every flag, enum, and field on the person commands.

Run a person over the API

Put a Person in the decision loop of your own environment, turn by turn.