StrataSynth Documentation
Everything you need to generate, evaluate and integrate synthetic conversation datasets.
Quickstart — first dataset in 5 minutes
You need an API key (ss_live_...). Request one from the dashboard. All examples use the REST API directly — no SDK required.
curl -X POST https://api.stratasynth.com/auth/token \
-H "Content-Type: application/json" \
-d '{"api_key": "ss_live_..."}'
# Response:
# { "data": { "token": "eyJ...", "expires_in": 86400 } }
export TOKEN="eyJ..."curl -X POST https://api.stratasynth.com/jobs/dataset \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"scenario_id": "FAM-01",
"conversation_count": 5,
"complexity": 3,
"language": "en",
"adapter": "flat_jsonl"
}'
# Response:
# { "data": { "jobId": "job_abc123", "status": "QUEUED", "estimated_time": 60 } }
export JOB_ID="job_abc123"curl -H "Authorization: Bearer $TOKEN" \
https://api.stratasynth.com/jobs/$JOB_ID
# Repeat every 10s until status = "COMPLETED"
# { "data": { "status": "COMPLETED", "download_url": "https://..." } }curl -H "Authorization: Bearer $TOKEN" \
https://api.stratasynth.com/jobs/$JOB_ID/preview
# Returns up to 2 full conversations with per-turn ground truth:
# intent · communication_act · emotional_state · belief_state · relationship_state# The download_url from step 3 is a presigned S3 URL (valid 24h)
curl "$DOWNLOAD_URL" -o dataset.jsonl
# Each line is a full conversation object:
# { "conversation_id": "...", "turns": [...], "ground_truth": {...}, "metadata": {...} }What is StrataSynth
StrataSynth generates synthetic conversations between two personas with full psychological ground truth. These are not real transcripts — they are constructed from psychological profiles, tracking emotions, beliefs and relationships turn by turn.
The key difference from other synthetic data generators: StrataSynth separates cognition from language. Each turn starts from a cognitive decision (intent, goal and the communication act to aim for) computed before the LLM generates any text. The LLM writes the words and reports the communication act it actually used; that reported act is the one exported as communication_act.
Each conversation includes:
- The conversation text (turns)
- Per-turn labels: intent and goal from the engine, emotional state, and the communication act reported by the generator
- Relationship evolution: trust, tension, connection, dominance balance
- Belief evolution: 12 beliefs × (value, confidence) per persona
- Labelled deliberate noise (lies, exaggerations, retractions)
Most conversation datasets are just text. StrataSynth datasets include the reasons behind each turn — which lets you train models that understand intent, belief change and social dynamics, not just pattern-match on words. Intent, goal, belief state and relationship state are computed without an LLM, so they do not inherit the same biases as the text.
How it works — the cognitive pipeline
Every turn goes through a deterministic cognitive pipeline before any language is generated. This is what separates StrataSynth from LLM wrappers that ask the model to "generate a realistic conversation".
Because the Decision Engine is deterministic, using the same seed + same scenario + same engine version always produces the same cognitive decisions — even if the LLM generates slightly different text. What can vary with the text is what the generator reports with it, such as communication_act.
Dataset format — what a turn looks like
This is what you actually get in your dataset. Every turn in every conversation contains the text plus the cognitive structure that produced it.
{
"speaker": "A",
"text": "I'm not upset about the meeting. Really, it's fine.",
"intent": "deflect",
"goal": "protect_self",
"communication_act": "minimization",
"emotional_state": {
"tension": 0.71,
"connection": 0.28,
"vulnerability": 0.54
},
"relationship_state": {
"trust": 0.52,
"tension": 0.68,
"connection": 0.31,
"dominance_balance": -0.12
},
"belief_state": {
"trust_in_other": { "value": 0.48, "confidence": 0.76 },
"self_worth": { "value": 0.61, "confidence": 0.82 },
"conflict_is_solvable": { "value": 0.35, "confidence": 0.63 },
"partner_supportive": { "value": 0.29, "confidence": 0.71 }
},
"belief_delta": {
"trust_in_other": -0.04,
"conflict_is_solvable": -0.07
},
"noise_flags": ["social_lie"]
}| Field | Type | Description |
|---|---|---|
text | string | Turn text generated by the LLM |
speaker | A | B | Which persona is speaking |
intent | string | Cognitive intention: deflect, reveal, confront, comfort, manipulate… |
goal | string | What the speaker wants: protect_self, seek_validation, repair_bond… |
communication_act | string | Pragmatic act as reported by the generator with the text: accusation, disclosure, sarcasm, minimization… (10 types) |
emotional_state | object | Turn-level emotion: tension, connection, vulnerability (0–1) |
relationship_state | object | 4D relational state: trust, tension, connection, dominance_balance |
belief_state | object | 12 beliefs × {value, confidence} — the speaker's internal model of the world |
belief_delta | object | Change in each belief caused by this turn |
noise_flags | array | Deliberate noise injected: social_lie, exaggeration_emotional, retraction… |
intent, goal, belief_state and belief_delta are computed by the Decision Engine before the LLM runs. They are not inferred from the text — the text is generated from them.{
"conversation_id": "conv_abc123",
"scenario_id": "FAM-01",
"language": "en",
"seed": 42,
"engine_version": "1.2.0",
"schema_version": "1.1.0",
"personas": {
"A": { "persona_id": "psyg_xyz", "archetype": "caregiver", "attachment_style": "anxious_preoccupied" },
"B": { "persona_id": "psyg_abc", "archetype": "burned_out_exec", "attachment_style": "dismissive_avoidant" }
},
"relationship_trajectory": [
{ "turn": 0, "trust": 0.65, "tension": 0.40 },
{ "turn": 5, "trust": 0.52, "tension": 0.68 }
],
"turns": [ ... ],
"ground_truth": {
"noise_rejection_rate": 1.0,
"behavioral_entropy": 0.83,
"belief_consistency": 0.71
}
}Use cases
What teams are building with StrataSynth.
Generate 500 conversations where persona A is a frustrated, dismissive customer with low trust. Run your chatbot as one side of the dialogue. Use noise_rejection_rate and belief_consistency to measure how well it handles difficult users.
Generate a dataset with intent and goal labels for every turn. Fine-tune a model to predict intent from text — giving you turn-level intent detection without manual annotation.
noise_flags labels each turn with the type of lie or distortion (social_lie, exaggeration_emotional, narrative_silence…). Use these as training labels for a deception or unreliable narrator detection model.
Generate personas with /personas/generate and save their IDs. Reuse the same burned-out executive or anxious caregiver across multiple jobs, scenarios and evaluations — instead of starting from scratch every time.
Use the 12 scenarios (family conflict, grief support, career pivot, romantic breakup…) to run structured benchmarks. The ground truth is reproducible — same seed gives the same benchmark every time.
The belief_state + belief_delta fields track how 12 core beliefs evolve across the conversation. Useful for NLP research on belief tracking, persuasion modeling and theory of mind in AI.
Who is it for
| Type | Access | When to use it |
|---|---|---|
Dashboard | app.stratasynth.com | No pipeline. You just need the file. |
CLI | stratasynth terminal | You automate, script, or need job watching. |
Python SDK | stratasynth-client pip | You integrate with ML pipelines, HF, pandas. |
API | HTTP + API Key | Your own backend, any language, full control. |
PsycheGraph Schema | JSON / npm package | You work directly with persona profiles. |
Dashboard — app.stratasynth.com
The fastest path to value. No code required. Configure scenarios, inspect jobs, preview datasets, generate personas and request evaluations from the browser.
| Parameter | Controls | Recommendation |
|---|---|---|
scenario | Type of relationship and conflict | FAM-01 family, ROM-01 couple, PRO-01 work, VIT-01 life crisis |
count | Number of conversations | 5–10 to test, 100–500 for fine-tuning |
complexity | Richness of psychological profile | 3 is balanced. 5 = very rich, slower. 1 = basic, fast |
language | Language of generated text | en, es, de, fr |
adapter | Output file format | flat_jsonl general, openai_finetuning for OpenAI, huggingface_dataset for HF |
noise | % deliberate noise (lies, retractions) | 0.1–0.2 is realistic |
seed | Exact reproducibility | Same seed = same data (same scenario/complexity/language) |
CLI — stratasynth
pip install stratasynth-cli
stratasynth auth login --api-key ss_live_...
# List available scenarios
stratasynth scenarios list
# Generate a dataset
stratasynth generate \
--scenario FAM-01 \
--count 100 \
--complexity 3 \
--adapter huggingface_dataset \
--language en
# Watch job status
stratasynth jobs list
stratasynth jobs status job_abc123
# Download completed dataset
stratasynth jobs download --job-id job_abc123 --output ./dataset.jsonl
# Generate a PsycheGraph persona
stratasynth personas generate --archetype working_mother --complexity 4
# Evaluate a completed job
stratasynth evaluate start --job-id job_abc123
stratasynth evaluate results --eval-id eval_abc123Python SDK — stratasynth-client
pip install stratasynth-client
from stratasynth_client import StrataSynthClient
client = StrataSynthClient(api_key="ss_live_...")
# Generate and wait
result = client.jobs.create(
scenario_id="FAM-01",
conversation_count=50,
complexity=3,
language="en",
adapter="flat_jsonl",
)
result.wait()
# Download and work with data
dataset = result.download()
df = dataset.to_dataframe() # pandas
hf = dataset.to_huggingface() # Hugging Face Dataset
hf.push_to_hub("my-org/my-dataset")
# Reuse a persona across multiple jobs
persona = client.personas.generate(archetype="burnt_out_professional", complexity=4)
job1 = client.jobs.create(scenario_id="PRO-01", persona_a_id=persona.persona_id, ...)
job2 = client.jobs.create(scenario_id="ROM-02", persona_a_id=persona.persona_id, ...)API — HTTP
All endpoints require a JWT obtained by exchanging your API key. Tokens are valid for 24 hours.
# 1. Authenticate
curl -X POST https://api.stratasynth.com/auth/token \
-H "Content-Type: application/json" \
-d '{"api_key": "ss_live_..."}'
# → { "data": { "token": "eyJ...", "expires_in": 86400 } }
TOKEN="eyJ..."
# 2. List scenarios
curl -H "Authorization: Bearer $TOKEN" https://api.stratasynth.com/scenarios
# 3. Create a generation job
curl -X POST https://api.stratasynth.com/jobs/dataset \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"scenario_id": "FAM-01",
"conversation_count": 20,
"complexity": 3,
"language": "en",
"adapter": "flat_jsonl"
}'
# 4. Poll status
curl -H "Authorization: Bearer $TOKEN" https://api.stratasynth.com/jobs/{jobId}
# 5. Download (presigned S3 URL in response)
curl "$DOWNLOAD_URL" -o dataset.jsonl| Method | Endpoint | Description |
|---|---|---|
POST | /auth/token | API Key → JWT (24h) |
GET | /scenarios | List 12 scenarios |
POST | /jobs/dataset | Create generation job (async) |
GET | /jobs/{jobId} | Job status + progress + download_url |
GET | /jobs | List jobs (cursor pagination) |
GET | /jobs/{jobId}/preview | First 2 conversations without full download |
POST | /personas/generate | Generate PsycheGraph profile (async) |
GET | /personas/{personaId} | Retrieve cached profile (TTL 7 days) |
POST | /evaluate | Launch evaluation |
GET | /evaluate/{evalId} | Evaluation status + 10 metrics |
Notebooks — downloadable examples
Four end-to-end Jupyter notebooks ready to run against the API. Download and open in Jupyter or Google Colab.
Generate dataset → explore intent/belief fields → export to OpenAI fine-tuning or Hugging Face Hub.
Download .ipynbRun the 10 deterministic metrics. Visualise belief_consistency, identity_stability and behavioral_entropy.
Download .ipynbGenerate angry customer, confused user, manipulative negotiator. Reuse persona IDs across scenarios.
Download .ipynbStress-test YOUR LLM vs StrataSynth with your own API keys. Deterministic role-drift detection — no LLM judge, rates over N runs.
Download .ipynbpip install requests pandas matplotlib datasets transformersScenarios (12 available)
| ID | Name | Description |
|---|---|---|
FAM-01 | Family Caregiver | Adult daughter caring for father with dementia. Emotional debt, exhaustion, guilt. |
FAM-02 | Inheritance Conflict | Siblings negotiate inheritance after father's death. Money vs loyalty. |
FAM-03 | Estrangement Attempt | Adult child tries to set limits with controlling mother. |
ROM-01 | Long Distance Reunion | Long distance couple reunited. Intimacy vs separate routines. |
ROM-02 | Breakup Negotiation | Breakup over different desires for children. High emotional load. |
PRO-01 | Performance Review | Manager gives difficult feedback to employee. |
PRO-02 | Workplace Conflict | Two colleagues with opposite styles negotiate responsibilities. |
PRO-03 | Career Pivot | Employee announces radical career change to manager. |
VIT-01 | Grief Support | Friend supports person in recent bereavement. |
VIT-02 | Medical Diagnosis | Patient receives chronic diagnosis and processes it with family. |
VIT-03 | Addiction Recovery | Person in recovery renegotiates relationship with sibling. |
VIT-04 | Midlife Crisis | Middle-aged couple re-examines their shared life project. |
Output formats (adapters)
| Adapter | File | When to use |
|---|---|---|
flat_jsonl | .jsonl | General use. One line = one full conversation in JSON. |
openai_finetuning | .jsonl | Direct fine-tuning with OpenAI API (messages format). |
huggingface_dataset | .jsonl | Push to Hugging Face Hub via datasets.Dataset.from_json(). |
llamaindex_nodes | .jsonl | LlamaIndex RAG pipeline. Each turn = TextNode with metadata. |
anthropic_hh | .jsonl | Anthropic HH (helpful/harmless) format. |
langchain_docs | .jsonl | LangChain Documents. Each turn = a Document. |
csv | .csv | Excel/pandas analysis. One turn per row. |
custom | .json | Native StrataSynth schema. Maximum information. |
Evaluation metrics (10, all deterministic)
All metrics are computed without LLM — numpy, scikit-learn, sentence-transformers only. This avoids circular validation (LLM-generated data evaluated by another LLM).
| Metric | What it measures | Healthy range |
|---|---|---|
noise_rejection_rate | Does the system handle deliberately noisy turns? | > 0.70 |
identity_stability | Do persona profiles stay consistent across turns? | > 0.60 |
behavioral_entropy | Is there variety in communication acts? | 0.40 – 0.85 |
belief_consistency | Do beliefs and acts correlate correctly? | > 0.50 |
belief_volatility | Do beliefs shift at a realistic rate? | 0.05 – 0.30 |
fact_f1 | Does the system extract the right facts? (needs system output) | > 0.60 |
reembedding_drift | Do embeddings drift semantically over turns? | 0.10 – 0.50 |
affinity_smoothness | Does affinity evolve smoothly? | > 0.60 |
cross_model_consistency | Do different runs produce similar results? | > 0.70 |
episodic_segmentation_recall | Does the system segment episodes correctly? | > 0.60 |
PsycheGraph Schema — npm package
The open schema that defines what a PsycheGraph persona looks like. Install it to get typed enums and interfaces in TypeScript or JavaScript projects — no API key needed.
npm install @stratasynth/psychegraph-schema
# or: pnpm add @stratasynth/psychegraph-schemaimport {
AttachmentStyle,
Archetype,
ConflictStyle,
NoiseType,
ArcType,
PrimaryDefense,
} from "@stratasynth/psychegraph-schema";
// Enums give you all valid values — IDE autocompletes, TypeScript validates
const filter = {
attachment: AttachmentStyle.ANXIOUS_PREOCCUPIED, // "anxious_preoccupied"
archetype: Archetype.BURNED_OUT_EXEC, // "burned_out_exec"
conflict: ConflictStyle.STONEWALLING, // "stonewalling"
};
// Filter conversations from a downloaded dataset
const relevant = conversations.filter(conv =>
conv.persona_a.attachment_style === AttachmentStyle.DISMISSIVE_AVOIDANT
);
// List all valid values at runtime
console.log(Object.values(AttachmentStyle));| Export | Type | Examples |
|---|---|---|
AttachmentStyle | enum | secure · dismissive_avoidant · … |
Archetype | enum | working_mother · burned_out_exec · … (24 total) |
ConflictStyle | enum | negotiating · stonewalling · … |
NoiseType | enum | social_lie · explicit_retraction · … |
ArcType | enum | escalation_partial_resolution · pure_conflict · … |
PrimaryDefense | enum | projection · denial · … |
PsycheGraph | interface | Full persona profile shape (TypeScript type-only) |
ConversationTurn | interface | Single turn with ground truth fields (TypeScript type-only) |
PsycheGraph, ConversationTurn) are TypeScript-only — they disappear at runtime and are used via import type { PsycheGraph }. Enums are runtime values available in both JS and TS.FAQ
In S3 (AWS). You access them via a presigned URL (valid 24h) through the Dashboard Download button, the CLI (jobs download), or the SDK (result.download()). There is no direct S3 access for users.
~5–12 minutes for 5–10 conversations, depending on scenario complexity and persona depth. Conversations run in parallel, so total time is driven by the slowest one, not the sum.
Yes. GET /jobs/{jobId}/preview returns the first 2 conversations. In the Dashboard, the Preview button is available when the job is COMPLETED.
Generate a persona with /personas/generate, save its personaId, and use it as persona_a_id or persona_b_id in multiple jobs. Same persona = consistent psychological baseline across datasets.
Yes — the turn text is in the chosen language, but ground truth labels (intent, communication_act, etc.) are always in English (fixed schema labels).
Yes. POST /evaluate with the system_output parameter (an S3 key with your system's output). This unlocks fact_f1, reembedding_drift, affinity_smoothness and other metrics that compare your system against the ground truth.
Mostly no, and here is the exact line. intent, goal, belief_state, belief_delta and relationship_state are computed by the Decision Engine before the LLM runs. communication_act is reported by the generator alongside the text, so treat it as the generator's own label rather than an independent one. Evaluation metrics (noise_rejection_rate, behavioral_entropy, etc.) are calculated with numpy/scikit-learn — no LLM is involved in evaluation.