Social Simulation
From an explicit interaction design to inspectable Concordia code, recorded runs, transcripts, and outcomes—with the social process itself as the object of study.
01 Orientation
Many experiments ask isolated people to answer the same question. Social simulation asks something different: what happens when agents act, react, reveal information, bargain, coordinate, or disagree inside a shared situation?
OneHeart is the study-definition and code-generation layer for that work. It stores the design as durable project state, validates it, and generates an inspectable pilot runner. Concordia supplies the simulation machinery; Expected Parrot EDSL supplies model access and post-run measurement.
Use OneHeart
When two or more agents interact, their roles and information matter, and treatments or outcomes must be tracked across runs.
Use a survey workflow
When each respondent independently reacts to a vignette or question and the interaction itself is not the research object.
Canonical state
The study specification under .oneheart/ is the durable record of intended design.
Derived artifacts
Generated runners, logs, transcripts, HTML chats, and outcome tables are inspectable products of that design.
02 The study model
A study becomes runnable when four pieces agree with one another.
| Piece | Question it answers | Typical contents |
|---|---|---|
| Interaction frame | What world and protocol do agents share? | Premise, turn order, maximum turns, game master |
| Agents | Who acts, what do they know, and what do they want? | Role, goal, public bio, private context, stable attributes |
| Treatments | What changes exogenously between conditions? | Scope, target, levels, visibility, behavioral instructions |
| Measurements | What evidence will answer the research question? | Outcome type, evaluator, extraction prompt |
03 Design before code
Begin with a causal contrast small enough to inspect. A good first pilot usually has two to four agents, one treatment, one primary outcome, and a short interaction.
A worked question
This tutorial uses a hiring interview: does an opening compliment increase the interviewer’s hiring rating? The candidate receives either a compliment or neutral-opening instruction; the interviewer and the rest of the setting remain fixed.
| Design choice | Pilot decision | Reason |
|---|---|---|
| Protocol | ordered_dialogue, 8 turns | Clear alternation and a bounded first run |
| Prefab | conversational | Produces spoken dialogue rather than third-person narrative |
| Treatment | compliment / no compliment | One legible causal contrast |
| Primary outcome | 1–7 hiring rating | Specific and answerable from the completed interview |
| Manipulation check | compliment noticed? | Separates a null effect from a failed manipulation |
04 Create the project and interaction
oneheart init compliment_interview --title "Compliment Interview Pilot"
cd compliment_interview
oneheart study create compliment_effect \
--title "Opening compliment effect" \
--description "Candidate opens a job interview with or without a compliment."
oneheart study set-interaction compliment_effect \
--premise "A final-round interview for a B2B marketing manager role." \
--protocol ordered_dialogue \
--max-turns 8 \
--game-master dialogic
The premise describes common ground. It should contain what remains constant across conditions, not treatment-specific language. OneHeart supports ordered, random, and game-master-selected dialogue protocols.
| Protocol | Best use | Concordia acting order |
|---|---|---|
ordered_dialogue | Controlled alternation and inexpensive pilots | fixed |
random_dialogue | Speaker order is legitimately variable | random |
gm_choice_dialogue | The game master should choose the natural next speaker | game_master_choice |
05 Give agents goals and information
A name is not a social actor. Each focal agent needs a role, a goal, and enough context to behave distinctly. Keep public facts separate from information that only one agent should know.
oneheart agent add compliment_effect candidate \
--name "Alex Rivera" --role candidate \
--goal "Demonstrate fit and earn a strong hiring recommendation." \
--prefab conversational \
--public-bio "Five years of B2B SaaS marketing experience." \
--private-context "Especially strong in demand generation and product marketing."
oneheart agent add compliment_effect interviewer \
--name "Jordan Ellis" --role interviewer \
--goal "Assess fundamentals, results, and communication fairly." \
--prefab conversational
Use conversational for dialogue, basic when reflection and associative memory matter outside dialogue, and minimal for cheaper sweeps where richness is secondary.
oneheart agent attribute-set compliment_effect interviewer \
evaluation_style=evidence-focused
06 Make treatments behavioral
Treatment level names are labels, not instructions. A model does not reliably infer the intended behavior from opening_compliment=compliment. Define the factor, then attach an explicit stage direction to every level.
oneheart treatment add compliment_effect opening_compliment \
--scope agent --target candidate --type binary \
--levels compliment,no_compliment --private
oneheart treatment level-set compliment_effect opening_compliment compliment \
--instruction "Open with one sincere, specific compliment about the company or interviewer's work before answering. Do not compliment again."
oneheart treatment level-set compliment_effect opening_compliment no_compliment \
--instruction "Open with a brief neutral professional greeting. Do not compliment the interviewer at any point."
Agent-scoped instructions enter the target agent’s resolved prompt. Study- or environment-scoped instructions enter the resolved premise. Visibility should reflect the design: a private instruction is not automatically shared with the other participants.
07 Define observable measurements
Measurements are extraction questions asked after the simulation. Make each prompt answerable from the transcript or simulation context, name the evaluator, and choose a response type that matches the construct.
oneheart measurement add compliment_effect hiring_rating \
--kind outcome --response-type numeric --agent interviewer \
--prompt "On a 1–7 scale, how strongly would you recommend hiring the candidate?"
oneheart measurement add compliment_effect would_hire \
--kind outcome --response-type boolean --agent interviewer \
--prompt "Would you hire the candidate? Answer yes or no."
oneheart measurement add compliment_effect noticed_compliment \
--kind process --response-type boolean --agent interviewer \
--prompt "Did the candidate compliment you during the interview? Answer yes or no."
| Weak prompt | Stronger prompt |
|---|---|
| “How did it go?” | “Did the parties reach an agreement? Answer yes or no.” |
| “Was the candidate good?” | “On a 1–7 scale, how strongly would you recommend hiring the candidate?” |
| “Measure warmth.” | “Rate the interviewer’s warmth during the exchange from 1 (cold) to 7 (very warm).” |
08 Validate design and environment
Structural validation and runtime validation answer different questions. Run both before generation.
oneheart status
oneheart validate compliment_effect
oneheart doctor
oneheart validate compliment_effect --check-env
| Check | What it catches | Typical response |
|---|---|---|
status | Current project phase, counts, and next actions | Continue from the returned checklist |
validate | Missing frame, agents, treatments, measurements, or prefab mismatch | Repair the study definition |
doctor | Python, Concordia, and EDSL availability | Activate or install the intended runtime |
--check-env | Study readiness and runtime readiness together | Generate only after both pass |
Generated runners expect the Expected Parrot Concordia fork with EDSL support. If Concordia exists only as a checkout, the runner accepts --concordia-src /path/to/concordia.
09 Generate, then inspect
oneheart codegen pilot compliment_effect
Read prompts.md before spending model calls. Confirm that the resolved premise is correct, every agent receives the intended context, every treatment has a level-specific instruction, and every measurement is unambiguous.
10 Execute the pilot explicitly
python oneheart_jobs/compliment_effect/run_pilot.py --confirm-prompts
For repeat runs of the same generation, create the acknowledgement file once and run without the flag:
touch oneheart_jobs/compliment_effect/prompts.acknowledged
python oneheart_jobs/compliment_effect/run_pilot.py
The runner performs a model preflight, builds Concordia entities and the game master, runs the simulation, writes logs and transcripts, and uses EDSL to extract the configured measurements.
| Runner option | Purpose |
|---|---|
--model / --service-name | Override the EDSL model or provider |
--disable-remote-inference | Call the underlying provider rather than Expected Parrot remote inference |
--disable-language-model | Exercise structure cheaply with Concordia’s no-LM backend; measurements are not substantive |
--concordia-src | Use a local Concordia checkout |
--output-dir | Choose a different artifact directory |
11 Record provenance and export evidence
A generated directory is working code; a run record connects what was generated to what actually ran. Preserve the generation ID returned by codegen and record seed and model metadata.
oneheart run record compliment_effect \
--type pilot \
--generated <generation_id> \
--outputs oneheart_jobs/compliment_effect/outputs/pilot_summary.json \
--seed 42 \
--model gpt-5.4
oneheart export outcomes --output .oneheart/exports/outcomes.csv
oneheart export chat-html \
oneheart_jobs/compliment_effect/outputs/simulation_log.json \
--output writeup/compliment-chat.html
Keep both forms of evidence: the transcript shows whether the social process was credible, while the outcome table supports comparisons across recorded runs.
12 From one pilot to a comparison
A treatment is a design object, but a generated pilot resolves one condition. Generate and run each arm deliberately, keeping the agents, setting, measurements, model policy, and analysis constant.
# For a two-level treatment, "first" selects the first declared level;
# "midpoint" selects the second. Separate output directories avoid overwrites.
oneheart codegen pilot compliment_effect --selector first \
--output-dir oneheart_jobs/compliment_arm
oneheart codegen pilot compliment_effect --selector midpoint \
--output-dir oneheart_jobs/no_compliment_arm
- Generate the compliment condition and inspect its resolved prompt.
- Generate the neutral condition and verify that only the intended instruction changes.
- Run multiple seeds within each arm; one run per arm cannot estimate variation.
- Record every run and export a single outcome table.
- Inspect manipulation checks and transcript excerpts before estimating treatment differences.
13 Interpret without overclaiming
Simulation results characterize a configured model world. They do not automatically estimate how real people would behave. Interpretation should separate implementation validity, within-simulation evidence, and external validity.
| Question | Evidence | Failure to watch for |
|---|---|---|
| Did the treatment land? | Resolved prompts, opening turns, manipulation check | The level existed only as an inert label |
| Was the interaction credible? | Transcript and structured log | Narration, role leakage, repetitive or implausible dialogue |
| Was the outcome measured well? | Typed output and extraction prompt | Ambiguous scale or unsupported inference |
| Is the effect stable? | Replicates, seeds, agent/model variants | Reading causality from one trajectory |
| Does it generalize? | Human validation or empirical benchmarks | Treating model behavior as population truth |
14 Command reference and recovery
| Command | Purpose |
|---|---|
oneheart status | Read project phase, counts, checklist, and next steps |
oneheart doctor | Check Python, Concordia, and EDSL |
oneheart docs list|show|search | Read bundled offline guidance |
oneheart study … | Create, configure, inspect, list, or select a study |
oneheart agent … | Add agents and stable attributes |
oneheart treatment … | Add experimental factors and per-level instructions |
oneheart measurement add | Define typed post-run extraction questions |
oneheart validate | Check study readiness, optionally including environment |
oneheart codegen pilot | Write provenance and an inspectable runnable copy |
oneheart run record | Connect completed outputs to generation metadata |
oneheart export … | Write outcome tables and chat artifacts |
# The recovery loop for humans and coding agents:
oneheart status
oneheart docs show workflow
oneheart docs show study-design
oneheart docs show codegen
Prefer CLI mutations to hand-editing files under .oneheart/studies/. If a generated runner needs study-specific refinement, edit the working copy under oneheart_jobs/; leave the immutable provenance snapshot intact.