Persona & Scenario Studio: typed test cases you can measure
June 23, 2026 · View on GitHub
Twin:
examples/sdk_persona_scenario_studio.py· emitsagent-learning.persona-library.v1· offline, no credentials. A coding agent can complete this page from the frontmatter alone.
1. What you are testing
A free-text persona ("an impatient customer") is unmeasurable: you cannot tell
whether the simulated user actually behaved impatiently or the model just said
it would. The studio replaces prose with five typed layers — identity,
temperament, behavior_policy, knowledge, provenance — where the behavior policy
is executable and searchable. The six canon behavior axes (patience,
disclosure, interruption, escalation, cooperation, repair) each ship
paired one-to-one with a transcript-observable realization metric
(turns_to_escalation, info_withholding_rate, interruption_count,
intensity_trajectory_match, compliance_rate, repair_turn_fraction). An
axis with no realization metric does not ship.
The temperament axes (rajas, sattva, tamas) are a scholarly design device
used as deterministic engineering metadata, never a psychometric claim about
simulated users — and they always appear with their realization metrics, which
is what makes them falsifiable rather than decorative. Demographics are
optional, always lint-flagged, and explain about 1.5% of behavioral variance.
No layer ever claims population representativeness; the schema says so
(representativeness_claim: "none"), not just the docs.
Legacy embedded-dict personas keep working unchanged: they validate, run, and
auto-upgrade with provenance=legacy — they simply stay untyped and produce no
fidelity evidence.
2. Run it
python examples/sdk_persona_scenario_studio.py artifacts/persona-scenario-studio.json
The example runs entirely on the committed examples/persona_library/
fixtures: it round-trips typed personas, upgrades a legacy row, compiles
behavior policies, writes a content-addressed library, computes obligation
coverage with a budgeted residual estimator, runs the set-level bias lint, and
imports Vapi/Retell personas byte-exact. No network, no API key.
3. What you built
A content-addressed persona/scenario library (agent-learning.persona-library.v1):
each persona and scenario is stored under its own sha256 content hash, so a
hand-edit is loud (the re-hash mismatches and the load is refused). Coverage is
reported as obligation coverage per axis plus a residual estimate — never a
global library count; library_size and scenario_count are forbidden headline
keys. The whole thing is local-first under .agent-learning/library/.
4. When it fails
agent-learn doctor reports missing_engine_modules when the simulation engine
is not importable, and api_key_configured for the keyed pull lane (not needed
for this page — everything here is local). A persona that declares a behavior
axis without its realization metric is refused by validate_persona; a
demographics-bearing persona is flagged and cannot be admitted until the
set-level bias lint passes.
5. Prove it / keep it
The persona_scenario_studio_readiness release gate executes this exact example
on every release-check and audits the fidelity admission loop, calibration
lifecycle, coverage, bias lint, vendor import parity, and scan refusals. To
prove it live, the keyed account pull (agent-learn persona pull) downloads
real personas with full pin + checksum + content-scan provenance — linked here,
never claimed offline.