# Persona

> >

- **Type:** Skill
- **Install:** `agentstack add skill-takechanman1228-claude-persona-persona`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [takechanman1228](https://agentstack.voostack.com/s/takechanman1228)
- **Installs:** 0
- **Category:** [Data & Analytics](https://agentstack.voostack.com/c/data-and-analytics)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [takechanman1228](https://github.com/takechanman1228)
- **Source:** https://github.com/takechanman1228/claude-persona/tree/main/skills/persona

## Install

```sh
agentstack add skill-takechanman1228-claude-persona-persona
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# AI Persona Panels for Customer Research

Build reusable persona panels, ask open-ended customer questions,
and run concept tests on messages, offers, and product ideas. 

## 3-Step Workflow

Inspired by TinyTroupe (Generate Personas → Simulate Interactions → Extract & Analyze):

| Step | What happens | Component |
|------|-------------|-----------|
| **1. Build Panel** | Define your market, generate diverse personas | Panel Builder |
| **2. Run Ask / Concept Test** | Each persona responds independently in its own subprocess | Simulation Engine |
| **3. Review Findings** | Structured report with themes, cross-tabs, charts, and verbatims | Analysis Pipeline |

Recommended workflow:
1. `/persona generate` — build a reusable panel
2. `/persona ask` — explore motivations, barriers, language, and decision criteria
3. `/persona concept-test` — compare explicit options when ready for a structured choice task

## Quality Guidelines

- **Take your time with persona generation.** Diverse, detailed personas are the foundation of useful results. Do not skip diversity verification.
- **Do not skip validation.** Always verify response JSON structure before proceeding to analysis.
- **Quality over speed.** A 5-persona panel with rich, differentiated responses is more valuable than a 15-persona panel with generic answers.

## Quick Reference

| Command | What it does |
|---------|-------------|
| `/persona generate Running shoe shoppers in the US` | Build a reusable panel (default 5 personas) |
| `/persona generate --count 10 Gen Z skincare shoppers in the US` | Panel with custom size |
| `/persona generate --segments Canned coffee drinkers in Japan` | Segment-driven panel (default 15) |
| `/persona ask What frustrates you most about choosing skincare products?` | Explore motivations and barriers |
| `/persona ask Why would you ignore an ad for a new running shoe?` | Qualitative reaction before concept test |
| `/persona concept-test Compare 3 running shoe concepts` | Concept test — concepts provided interactively |
| `/persona concept-test --market japan Evaluate 3 canned coffee concepts` | Concept test with Japanese panel |

`ask` explores open-ended motivations, barriers, and language.
`concept-test` covers any comparison research: product concepts, messaging A/B,
packaging, competitive comparisons, feature bundles, and value framing with
price context.

For detailed input requirements and output descriptions per command,
see `references/command-details.md`.

---

## Argument Parsing Rules

The text after the command is parsed as follows:

1. **Command** (required): `concept-test`, `generate`, `ask`
2. **Options** (optional):
   - `--count N` — Panel size (default: **5**; not applicable for `ask`)
   - `--market MARKET` — Target market/country (default: **us**). Accepts country codes (`us`, `japan`/`jp`, `uk`, `de`, `fr`, `cn`, `kr`) or freeform descriptors ("Southeast Asia", "urban Brazil"). Shorthand codes are expanded: `us` → United States, `japan`/`jp` → Japan, `uk` → United Kingdom, etc.
   - `--segments` — Activate segment-driven flow; default panel size becomes 15 (not applicable for `ask`)
   - `--panel PANEL` — (`ask` only) Specify the panel survey-id to use (e.g., `running-footwear-us-15p-2026-04`). Skips auto-detection.
3. **Free text** (optional): Everything else is the **research intent** — a natural language
   description of what the user wants to research. For `ask`, the free text is the question itself.

**Parsing examples**:
```
/persona concept-test Evaluate 3 new canned coffee concepts
  → type: concept-test, count: 5, intent: "Evaluate 3 new canned coffee concepts"

/persona concept-test --count 8 Compare ad headlines for EV launch
  → type: concept-test, count: 8, intent: "Compare ad headlines for EV launch"

/persona concept-test --segments Canned coffee
  → type: concept-test, count: 15, mode: segment-driven, intent: "Canned coffee"

/persona generate --count 15 Running shoes
  → type: generate, count: 15, market: "United States", intent: "Running shoes"

/persona generate --market japan --count 10 Canned coffee
  → type: generate, count: 10, market: "Japan", intent: "Canned coffee"

/persona concept-test --market japan Evaluate 3 new canned coffee concepts
  → type: concept-test, count: 5, market: "Japan", intent: "Evaluate 3 new canned coffee concepts"

/persona ask What frustrates you most about buying running shoes online?
  → type: ask, question: "What frustrates you most about buying running shoes online?", panel: auto-detect

/persona ask --panel running-footwear-us-15p-2026-04 Why would you ignore this ad?
  → type: ask, question: "Why would you ignore this ad?", panel: "running-footwear-us-15p-2026-04"

/persona ask --market japan What makes this product feel overpriced?
  → type: ask, question: "What makes this product feel overpriced?", market: "Japan", panel: auto-detect
```

**When free text is provided**:
- Extract the topic from the intent text
- Determine what information is still missing:
  - `concept-test`: concept/option details (names + descriptions) — ask only if not in intent
  - `ask`: the question is the free text; no additional info required
- If sufficient information is present, proceed without further questions

**When no free text is provided**:
- Collect all required information interactively (current behavior)

---

## Orchestration Logic

### Step 1: Build Panel

1. **Parse the user's request** to determine:
   - Command (concept-test or generate)
   - Free-text research intent (if provided)
   - Panel size (default: **5**; or 15 if `--segments`)
   - Market (default: **United States**; resolve shorthands like `jp` → Japan)
   - Mode: topic-only (default) or segment-driven (`--segments`)

2. **Collect missing info**:
   - Extract topic from free text (e.g., "Evaluate 3 new canned coffee concepts" → topic = "Canned coffee")
   - For concept-test: identify concept/option details — ask only if not provided
   - If free text provides sufficient context, skip interactive questions

3. **Persona Panel Decision**:

   a) **User explicit instruction**:
      - "Use existing panel" / "reuse {name}" → load from specified `personas/{survey-id}/` directory
      - "Generate new personas" or provides segment definitions → new generation
      - No instruction → proceed to auto-decision (b)

   b) **Auto-decision** (default is NEW generation):
      - Scan `personas/` for subdirectories containing `manifest.json` (ignore `_archive/`)
      - If a manifest's `category` closely matches the current topic AND `market` matches (or is absent, treated as "United States") → propose reuse, ask user
      - If no match found → proceed directly to new generation (no confirmation needed)

   c) **New generation flow — two modes**:

      **Topic-only mode** (default):
      - Skip segment inference entirely
      - Infer diversity dimensions inline and generate all N personas in one batch
      - See `references/topic-only-generation-flow.md` for the 4-step flow
        (dimension inference, target assignment, generation, manifest creation)
      - Do NOT ask user for segment approval — proceed directly

      **Segment-driven mode** (`--segments`):
      - If user provided segment definitions → use them directly
      - If topic only → run segment inference (see `references/segment-inference-prompt.md`)
        to generate 3-4 segments → present to user for approval
      - Default panel size: 15 personas (3 segments × 5 personas)
      - Follow the **4-step generation flow** below

      ### Segment-Driven 4-Step Generation Flow

      Inspired by TinyTroupe's TinyPersonFactory plan-based approach:
      instead of letting the LLM freely generate N personas per segment,
      first build a deterministic sampling plan, then generate each persona
      from its slot specification.

      **Step 1a: Deterministic Count Allocation**

      Compute per-segment counts deterministically — do NOT delegate count
      management to the LLM. This is the orchestrator's responsibility:

      1. `base = floor(count / num_segments)`
      2. `remainder = count mod num_segments`
      3. First `remainder` segments get `base + 1`; remaining get `base`
      4. **Verify**: `sum(segment_counts) == count` before proceeding

      Examples:
      - 30 ÷ 3 = 10 + 10 + 10
      - 17 ÷ 4 = 5 + 4 + 4 + 4
      - 8 ÷ 3 = 3 + 3 + 2

      Record each segment's allocated count. If the sum does not equal
      the requested count, fix the allocation before generating.

      **Step 1b: Sampling Plan Generation**

      Generate a sampling plan that assigns diversity attributes to each
      persona slot. See `references/sampling-plan-prompt.md` for the prompt.

      The plan is a JSON array with exactly N rows (one per persona).
      Each row specifies: segment, age_bucket, gender, occupation_tier,
      geography_type, region_hint, category_stance, ethnicity_hint.

      After the LLM returns the plan, verify:
      - `len(plan) == count`
      - Per-segment row counts match the allocation from Step 1a
      - If verification fails, regenerate the plan (max 2 attempts)

      **Step 1c: Persona Generation from Slot Specifications**

      Generate personas sequentially by segment. For each segment batch:

      1. Pass all slot rows for that segment to `persona-generation-prompt.md`
         as `{{slot_spec}}` — the LLM fleshes out each slot into a full persona
      2. Pass the **exclusion list** of already-used names, surnames, and
         occupation titles from previous segments as `{{exclusion_list}}`
      3. After generation, extract the names, surnames, and occupation titles
         from the generated personas and add them to the exclusion list
         for the next segment

      This ensures cross-segment duplicate suppression is built into the
      generation flow, not left to chance.

      **Step 1d: Panel Validation**

      After all personas are generated, run `scripts/validate_panel.py`
      programmatically:

      ```bash
      python scripts/validate_panel.py --panel-dir personas/{survey-id} --requested-count {count} --json
      ```

      Interpret the results:
      - **Hard fails** (severity: "fail"): The panel has a contract violation.
        Attempt to fix the specific issue (e.g., regenerate a duplicate-named
        persona) and re-validate. Max 2 retry cycles.
      - **Warnings** (severity: "warning"): Note them but do not block.
      - If hard fails persist after retries, present the panel with
        warnings and let the user decide.

   d) **Panel confirmation with QA summary**:
      - Present the panel overview table:
        ```
        | # | Name | Age | Gender | Occupation | Segment |
        |---|------|-----|--------|------------|---------|
        | 1 | Marcus Chen | 34 | M | Software Engineer | Serious Runners |
        | 2 | Diana Okafor | 52 | F | School Principal | Casual Joggers |
        | 3 | Jake Morales | 23 | M | Barista / Student | Fashion-Conscious |
        ```
      - Below the table, show a **QA Summary** from validate_panel results:
        ```
        ### Panel QA
        - Count: 30/30 ✓
        - Segment balance: Serious (10), Casual (10), Fashion (10) ✓
        - Names: all unique ✓
        - Occupation duplicates: none ✓
        - Age spread: OK ✓
        - Gender balance: OK ✓
        - Big Five near-duplicates: 1 pair (0.985) ⚠
        ```
      - If any hard fail remains, flag it prominently and offer to
        regenerate the affected personas
      - After user approves → proceed to concept test execution

   e) **Save personas**:
      - Save each persona as `personas/{survey-id}/{Name_Underscored}.json`
      - Create `manifest.json` with:
        - `"generation_mode": "topic-only"` or `"segment-driven"`
        - `"market": "{resolved market name}"`
        - `"requested_count": {count}`
        - `"sampling_plan": [...]` (the slot specifications from Step 1b)
        - `"validation_report": {...}` (from validate_panel output)
        - All segments must include `"description"` field

4. **Load survey template** from `templates/concept_test.md`.

### Step 2: Run Concept Test

Read `references/simulation-prompt.md` for the core simulation prompt.

**Before simulation, extract simulation profiles** from the full persona JSONs
using `extract_simulation_profile()` in `scripts/simulate_survey.py`. Pass the compact
profiles (~40-50 lines/persona) as `{PERSONAS_JSON}` instead of the full personas
(~300 lines/persona). This saves context window while preserving all response-driving fields.

#### Agent-Separated Execution (Recommended)

Use `simulate_survey.py` for production-quality results. This wrapper must force
`--backend claude-cli`, which runs each persona in a fully independent
`claude -p` subprocess — zero inter-persona bias.

```bash
python scripts/simulate_survey.py --config {config-path} --backend claude-cli
```

How it works:
1. Builds a per-persona system prompt (simulation instructions + single persona profile + survey questions)
2. Launches parallel `claude -p` processes (controlled by `--concurrency`, default 5)
3. Each process uses `--output-format json --tools "" --no-session-persistence`, plus
   `--safe-mode` (context isolation: no CLAUDE.md/plugins/hooks leak into persona calls) and
   `--json-schema` (server-validated structured output) when the installed CLI supports them
4. Parses the response (`structured_output` preferred, text extraction as fallback),
   validates structure, retries on failure (up to 3 attempts)
5. Saves `results.json` + `run_metadata.json` to `config.output_dir` when provided, otherwise to `outputs/{YYYY-MM-DD}/{HHMMSS}/{survey_type}/`
6. Runs a backend preflight before persona fan-out; if it fails, stop immediately and record `failure_stage: "preflight"`

Options: `--dry-run`, `--analyze`, `--report-llm`, `--no-adherence-check`, `--model`,
`--concurrency`, `--report-backend`, `--no-structured-output`, `--no-isolation`,
`--fallback-model`, `--effort`

#### Model Selection

The default simulation model is `sonnet` — the best cost/quality balance for
10-15-way persona fan-outs. All `claude` model aliases and full model IDs work:

| Model | When to use | Notes |
|-------|-------------|-------|
| `sonnet` (default) | Standard panels | Best cost balance for fan-out |
| `haiku` | Quick smoke tests, large panels | Cheapest; does NOT support `--effort` |
| `fable` (Claude Fable 5) | Highest-fidelity simulation, final runs | ~4x sonnet cost (higher price + denser tokenizer); slower turns |
| `opus` | High-fidelity alternative | Between sonnet and fable in cost |

Config keys (all optional, omit for current behavior):

```json
{
  "model": "sonnet",
  "report_model": "fable",
  "fallback_model": "sonnet",
  "effort": "medium",
  "max_budget_usd_per_call": 0.50,
  "structured_output": true,
  "isolation": true
}
```

- `"report_model": "fable"` — recommended upgrade: keep the fan-out on sonnet but
  synthesize the final report with Fable 5 (one call, small cost increase, richer narrative).
- `"fallback_model": "sonnet"` — recommended when running the fan-out on `fable`/`opus`:
  automatically falls back when the primary model is overloaded.
- `"effort"` — lower (`low`/`medium`) for cheaper, faster persona answers; not supported by haiku.
- `"max_budget_usd_per_call"` — hard cost cap per subprocess call.
- Run metadata records both the requested alias (`resolved_model`) and the exact
  model IDs that actually served the calls (`actual_model_ids`), plus `total_cost_usd`.

**Why agent-separated**: Shared-context simulation suffers from anchoring bias,
consensus bias, and style contamination. Agent separation eliminates all three.
Context isolation (`--safe-mode`) extends this: persona subprocesses do not read
the user's CLAUDE.md, plugins, or hooks, so project context cannot bias responses.

**Error handling**: If `simulate_survey.py` exits non-zero, read `run_metadata.json`
for `failure_stage`, `p

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [takechanman1228](https://github.com/takechanman1228)
- **Source:** [takechanman1228/claude-persona](https://github.com/takechanman1228/claude-persona)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** yes
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-takechanman1228-claude-persona-persona
- Seller: https://agentstack.voostack.com/s/takechanman1228
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
