Skip to main content

person_attach

Tier: write · Tags: person, write Enrich one existing private person with extra grounding - exactly one of source / evidence. Use this to add hand-tailored material to a single persona after the fact (vs. person_generate, which mints N personas from a brief / sources). See docs_get("guides/build-specific-person") for the evidence loop.
  • source=SourceAttachInput(path=..., description=...) runs the Person-scoped 3-step attachment intake (initiate → signed-URL PUT → confirm) - a file you want this persona to react to.
  • evidence=[EvidenceTraceInput(...), ...] POSTs scenario answers the persona’s simulation-time prompt reads as <past_reactions>.
The Person must be private (visibility="private"): the backend rejects shared/published people (moderation gate); the MCP surfaces that as [validation_error] with a “must be private” message. person_id: UUID or short alias (e.g. p-d4e); must be a caller-owned private Person. source: file payload - exactly one of source / evidence. evidence: 1..N EvidenceTraceInput rows (mutually exclusive with source). Each carries text (persona answer), source enum (situation / voice / binary / micro-story), scenario_prompt (the question), optional raw_response. Returns a PersonAttachResponse. With source, success sets attachment_id; with evidence, evidence_traces lists the persisted rows. On failure inspect error_kind{validation_error, not_found, forbidden, server_error, network_error, http_error}.

Parameters

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

person_delete

Tier: destructive · Tags: delete, person Permanently delete a person. DESTRUCTIVE. Public-pool people cannot be deleted by individual workspaces; the backend rejects those with [auth_failed] (or [not_found] if the Person does not exist). person_id: UUID or short alias (e.g. p-d4e) of the person to delete. Returns {"deleted": True, "person_id": <id>} on success; on failure raises ToolError with error_kind{auth_failed, forbidden, not_found, server_error, network_error, http_error}.

Parameters

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

person_generate

Tier: long-running · Tags: dispatch, person Build a person (or cohort) “ish” from a description and/or real research artifacts, via the agentic generation pipeline (turns the brief plus uploaded evidence - emails, PDFs, text, images, audio - into people, optionally with grounded scenarios). See docs_get("concepts/person") (generate vs manual) and docs_get("concepts/source") (artifacts as generation inputs). Blocks by default (wait=True): uploads artifacts, enqueues the job, polls to terminal, returns resolved people + scenarios. Pass wait=False for the job_id immediately, then pick up results via person_get(workspace_id=..., type="ai") - see docs_get("reference/long-running-jobs"). The three inputs (description, source_paths, source_upload_ids) freely combine. Counts toward the plan’s custom-person entity cap (independent of the per-run credit pool) - see docs_get("reference/credits"); on hit: [usage_limit_reached]. Single-person role-fitting (pair-mode use case). Pair-mode chat rehearsals (study_add_iteration with chat_pair=...) need one person per side: call person_generate(count=1, description="...") per side; the returned ids plug into ChatPairConfig.group_a / group_b. workspace_id: UUID or short alias (e.g. w-6ec) of the workspace. description: free-text audience brief (>=20 chars when supplied). source_paths: evidence references - prefer a data: URL or an http(s):// URL (fetched server-side, SSRF-guarded, 10MB cap): those are portable and work against the hosted server. A local file path is read from the MCP server’s own filesystem, so it only helps when you run the server yourself. To feed raw local bytes to the hosted server, upload them first with source_upload(inline_base64=...) and pass the returned id via source_upload_ids. Supported MIME: audio/*, image/*, text/*, application/pdf, application/json, office-document types. source_upload_ids: reuse sources already uploaded via source_upload (or a prior partial build) without re-uploading. reaction_notes: one researcher note per source_paths entry (same order, same length) describing how the real person reacted to THAT artifact; "" skips a note for that file. count: pin audience size to [1, 10]; omit to let the agent propose. age_range: (min, max) inclusive. country: ISO-3166-alpha-2 codes. gender: list of gender labels. generate_evidence: also produce grounded EvidenceTrace rows. None (default) = auto (scenarios only when sources attached); True / False override. wait: block until terminal (default True; runs take ~30-60s). timeout: seconds to wait when wait=True (default 180s). Returns a PersonGenerateResponse discriminated by ok. With wait=True, success populates people + person_ids; with wait=False, job_id + status="queued" only. On failure inspect error_kind{validation_error, not_found, usage_limit_reached, generation_failed, timeout, rate_limited, server_error, network_error, http_error}. Partial-failure contract: when upload(s) succeeded but enqueue failed, source_ids is still populated so agents can retry against existing sources without re-uploading.

Parameters

string
required
UUID or short alias (e.g. ‘w-6ec’, ‘p-abc’)
string
 
string[]
 
string[]
 
string[]
 
integer
 
object[]
 
string[]
 
string[]
 
boolean
 
boolean
Default: true.
number
Default: 180.0.

person_get

