Multi-Charakter-Szenen
Definiere typisierte Beziehungen zwischen Personas, öffne eine Session mit mehreren Sprechern und orchestriere Szenen-Turns, ohne dass ihre Stimmen ineinander kollabieren.
Eine Szene mit zwei oder mehr Personas ist eine andere Runtime als Single-Persona-Chat. Die Stimmen müssen distinkt bleiben, die Beziehungen müssen lesbar bleiben und der Nutzer (oder wer auch immer orchestriert) muss kontrollieren, wer wann spricht. Dieses Tutorial verdrahtet diese drei Anliegen.
1. Zwei Personas erstellen
const mert = await client.personas.createPersona({
intent: 'Ein 34-jähriger Gründer aus Istanbul. Brillant, aber rastlos.',
workspaceId: 'ws_...',
});
const leyla = await client.personas.createPersona({
intent:
'Eine 32-jährige Design-Leadin in Berlin. Scharf, prinzipientreu, allergisch gegen Corporate-Jargon.',
workspaceId: 'ws_...',
});2. Die Beziehung deklarieren
POST /v1/personas/{id}/relationships schreibt eine Kante in den
Ensemble-Graphen. Die Runtime
konsultiert diesen Graphen bei jedem Multi-Persona-Turn.
await client.personas.createRelationship({
personaId: mert.id,
with: leyla.id,
type: 'ex-lover',
note: "Co-Gründer, die im selben Quartal ein Unternehmen und eine Beziehung getrennt haben. Höflich, aber vorsichtig.",
});Die Kante ist standardmäßig bidirektional. Beide Personas wissen nun voneinander, wenn sie in einer gemeinsamen Session sprechen.
3. Die Multi-Persona-Session öffnen
const session = await client.chat.createSession({
personaId: mert.id,
ensemble: [leyla.id],
metadata: { sceneId: 'pitch-meeting-q3' },
});ensemble ist das Array zusätzlicher Personas in der Szene. Die
Runtime kennt alle; du wählst den Sprecher in jedem Turn.
4. Turns treiben
const mertSays = await client.chat.sendMessage({
sessionId: session.id,
speaker: mert.id,
content: 'Erzähl mir, was beim All-Hands passiert ist.',
});
const leylaSays = await client.chat.sendMessage({
sessionId: session.id,
speaker: leyla.id,
content: 'Du weißt schon, was passiert ist. Warum fragst du mich hier?',
});Das speaker-Feld ist die Persona-ID, die antworten soll. Der
Prompt-Assembly enthält das volle Layer-Dokument des Sprechers plus
die relevanten Beziehungs-Kanten (Leyla spricht → Merts ex-lover-
Kante wird injiziert).
Jede Antwort trägt weiter ihr eigenes Drift-Envelope, gescored gegen den Fingerprint des Sprechers — nicht gegen eine geteilte Szenen-Baseline. Die Stimmen bleiben separat messbar.
5. Auf Konvergenz achten
In langen Szenen können Stimmen aufeinander zudriften. Re-check Distinctiveness regelmäßig:
const distance = await client.consistency.compare({
fromPersonaId: mert.id,
toPersonaId: leyla.id,
});
if (distance.value < 0.25) {
console.warn('Stimmen konvergieren — Fingerprints refreshen oder re-prompten');
}6. Orchestrierung gehört dir
Moonborn verwaltet weder Turn-Reihenfolge noch Scene-State noch verzweigtes Narrativ. Diese Anliegen leben in deinem Application- Code oder Agent-Framework. Die Produktoberfläche oben ist die Charakter-Schicht.
Für Game-Maker heißt das typischerweise, Moonborn mit einer Szenen-State-Machine zu paaren (XState, deine eigene Enum-basierte). Für UX-Forscher heißt es, ein Panel zu scripten, in dem jeder Persona dieselbe Frage der Reihe nach gestellt wird.
Weiter
- Produktions-Patterns: Game NPC orchestration use case.
- Ein Synthetic-Panel bauen: Synthetic user panel tutorial.
- Ensemble API reference.