Open app
Moonborn — Developers

Ensemble relationship graphs

Declare typed edges between personas — rival, ex-lover, mentor — and let multi-persona prompts pick up the context.

A cast without relationships is a list of monologues. Moonborn's ensemble graph encodes who knows what about whom.

Edge types

Common types (configurable per workspace; this is the built-in set):

  • family — parent / sibling / child / spouse / ex-spouse
  • romantic — partner / ex-lover / unrequited / one-night
  • mentor — mentor / protégé / former-mentor
  • peer — colleague / collaborator / rival
  • power — employer / employee / patron / client
  • social — friend / acquaintance / enemy / nemesis

Declare an edge

await client.personas.createRelationship({
  personaId: mert.id,
  with: leyla.id,
  type: 'ex-lover',
  note: 'Co-founders who split a company and a partnership in the same quarter.',
});

Edges are bidirectional by default — both personas see the relationship in multi-persona sessions.

Query the graph

const rels = await client.personas.listRelationships({ id: mert.id });
for (const r of rels) {
  console.log(`${r.type}${r.with.name}: ${r.note}`);
}

How prompts use the graph

When persona B is the speaker in a session that includes persona A:

  • The runtime fetches the A↔B edge (if any).
  • The edge type + note get injected into B's system prompt.
  • B's reply reflects the relationship — without you re-stating it.

Asymmetric edges

For relationships where each side sees the other differently:

// Mert sees Leyla as ex-lover.
await client.personas.createRelationship({
  personaId: mert.id,
  with: leyla.id,
  type: 'ex-lover',
  note: 'I still respect her.',
  bidirectional: false,
});
 
// Leyla sees Mert as rival.
await client.personas.createRelationship({
  personaId: leyla.id,
  with: mert.id,
  type: 'rival',
  note: 'Co-opted my idea, never apologized.',
  bidirectional: false,
});

This produces a scene where their interpretations of the same shared past diverge — useful narrative tension.

Limits

  • Max 50 edges per persona (engine.ensemble.max_edges, configurable).
  • Cycles allowed; the runtime resolves edge lookup per-turn so no infinite expansion.

Tier

Pro and up.

Related