Tier: read-only · Tags: person, read Read people. Polymorphic on person_id: omit to list, pass it to fetch one Person. See docs_get("concepts/people") for people-selection semantics. List mode (no person_id): people in the workspace plus the public pool. Within a dimension (country / gender / occupation / each *_in enum) values OR; across dimensions they AND. Defaults to type="ai" (simulatable); "human" or "all" widen it. Pagination via limit (max 200) + offset. Returns a PaginatedList[Person] ({items, total, returned, limit, offset, has_more}); total is the match count, handy for pre-flighting a pair-mode side’s pool (the *_in enums + a11y booleans share their vocabulary with RoleCriteria). If nothing matches, fall through to person_generate to mint matching people. Public-pool rows surface but can’t be deleted by the caller (person_delete[auth_failed]). Single mode (with person_id): that Person with workspace-scoped custom fields + usage stats. include_evidence=True attaches persisted EvidenceTrace rows (newest-first) under the Person’s evidence; rejected in list mode (per-row evidence blows the token budget). Three text-search dimensions (each case-insensitive substring, AND’d): search → name; bio → narrative bio; occupation=[...] → occupation (OR’d within the dimension). workspace_id: UUID or short alias (e.g. w-6ec) of the workspace. person_id: UUID or short alias (e.g. p-d4e); omit to list. country: ISO-3166-alpha-2 codes. gender: gender labels. occupation: free-text occupation substrings (OR’d). role_in: canonical role keys (founder, product_leader, engineer, …) that OR-expand into many occupation substrings - a best-effort convenience over free-text occupation; merged with any explicit occupation. Pass an unknown key to see the full list in the [validation_error]. age_min / age_max: inclusive age bounds. search: name substring. bio: bio substring. type: ai (default) / human / all. limit / offset: pagination. include_bio, include_accessibility_profile: default False (each is large per row; fetch a single Person for the full payload). include_evidence: single mode only. visibility: narrows the list; default unions every scope, ordered workspace → platform → shared. Canonical values "workspace" (caller’s own; required ahead of person_evidence_add), "shared" (community-published), "platform" (admin-curated). Pre-rollout "private" / "public" are accepted as deprecation aliases for "workspace" / "platform". Extended demographic enums (snake_case, must match spec/profile-enums.v1.json):
  • education_level_in: less_than_secondary, secondary, some_post_secondary, vocational_or_associate, bachelor, graduate.
  • household_in: single, couple_no_kids, couple_with_kids, single_parent, shared_housing, adult_with_parents, multi_generational.
  • locale_type_in: urban, suburban, small_town, rural.
  • income_level_in: lower, lower_middle, middle, upper_middle, upper, prefer_not_to_say.
  • employment_status_in: employed_full_time, employed_part_time, self_employed, unemployed_seeking, student, homemaker, retired, unable_to_work, other.
Accessibility booleans (filter over the accessibility_profile JSONB): requires_captions, uses_screen_reader, prefers_reduced_motion, prefers_high_contrast, has_any_accessibility_need. Returns PaginatedList[Person] (no id) or Person (with id); on failure raises ToolError with error_kind{auth_failed, forbidden, not_found, server_error, network_error, http_error}.

Parameters

string
required
UUID or short alias (e.g. ‘w-6ec’, ‘p-abc’)
string
 
string[]
 
string[]
 
string[]
 
string[]
 
integer
 
integer
 
 
string
 
"ai" | "human" | "all"
Default: "ai".
integer
Default: 50.
integer
Default: 0.
boolean
Default: false.
boolean
Default: false.
boolean
Default: false.
string[]
 
string[]
 
string[]
 
string[]
 
string[]
 
boolean
 
boolean
 
boolean
 
boolean
 
boolean
 
"workspace" | "shared" | "platform" | "private" | "public"
 

source_upload

Tier: write · Tags: person, write Upload one piece of real evidence (email, PDF, text/doc, image, audio) so a later person_generate can ground a participant “ish” in how a real person reacted. Returns a source_upload_id to hand to person_generate(source_upload_ids=[...]). See docs_get("concepts/source"). Pass the bytes with inline_base64 (or a data: URL) - that is the portable path and the only one that works against the hosted MCP server, which cannot see your filesystem. source_path reads a LOCAL file from the MCP server’s own filesystem, so it only helps when you run the server yourself; an http(s):// URL is fetched server-side. workspace_id: UUID or short alias (e.g. w-6ec) of the workspace. source_path: read the evidence from the MCP server’s filesystem (a local path only works when the server runs on your machine), an http(s):// URL (fetched server-side, SSRF-guarded, 10MB cap), or a data: URL. Supported MIME: audio/*, image/*, text/*, application/pdf, application/json, office-document types. Omit when passing inline_base64. reaction: researcher note on how the real person reacted to THIS artifact (e.g. “called this proposal lazy and low-effort”); rides along to the agent. Backend caps it at 500 chars. inline_base64: raw base64-encoded file bytes (no data: prefix) - the portable input for hosted MCP clients that can pass the bytes but not a server-visible path. file_name is REQUIRED with this (it carries no name or MIME). Mutually exclusive with a non-data source_path. file_name: name to record for the upload; required with raw inline_base64, optional otherwise (overrides the path/URL basename). content_type: MIME override; inferred from file_name / the remote Content-Type when omitted. Returns a SourceUploadResponse discriminated by ok. On success source_upload_id is the new source’s ID. On failure inspect error_kind{validation_error, not_found, server_error, network_error, http_error}.

Parameters

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