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 involves a full cognitive decision (intent, goal, communication act) computed before the LLM generates any text. The LLM only renders the words — it does not decide what the persona does.
Each conversation includes:
- The conversation text (turns)
- Per-turn ground truth: intent, goal, communication act, emotional state
- 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. The ground truth is computed without LLM, so it does 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. Ground truth labels are always identical for the same seed.
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: 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.
No. intent, goal, communication_act and belief_state are computed by the Decision Engine before the LLM runs. Ground truth metrics (noise_rejection_rate, behavioral_entropy, etc.) are calculated with numpy/scikit-learn. No LLM is involved in evaluation.