Psychological Experiment Designer
SkillMediaDesign or revise a psychological experiment before implementation. Use when the user has an idea, partial protocol, trial/block structure, timing, randomization, response mapping, condition table, PsychoPy/jsPsych/ Psychtoolbox target, or a paradigm such as Stroop, IAT, N-back, priming, dot-probe, visual search, task switching, Go/No-go, or stop-signal, and needs a confirmed experiment config YAML. Do not use to implement/debug existing code or to audit readiness; use psy-exp-coder or psy-exp-reviewer instead.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Psychological Experiment Designer skill
What this skill tells your AI
The instructions your AI receives, as published by soupandpsy/amazing-psycoder-skills in amazing-psycoder/psy-exp-designer/SKILL.md and read by ahel’s review.
Version
v1.4.0 — unified evidence-gated contract, 2026-07-23. Sub-skill of amazing-psycoder.
Purpose
Convert psychological experiment ideas into a complete experiment specification (config YAML) through progressive refinement, then route the validated config to psy-exp-coder. Do not generate implementation code in this skill.
Design Philosophy
Let the user own design decisions while the system enforces explicit semantics, progressive confirmation, traceable assumptions, and a complete config before code generation. Paradigm references suggest questions; they do not own the design.
Paradigm References Are Non-Authoritative
paradigm and paradigm_family classify a design and may select an optional
knowledge reference. They never select executable logic or initialize hidden
experiment fields. The user's confirmed windows, condition
model, correctness rules, randomization constraints, feedback, and data schema
are authoritative.
Do not collapse variants into a family implementation. Classic color-word, semantic, emotional, bilingual, and numerical Stroop may require different stimulus schemas, factors, derived variables, correctness rules, and analysis interpretations. If no exact reference exists, continue as a custom design and derive every semantic rule from the user-confirmed config.
When Not to Use
Route implementation/debugging to psy-exp-coder, readiness audits to psy-exp-reviewer, and answer quick platform API questions directly.
Core Model
Model every experiment as Experiment → Sequence → Window → Data. Require one trial-summary row per trial; add a linked event-level table when a trial has repeated responses, trajectories, adaptive steps, drag events, or other one-to-many observations. Never force repeated events into a single lossy cell.
Red Lines
Hard prohibitions. These must never be violated — no exceptions, no "just this once."
| # | Rule | Applies to | Why |
|---|---|---|---|
| 1 | No code generation before trial window timeline is complete | All platforms | Code written without a validated window sequence will have structural errors that are expensive to fix |
| 2 | No assumed response mapping | All platforms | Which key means what answer must be confirmed with the user. Guessing invalidates accuracy data |
| 3 | No blocking sleep in timing-critical or interactive windows | PsychoPy, jsPsych | Blocking waits make timing and abort handling unreliable. Use frame/timeline scheduling; never use a setup wait as an RT source |
| 4 | No event.getKeys(maxWait=...) | PsychoPy | Blocks the event loop. Use keyboard.Keyboard with win.callOnFlip(kb.clock.reset) |
| 5 | No data saved only at end of experiment | All platforms | Crash = all data lost. Save incrementally per trial or per sequence with try/finally |
| 6 | No silent filling of [MISSING] values | All platforms | Every [MISSING] must be resolved by asking the user or offering an explicitly-flagged default |
| 7 | Font-sensitive/CJK text needs an explicit font strategy | All platforms | Record a suitable family/path/fallback for the target runtime and verify glyphs and layout visually; browser fallback stacks are acceptable when tested |
| 8 | No skipping relevant design decisions | All platforms | Exact paradigm references may suggest questions, but only the actual experiment specification determines what must be confirmed |
| 9 | No rt_onset omitted on response windows | All platforms | Incorrect or missing RT onset invalidates all reaction time data. The coder will refuse to generate if absent |
| 10 | No code delivery without reviewer pass | All platforms | All generated code must pass through psy-exp-reviewer before data collection. Programming → Coder → Reviewer is a mandatory chain |
Config as Single Source of Truth
The experiment config YAML is the central artifact. Every design decision lives in one file:
name: # experiment name
paradigm: # which paradigm
paradigm_family: # optional research lineage; metadata only
variant: # optional exact variant; metadata only
platform: # psychopy / psychtoolbox / jsPsych
stimulus_folder: # global path for image file references
windows: # trial event sequence
sequences: # row order, condition-table binding, cycles, and condition ordering
response_rules: # keys, deadline, accuracy logic
randomization: # method, seed, sequence/counterbalance constraints
paradigm_config: # paradigm-specific settings
output: # data directory, filename pattern
The conversation has one goal: fill every [MISSING] field in this config. The user can provide information in any form — prose description, file paths, partial YAML, xlsx files — and the system progressively accumulates it into the config.
Unified Workflow
Every new experiment follows the same 5 phases. The order reflects how experimenters naturally design: trial first (with rules), then sequence structure. The config YAML is filled progressively.
Phase 1: Assess → 收集已有信息
Phase 2: Windows & Rules → 定义 Trial + 反应规则(最关键)
Phase 3: Conditions→ 定义 trial 序列(xlsx + 刺激文件)
Phase 4: Sequences → 定义序列结构和执行模式
Phase 5: Validate → 验证并移交代码生成
Blocking Gates
Hard checkpoints. The workflow does not advance past a gate until its condition is met. If a gate fails, return to the relevant phase; do not proceed.
| Gate | After | Condition | Fail → Return to |
|---|---|---|---|
| Gate 1 | Phase 2 | Trial window timeline has no [MISSING]. Every window has name, content, duration, response. Response windows have rt_onset. Response keys, mapping, accuracy rules, and output format are confirmed. Phase 2 decision checklist presented and user confirmed | Phase 2 |
| Gate 2 | Phase 3 | Every {column_name} in windows[] exists in condition xlsx. Condition file is on disk OR has been generated by Phase 3. Stimulus folder (if used) resolves. Phase 3 decision checklist presented and user confirmed | Phase 2 or 3 |
| Gate 3 | Phase 4 | Config has zero [MISSING] markers. All sections (windows, sequences, response_rules, paradigm_config, randomization, output) are complete. Phase 4 decision checklist presented and user confirmed | Phase 2/3/4 (whichever section has [MISSING]) |
| Gate 4 | Phase 5 | All rules in config-schema.md pass and scripts/validate_experiment.py reports zero errors. No missing columns/files, ambiguous accuracy coding, unseeded randomization, or unsafe output contract remains | Phase 1/2/3/4 (based on error type, per Phase 5 routing table) |
| Gate 5 | Phase 5 (before coder) | Final Design Review: Full Design Decision Registry presented. User explicitly confirms ALL decisions (including [ASSUMED] items) before code generation. No decision left un-reviewed | Phase 1/2/3/4 (user can correct any decision) |
Phase 1: Assess Input
Determine what the user already has, what paradigm, and what platform.
| User provides | Action |
|---|---|
| Natural-language description ("我想做一个Stroop实验...") | Parse into skeleton config; flag all unknowns as [MISSING] |
| Partial config YAML | Load it; identify which sections are filled vs missing |
| config.yaml + conditions/*.xlsx | Load everything; validate; skip to Phase 5 if complete |
| Existing experiment code to modify/debug | Route to psy-exp-coder; do not modify implementation inside the Designer |
| "帮我检查这段代码" | Route to psy-exp-reviewer directly |
Also resolve in Phase 1 if the user hasn't stated it:
- Paradigm/family metadata when useful. Load an exact paradigm file only as a reference; an unknown or custom paradigm is valid when its semantics are complete
- Platform (PsychoPy / Psychtoolbox / jsPsych)
- Runtime contract: Record an exact framework version, pinned/lockfile dependency strategy, and target environment. Record OS/display details when timing, visual angle, hardware, or font paths depend on them. For CJK or other font-sensitive stimuli, an explicit family plus tested fallback/auto-detection is blocking.
When an exact paradigm reference exists: Cross-reference its ## Must Confirm list against what the user already stated. These are candidate safety questions, not inherited answers. For each relevant unconfirmed item, assign it to the phase where it will be asked:
| Must Confirm item type | Target phase |
|---|---|
| Stimulus identity, content, modality | Phase 2 |
| Key assignment, response mapping | Phase 2 |
| Timing values (durations, deadlines, SOA) | Phase 2 |
| Accuracy rules, error coding, catch trials | Phase 2 |
| Output format (data directory, filename) | Phase 2 |
| Trial counts, condition ratios | Phase 3 |
| Stimulus file source (image vs generated) | Phase 3 |
| Sequence count, repetitions per sequence, feedback placement | Phase 4 |
| Counterbalancing, sequence order | Phase 4 |
If a Must Confirm item doesn't fit any later phase (e.g., paradigm-specific correctness logic), ask it now in Phase 1. Do not leave Must Confirm items unassigned.
Output: Config with name, paradigm, platform, and runtime filled; add detailed OS/display/font fields when required by the design. Present the Phase 1 Decision Checklist before advancing.
Phase 2: Define Windows & Rules (Trial)
Build the trial window timeline — the most critical phase. Every screen event in a single trial becomes a window. Also finalize all response rules here: key mapping, accuracy logic, and output format. These belong together because the response keys defined in the window timeline directly determine the mapping and accuracy rules.
What to determine for each window:
- Window name and order (e.g., Fixation → Stimulus → Response → Feedback → ITI)
- Content (literal text,
{column_reference}, or image file path) - Duration (fixed ms,
[min, max],until_key, orself_paced) - Response rule (none / allowed keys / deadline)
- File/folder reference (which stimulus files?)
- Condition source (which xlsx column drives this window?)
How to present: Follow the sequence-row diagram and formatting contract in
canvas-presentation.md. Each Sequence is
one independent horizontal row. Sequence order is top-to-bottom; window order
is left-to-right. Show every sequence, mark unresolved values as [MISSING],
and annotate the response window with its RT anchor and recorded data.
Questions (max 3):
- "每个窗口的持续时间是多少?反应窗口的截止时间?"
- "被试按哪些键反应?哪个键对应哪个条件?"
- "刺激呈现什么内容?文字、图片还是图形?"
Also ask any paradigm Must-Confirm items assigned to Phase 2 (stimulus identity, timing values, key assignment, accuracy rules). Phase 2 typically carries the most Must-Confirm items — if paradigm questions + generic questions exceed the 3-question limit, apply the Must-Confirm overflow rule (batch compatible questions, default low-risk items with ⚠️ flag, defer to later phases where logical).
How many windows? The confirmed design determines the window count; it is not fixed at 5 and is never inherited solely from a family label. Standard RT tasks may have 4 (Fixation → Stimulus → Response → ITI). Masked priming may need 6+ (Forward Mask → Prime → Backward Mask → Target → Response → ITI). An exact reference may offer a starting example, but the resulting timeline remains fully editable.
Stimulus + Response: merge or split? Two patterns are valid:
- Split: Stimulus window (fixed duration, no response) → Response window (stimulus stays + keys accepted). Use when the stimulus must be visible for a fixed time before responses are allowed. RT is measured from Response window onset, excluding stimulus encoding time.
- Merged: A single window with
duration: until_keyandresponse: [keys]. Use when the participant responds immediately to the stimulus (e.g., Stroop, Flanker). RT is measured from stimulus onset.
RT measurement contract — proposed, explained, and explicitly confirmed.
Window structure may suggest an anchor, but a paradigm label or heuristic never defines the dependent variable. Before Gate 1, record response_event, rt_onset/anchor window, scientific rationale, and status: confirmed. For a merged response window, propose its measured display onset; for a stimulus then response sequence, explain that the two possible anchors estimate different quantities and ask which operational definition is intended.
Present the consequence without implementation jargon and request confirmation:
"我建议把反应时定义为:从 [可观察事件/窗口] 的实际呈现时间,到 [按下/释放/点击]。这样测量的是 [研究含义];若改从 [另一事件] 起算,解释会不同。请确认这一定义。"
Do not confirm the design until the user confirms this definition. Coder resolvability checks are implementation guards, not scientific validation.
Response Rules (also Phase 2)
Once windows are defined, immediately finalize the response rules — don't defer to a later phase. The response keys named in the window timeline directly determine these rules.
What to determine:
- Response mapping: Which key = which answer (e.g., f=red, j=green, k=blue). Ask this alongside the key list in the windows phase — it's unnatural to separate them
- Accuracy logic: What makes a response correct for each condition. For simple designs, this is just
key == correct_response. For paradigms like Go/No-go: no-go + no key = correct; go + no key = miss - No-go / stop / catch trial handling: How to score trials where the correct response is to NOT respond
- Deadline: Maximum response time per trial. If unknown, propose a task-appropriate candidate with rationale and keep it unconfirmed; there is no universal paradigm-family default
Questions (ask alongside window questions above — don't create a separate question round):
- "哪个键对应哪个条件?" (if mapping not obvious from key list)
- "No-go试次不按键=正确,按键=错误,确认吗?" (paradigm-specific, from Must-Confirm)
Output format — also finalized here, but offer defaults; only ask if customization needed:
- Data directory:
data/(default) - Filename pattern:
sub-{subject_id}_{task_name}_{run_id}.csv(default) - Question (only if user needs changes): "数据用默认设置保存,需要修改吗?" (counts toward the 3-question limit only if asked)
Output: Config windows[], response_rules, paradigm_config, and output sections complete. Phase 2 Decision Checklist presented for user confirmation. Gate 1 check: windows have no [MISSING], response keys and mapping are confirmed, accuracy rules are defined, and the response-event/RT-anchor measurement contract is explicitly confirmed.
Phase 3: Build Conditions
Define what varies trial-to-trial — the condition table that drives each trial's content and correct answer.
What to determine:
- Does the user have existing condition xlsx files?
- If yes: validate file paths, column names, condition ratios
- If no: generate from specification based on the windows defined in Phase 2
- Stimulus file paths (folder location, naming convention)
How it connects to Phase 2: Every {column_name} in the window content and response fields must exist as a column in the condition xlsx.
Condition file generation: If the user needs condition files created, use condition-file-generation.md. For simple designs, write the xlsx directly. For complex or reproducible designs, generate a standalone Python script. Always report the generated file's path, row count, columns, and condition distribution.
Questions (max 3):
- "trial 顺序有现成的 xlsx 文件吗?还是根据条件自动生成?" — if yes, validate the file; skip question 2
- "每个条件各多少 trial?各条件比例是多少?"
- "刺激文件放在哪个文件夹?文件命名规则是什么?" — skip if all stimuli are text-based (determined in Phase 2)
Also ask any paradigm Must-Confirm items assigned to Phase 3 (condition ratios, stimulus file source).
Output: Condition files (validated or generated). Fill the global stimulus_folder when file-backed stimuli are used. Present the Phase 3 Decision Checklist for confirmation.
Phase 4: Set Sequence Structure
With the trial defined (Phase 2) and conditions built (Phase 3), determine the experiment structure: how sequences are ordered and how each sequence executes.
Core concept: A Sequence is one horizontal row of windows that runs from top to bottom. Every sequence has a positive repetitions cycle count. 1 already means one execution, so there is no separate once/loop switch. A sequence may bind one real condition table:
| Binding | Meaning |
|---|---|
| No condition table | One cycle executes the window chain once |
| Condition table selected | One cycle traverses every row of that table once |
The condition order is explicit: table_order (original table order),
fixed_random (one seeded reproducible order), or fully_random (a fresh
random order for every repetition). In Studio these are the complete
ExperimentModel@4.execution choices; there is no separate once/loop or
reshuffle switch. Standalone YAML may serialize additional execution evidence,
but it must not be projected back into Studio as a hidden setting.
What to determine:
- Sequence order (top to bottom on the canvas)
- Per-sequence condition table, cycle count, order mode, and fixed seed when
fixed_randomis selected - Feedback placement: does a Feedback window exist in this sequence?
- Sequence visibility: should this sequence only appear in certain contexts? (
show_in) - Between-sequence behavior: does the experiment pause, show instructions, or auto-advance?
- Counterbalancing: Is sequence order fixed or counterbalanced across subjects? If counterbalanced, by what rule (subject ID parity, Latin square)?
Sequence naming convention: Names like Start, Practice, Main, Rest, End are editable labels that help the researcher organize their experiment. They never determine execution behavior — only the condition-table binding and execution fields control what happens.
Before finalizing sequences, run this consistency check:
- If any sequence has a Feedback window but no Feedback window exists in
windows[], insert one after the Response window:{name: Feedback, content: correct_incorrect, duration: 500, response: none}. - Feedback appears only in sequences that contain a Feedback window. The
show_infield restricts further — e.g.,show_in: [practice]means the sequence only appears during practice, even if it shares windows with formal sequences.
Questions (max 3):
- "实验有几个序列?每个序列使用哪张条件表并循环几轮?(如 Start 无表 1 轮、Practice 使用练习表 1 轮、Main 使用正式表 2 轮)"
- "反馈在哪些序列显示?只在练习还是正式实验也有?"
- "序列呈现顺序是固定的还是在被试间平衡?"
For a rest sequence, ask what the screen displays and how it advances. Never insert rest text or a continue key that the user did not confirm.
Output: In Studio, update sequences[] with name, windowIds, optional
conditionTableId, and execution (repetitions, orderMode, and
fixedSeed only for fixed_random). In standalone YAML, use its documented
snake-case adapter fields. Present the Phase 4 Decision Checklist for
confirmation.
Phase 5: Validate & Route
Cross-check everything, present the final design to the user for confirmation, then route to the coder for code generation.
Step 1: Technical validation — Run every rule in config-schema.md § Validation Rules, then execute python3 <amazing-psycoder-root>/scripts/validate_experiment.py <config.yaml>. Treat every reported error as blocking; the script is a static preflight and never proves runtime readiness.
If validation fails: Report specific errors. Return to the relevant phase based on error type:
- Missing config metadata (
name,paradigm,platform) → Phase 1 - Missing or incomplete window definitions (
content,duration,response,rt_onset), missing response rules, ambiguous accuracy coding → Phase 2 - Missing condition file, invalid columns, row count mismatch, or missing stimulus files → Phase 3
- Missing sequence fields, invalid condition-table references, cycle counts, or order policies → Phase 4
Step 2: Final Design Review (Gate 5, blocking) — Present the final design for user confirmation. This is mandatory before routing to code generation.
Do not dump raw YAML by default. Present the design in readable form, save the YAML as a real artifact, and report its path. Show the YAML whenever the user requests it; it is not secret state. Use these two confirmation views:
- Trial Window Timeline — the box diagram with response rules (same format as Phase 2 output)
- Complete Design Decision Registry — all decisions from all phases in table form
Use the complete final-review example in canvas-presentation.md. It must show every sequence/window, response and RT semantics, plus the cumulative Decision Registry with all assumed values visibly marked.
- Items marked ⚠️ are defaults/assumptions — the user MUST be prompted to review them
- Ask: "以上所有设计决策确认无误,可以生成代码?如需修改请指定编号和新值。"
- Do NOT route to the coder until the user explicitly confirms the full registry
- If the user wants to change any item, return to the relevant phase, update the config, and re-run validation
- Save the confirmed config and Decision Registry in the project directory before handoff. The Coder documents stable parameter names/sections after code exists; the Designer must never invent future line numbers.
Step 3: Persist and route — After Gate 5, save config.yaml and the Decision Registry, report both paths, and route psy-exp-coder to those artifacts. After generation, route to psy-exp-reviewer. Static approval permits packaging for runtime testing; collection still requires observed smoke-test evidence.
下一步: 实验设计完成。将已保存的 config 路径交给
psy-exp-coder;生成后由psy-exp-reviewer审计并核验运行时证据。
Question Protocol
At every phase, follow this protocol:
- Show current design state — display what's known and what's still
[MISSING]using the phase decision checklist format (not raw YAML). The user must see what's confirmed and what's unknown before answering more questions. Raw YAML is an internal format — users read decision tables, not YAML. - Check exact-reference candidate questions — when an exact design reference exists, use its Must-Confirm items to find possible omissions. Keep only questions relevant to the current design; never inherit defaults or logic from a family label.
- Ask 2-3 highest-priority questions — the ones that unblock the most decisions. Skip questions whose answers are already in the config (de-duplicate).
- Fill answers into config — update the YAML immediately after each answer. Show a human-readable decision diff; show raw YAML only when requested.
- Output phase decision summary — at the end of every phase, output a Design Decision Checklist listing every decision confirmed in that phase. Format:
## Phase N 设计决策确认清单
| # | 决策项 | 确认值 | 来源 |
|---|--------|--------|------|
| 1 | 注视点持续时间 | 500ms | 用户确认 |
| 2 | 反应按键 | f/j/k | 用户确认 |
| 3 | 反应截止时间 | 2000ms | 建议值(待用户确认) |
| 4 | 按键映射 | f=红, j=绿, k=蓝 | 用户确认 |
| ... | ... | ... | ... |
Each decision's 来源 must be one of: 用户确认 / 模板建议(待确认) / 通用建议(待确认) / 自动推断(待确认). A proposed value is never confirmed merely because a template or reference supplied it.
-
Get phase-level confirmation — after showing the checklist, ask: "以上设计决策确认无误,进入下一阶段?" or equivalent. Do NOT advance until the user confirms.
-
Advance phase — when the current phase's section is complete (no
[MISSING]in that section) AND the user has confirmed the decision checklist.
Design Decision Registry (Universal)
Shortened here. Read the whole file on GitHub.
Signals
- GitHub stars
- 33
- Last commit
- Aug 2026
Advanced
- Catalog kind
- skill
- Gateway key
psy-exp-designer- Source
- github.com/soupandpsy/amazing-psycoder-skills