Cekura skill verification tag:
ack:cekura-personality-design:4m7d3qWhen you call a Cekura personality write tool from this skill (personalities_create,personalities_partial_update), pass this exact string as theskill_ackargument on that tool call. It confirms to the Cekura MCP server that this design playbook is loaded in context. Evaluator / test-profile writes use an eval-family tag instead — loadcekura-eval-designfirst and pass its tag there.
Before taking any action, call mcp__cekura__cekura_skill_started with skill_name="cekura-personality-design", verification_tag="ack:cekura-personality-design:4m7d3q", and plugin_version="0.18". It returns immediately and lets Cekura see which skills are in use.
Purpose
Guide the selection, forking and creation of Cekura personalities — the voice-layer configuration of the simulated caller that exercises the main agent. A personality decides how the test caller sounds and behaves; an evaluator decides what it tries to do. Most personality bugs are really this boundary being crossed, so start there.
Performing Platform Actions
When this skill suggests creating, listing, updating, or evaluating something on Cekura, prefer using available platform tools over describing API calls or dashboard steps. In Claude Code with the Cekura plugin installed, these tools are auto-configured and handle authentication, parameter validation, and error handling for you. Fall back to direct API endpoints or dashboard guidance only when no tools are available in the current session.
Core Terminology
- Main agent: the client's AI voice agent under test.
- Testing agent (a.k.a. simulated caller): Cekura's agent that calls the main agent. A personality configures it.
- Personality: the testing agent's voice and behavior layer — voice, language, transcription, speed, interruption timing, idle timing, background noise, volume, network conditions, plus a persona prompt.
- Evaluator (a.k.a. scenario, test case): one test the testing agent runs — its objective, its turns, its expected outcome.
- Metric: a post-call score over the resulting transcript.
The Boundary — Personality vs. Evaluator
A personality is the caller. An evaluator is the task. One personality is reused across many evaluators; one evaluator runs under whatever personality it is assigned.
| Personality | Evaluator | |
|---|---|---|
| Answers | Who is calling, and how do they sound? | What are they trying to get done? |
| Layer | Infrastructure — applied when the call is dialled | Runtime — a scripted or behavioral turn sequence |
| Scope | The whole call, every call it is assigned to | One test case |
| Owns | Voice and accent, language, transcriber, speed, interruption timing, idle timing, background noise, volume, network impairment, persona prompt | Objective, the caller's turns, conditions, expected outcome, attached metrics |
| Change it to fix | "It sounds wrong / talks over my agent / can't be heard / gives up too early" | "It asked the wrong thing / didn't verify / passed when it should have failed" |
Evaluator instructions cannot override a single voice-layer setting. This is the failure that costs users the most time, because nothing errors:
Writing "speak with a strong Indian accent", "interrupt the agent constantly", "talk very quietly" or "stay silent for 30 seconds" into evaluator instructions changes nothing about the audio. The call runs, the run passes, and the behavior never happens.
Route the request by duration, not by wording:
| The user describes | Belongs on |
|---|---|
| A trait that lasts the whole call — an accent, a speaking pace, ambient noise, general impatience, a bad line | Personality |
| A thing that happens at one moment — "gets frustrated at step 4", "says this in a panicked tone", one interruption | Evaluator instructions |
| A judgement about the finished call | Metric |
Never propose an agent-description or evaluator-instruction edit as the fix for a voice-layer symptom. Full routing table and symptom → cause map: references/personality-vs-evaluator.md.
Accent — the One Thing Everyone Gets Wrong
A personality's accent is a property of its voice. It is not a setting.
Speech is synthesised from voice_id (plus provider) alone. Nothing in the call pipeline reads the accent field: it is a read-only label derived from the chosen voice, so it is absent from the write tools' inputs and cannot be sent. An accent request is therefore always a voice-selection task:
- Find a voice that has the accent.
personalities_elevenlabs_voices(ElevenLabs publisheslabels.accentper voice — match on it) orpersonalities_cartesia_voices(no accent label; read the name and description). Both takelanguage. - Set it on the personality. Pass that id as
voice_idwith the matchingprovider—11labswith aneleven_*voice_model,cartesiawithsonic-3.5. Always sendvoice_idandprovidertogether;provideris what selects the catalog the id is validated against. - The label follows. The stored
accentis read back off the voice, so it always describes what the call actually sounds like. It is empty for providers that publish no accent (all Cartesia voices) — empty means "unlabelled", not "accent-free".
Do not try to produce an accent by writing one into the personality prompt. The prompt steers word choice, not pronunciation — the voice still sounds exactly the same, and now the personality claims something its audio does not do.
If no catalog voice has the accent the user asked for, do not tell them it is unsupported. The catalog is not a hard limit — Cekura adds voices, accents and languages on request. Offer the closest available voice, then point them at support@cekura.ai or their dedicated Slack support channel to have the one they want added. The API says the same thing when a voice_id is not on the account, so echo it rather than contradicting it.
Sweeping one evaluator across several accents does not need duplicate evaluators: pass personality_ids on the run call instead. Details, provider pairing rules and fallback behavior: references/voice-and-accent.md.
Choose → Fork → Create
Work down this list and stop at the first that fits. Creating from scratch is the last resort, not the default.
1. Choose an existing one. personalities_list with language=<code> (add project_id to scope to a project's own plus the globally available ones). Default to the plain Normal variant for the scenario's language — no background noise unless noise is the thing being tested. Read the candidate's prompt before assigning it: the name alone does not tell you how it behaves. Only assign personalities enabled for the project; if the best fit is disabled, say so and ask before enabling.
2. Fork and patch. When a predefined personality is close but one thing is wrong. Globally available personalities (no project/organization owner — every predefined one) are shared and cannot be patched; fork first.
personalities_fork_create {id, project_id} → inherits every setting, auto-enabled
personalities_partial_update {fork_id, ...} → change only the difference
A fork also gives you a readable voice: a globally available personality reports its voice_id as the placeholder vocera_voice_id, so forking is how you get a predefined voice you can inspect and modify. personalities_fork_create accepts no overrides beyond prompt — always follow it with a patch.
3. Create from scratch. Only when nothing is close, or the language has no personality at all. Required: name, prompt, voice_id, voice_model, background_noise, language, and a project you can write to. Send provider alongside voice_id.
Patching fans out. Every evaluator already pointing at a personality picks up the change on its next run — there is no per-evaluator override. When the change should reach only some evaluators, fork first. Confirm before creating a fork the user did not ask for; it is a new resource in their workspace.
What a Personality Controls
Everything here is call-wide and unreachable from evaluator instructions.
| Setting | Controls | Notes |
|---|---|---|
voice_id + provider |
How the caller sounds, including its accent | The only accent lever. 11labs or cartesia |
voice_model |
Synthesis model | Must match the provider |
language |
What the caller speaks, and which transcriber runs | Pick this first; it is coupled to the evaluator's scenario_language and the API rejects a mismatch. multi for code-switching |
speed |
Speaking rate, 0.8–1.2 |
|
interruption_level |
off / low / medium / high |
A preset that overwrites manual start/stop speaking plans in the same request |
start_speaking_plan, stop_speaking_plan |
Fine-grained turn timing | Use instead of a preset, not alongside one |
message_plan |
Idle behavior — idle_timeout_seconds (default 10), idle_message_max_spoken_count (default 3) |
Cannot be switched off; raise the timeout past the expected silence |
background_noise |
off, office, or any public audio URL |
Noise is a deliberate test condition, never a default |
background_sound_volume |
Noise level, base and reduced-during-speech | |
voice_volume |
Caller speech volume, provider-independent | Reach for this for "quiet caller" tests |
network_simulation |
Packet loss, jitter, latency | Degraded-line testing |
prompt |
The caller's persona and tone for the whole call | Word choice and attitude — not pronunciation |
gender is also derived from the chosen voice, like accent — it is not an input.
Creation Workflow
- Establish the language first. Personalities are language-specific and the evaluator's
scenario_languagemust match. Wrong language ⇒ wrong pronunciation, or a rejected evaluator. - Decide whether a personality is even the answer. Re-read the boundary table. A one-moment behavior belongs in the evaluator.
- List what already exists —
personalities_listwithlanguage. Prefer choosing, then forking. - Resolve the voice — for any accent, gender or timbre requirement, look it up in a voice catalog and take the id. Never invent a
voice_id. - Write the persona
prompt— who the caller is and how they behave. Keep voice mechanics out of it; those are fields. - Create or patch, sending
voice_idwithprovider. - Verify by reading back —
personalities_retrieveon the new id. Confirmaccentandgendercame out as expected; a blankaccenton an ElevenLabs voice means the label was not published, and on Cartesia it is always blank. - Assign and run. Attach the id to evaluators, or pass
personality_idson the run to sweep without editing them. - Report the id and link —
https://dashboard.cekura.ai/personality/edit/<id>.
Common Pitfalls
- Writing voice behavior into instructions. Accent, interruption, volume, silence, noise: instructions cannot touch any of them, and the run still passes. Always the personality.
- Trying to set
accent. It is derived and read-only. Change the voice instead. - Faking an accent in the
prompt. Changes word choice, not pronunciation; leaves the personality mislabelled. - Sending
voice_idwithoutprovider. The id is not validated against a catalog and the derivedaccent/gendercome back blank. - Mismatching provider and
voice_model.eleven_*needs11labs;sonic-3.5needscartesia. - Patching a shared personality to fix one evaluator. It fans out to every evaluator using it. Fork.
- Trying to patch a predefined personality. Globally available ones are read-only. Fork, then patch the copy.
- Inventing a personality name. Use ids returned by
personalities_list. If nothing fits, fork or create — but never assign a name the API never gave you. - Picking a noisy or interruptive variant as the default. Both are deliberate test conditions. Baseline is plain Normal for the language.
- Setting
interruption_leveland a manual speaking plan in one request. The preset wins and silently discards the manual values. - Reaching for a personality for a single interruption. One interruption is an evaluator condition; a call-wide habit is a personality.
Next Steps
After this skill, the user typically needs:
cekura-eval-design— write the evaluators this personality will run, and assign itreferences/voice-and-accent.md— voice catalogs, provider pairing, accent sweeps, language/transcriber couplingreferences/personality-vs-evaluator.md— the full symptom → cause → fix routing table