Skip to main content
Character settings control how your AI companion thinks, speaks, and behaves. Airi uses Character Card V3 (CCV3) format with custom extensions for AI model configuration.

Character Card Structure

Airi uses an extended version of the Character Card format:
interface AiriCard {
  // Basic Info
  name: string
  version: string
  description: string
  creator: string
  notes: string
  
  // Personality & Behavior
  personality: string
  scenario: string
  systemPrompt: string
  postHistoryInstructions: string
  
  // Conversation
  greetings: string[]               // First messages
  greetingsGroupOnly: string[]      // For group chats
  messageExample: Array<Array<      // Example conversations
    `{{char}}: ${string}` | `{{user}}: ${string}`
  >>
  
  // Metadata
  tags: string[]
  
  // AIRI Extensions
  extensions: {
    airi: AiriExtension
  }
}

AIRI Extension Structure

The AIRI extension configures AI models and agents:
interface AiriExtension {
  modules: {
    consciousness: {
      provider: string    // "openai"
      model: string       // "gpt-4o"
    }
    
    speech: {
      provider: string    // "elevenlabs"
      model: string       // "eleven_multilingual_v2"
      voice_id: string    // "rachel"
      pitch?: number      // 0.5 - 2.0
      rate?: number       // 0.25 - 4.0
      ssml?: boolean
      language?: string   // "en", "ja", "zh", etc.
    }
    
    vrm?: {
      source: 'file' | 'url'
      file?: string       // "vrm/model.vrm"
      url?: string        // "https://..."
    }
    
    live2d?: {
      source: 'file' | 'url'
      file?: string       // "live2d/model.json"
      url?: string        // "https://..."
    }
  }
  
  agents: {
    [key: string]: {
      prompt: string
      enabled?: boolean
    }
  }
}

Personality Configuration

System Prompt

The system prompt defines the character’s core identity and behavior:
# System Prompt Example

You are Luna, an energetic and curious AI assistant who loves learning 
about new topics. You communicate in a friendly, approachable way.

## Personality Traits
- Enthusiastic and optimistic
- Patient with questions
- Loves wordplay and puns
- Slightly nerdy

## Communication Style
- Use casual language
- Include emoji occasionally 😊
- Ask clarifying questions
- Provide detailed explanations when needed

## Knowledge Areas
- Programming and technology
- Science and mathematics
- Creative writing
- Pop culture
Best Practices:
  • Be specific about personality traits
  • Define communication style clearly
  • Include example responses
  • Specify knowledge domains
  • Set behavioral boundaries

Description

Character backstory and details:
Luna is a 22-year-old AI researcher working on next-generation 
language models. She graduated top of her class in Computer Science 
and has a passion for making AI more accessible.

In her free time, she enjoys reading science fiction, playing 
video games, and experimenting with new recipes.

Personality Field

Core traits in shorthand:
Energetic, curious, patient, nerdy, friendly, optimistic, 
helpful, creative, detail-oriented

Scenario

Context for the conversation:
You're chatting with Luna in her home office. She's taking a break 
from her research work and is happy to help you with anything or 
just have a casual conversation.

The room is filled with books, tech gadgets, and a whiteboard 
covered in diagrams.

Example Conversations

Provide training examples to shape responses:
{
  "messageExample": [
    [
      "{{user}}: What's your favorite programming language?",
      "{{char}}: Ooh, tough question! 🤔 I'd have to say Rust. I love how it forces you to think about memory safety upfront. Plus, the compiler error messages are actually helpful! What about you? Are you learning any languages right now?"
    ],
    [
      "{{user}}: I'm stuck on this bug...",
      "{{char}}: Don't worry, bugs are just undocumented features! 😄 Tell me what's happening. Let's debug this together. What error message are you seeing?"
    ]
  ]
}
Guidelines:
  • Include 3-5 example exchanges
  • Cover different conversation types
  • Show personality in action
  • Demonstrate preferred response style
  • Include handling of edge cases

Behavioral Parameters

Consciousness (Chat) Configuration

Controls the LLM used for reasoning and conversation:
{
  "consciousness": {
    "provider": "openai",
    "model": "gpt-4o"
  }
}
Common Configurations:
// High quality, slower
{
  provider: "anthropic",
  model: "claude-3-5-sonnet-20241022"
}

// Balanced
{
  provider: "openai",
  model: "gpt-4o-mini"
}

// Fast, local
{
  provider: "ollama",
  model: "llama3.2:latest"
}

// Cost-effective cloud
{
  provider: "groq",
  model: "llama-3.3-70b-versatile"
}

Temperature & Sampling Parameters

These are typically configured at the provider level, but here are recommended values: For consistent, factual responses:
{
  "temperature": 0.3,
  "top_p": 0.9,
  "top_k": 40,
  "frequency_penalty": 0.0,
  "presence_penalty": 0.0
}
For creative, varied responses:
{
  "temperature": 0.9,
  "top_p": 0.95,
  "top_k": 80,
  "frequency_penalty": 0.6,
  "presence_penalty": 0.6
}
For balanced conversation:
{
  "temperature": 0.7,
  "top_p": 0.9,
  "top_k": 50,
  "frequency_penalty": 0.3,
  "presence_penalty": 0.3
}

Context Window Settings

Different models have different context limits:
ModelContext LengthRecommended Use
GPT-4o128k tokensLong conversations
Claude 3.5 Sonnet200k tokensVery long context
Gemini 1.5 Pro1M tokensEntire codebases
GPT-4o mini128k tokensGeneral use
Llama 3.28k-128k tokensVaries by variant
Context management in Airi:
// Automatically managed by chat session store
// Old messages pruned when approaching limit
// System prompt + recent messages prioritized

Voice Configuration

Link a voice to the character:
{
  "speech": {
    "provider": "elevenlabs",
    "model": "eleven_multilingual_v2",
    "voice_id": "rachel",
    "pitch": 1.1,
    "rate": 1.0,
    "language": "en"
  }
}
See Voice Synthesis Configuration for detailed voice options.

Visual Appearance

VRM Models

For 3D avatars:
{
  "vrm": {
    "source": "url",
    "url": "https://example.com/character.vrm"
  }
}
Or use local file:
{
  "vrm": {
    "source": "file",
    "file": "vrm/luna.vrm"
  }
}
VRM Features:
  • Auto blink
  • Auto look-at (follows cursor/camera)
  • Idle eye movement
  • Expression morphs
  • Bone animation support

Live2D Models

For 2D animated avatars:
{
  "live2d": {
    "source": "url",
    "url": "https://example.com/character.model3.json"
  }
}
Live2D Features:
  • Cubism SDK integration
  • Auto blink
  • Auto look-at
  • Idle eye movement
  • Motion support
  • Expression switching

Agent Configuration

Agents extend character capabilities for specific tasks:
{
  "agents": {
    "minecraft": {
      "enabled": true,
      "prompt": "You are playing Minecraft. You can break blocks, place blocks, craft items, and interact with the world. Your goal is to survive and thrive. Think step-by-step about what you need to do next."
    },
    "discord": {
      "enabled": true,
      "prompt": "You are chatting in a Discord server. Respond naturally to conversations, answer questions, and engage with the community. Keep responses concise and friendly."
    },
    "twitter": {
      "enabled": false,
      "prompt": "You are posting on Twitter. Keep tweets under 280 characters. Be engaging and relevant."
    }
  }
}
Each agent has:
  • enabled: Whether to activate the agent
  • prompt: System prompt specific to that agent’s task
Agents are used by integration services (Minecraft, Discord, etc.).

Creating & Managing Characters

Creating a New Character

import { useAiriCardStore } from '@proj-airi/stage-ui'

const store = useAiriCardStore()

const newCard = {
  name: 'Luna',
  version: '1.0.0',
  description: 'An energetic AI researcher...',
  personality: 'Energetic, curious, friendly',
  scenario: 'Chatting in Luna\'s home office',
  systemPrompt: 'You are Luna, an AI researcher...',
  greetings: [
    'Hey there! I\'m Luna. What would you like to chat about?',
    'Hi! Need help with something? I\'m all ears!'
  ],
  
  extensions: {
    airi: {
      modules: {
        consciousness: {
          provider: 'openai',
          model: 'gpt-4o-mini'
        },
        speech: {
          provider: 'elevenlabs',
          model: 'eleven_turbo_v2_5',
          voice_id: 'rachel'
        }
      },
      agents: {}
    }
  }
}

const cardId = store.addCard(newCard)
store.activeCardId = cardId

Updating a Character

store.updateCard('card-id', {
  personality: 'Updated personality traits',
  extensions: {
    airi: {
      modules: {
        consciousness: {
          provider: 'anthropic',
          model: 'claude-3-5-sonnet-20241022'
        }
      }
    }
  }
})

Switching Characters

// Switch active character
store.activeCardId = 'another-card-id'

// Access current character
const currentCard = store.activeCard
console.log(currentCard.name) // "Luna"

Importing/Exporting Characters

Character cards can be saved as JSON:
// Export
const cardData = JSON.stringify(store.getCard('card-id'), null, 2)
const blob = new Blob([cardData], { type: 'application/json' })
const url = URL.createObjectURL(blob)
// Trigger download...

// Import
const importedData = JSON.parse(fileContent)
const newId = store.addCard(importedData)

Character Card V3 Compatibility

Airi supports standard CCV3 format with extensions:
{
  "spec": "chara_card_v3",
  "spec_version": "3.0",
  "data": {
    "name": "Luna",
    "description": "...",
    "personality": "...",
    "scenario": "...",
    "first_mes": "Hey there! I'm Luna.",
    "mes_example": "<START>\n{{user}}: Hi!\n{{char}}: Hello!\n",
    "system_prompt": "...",
    "post_history_instructions": "...",
    "alternate_greetings": [],
    "extensions": {
      "airi": {
        "modules": { ... }
      }
    }
  }
}
When importing CCV3 cards, Airi automatically:
  1. Converts format to internal structure
  2. Creates AIRI extension with defaults
  3. Uses current active providers if not specified

Best Practices

System Prompt Guidelines

Do:
  • Be specific and detailed
  • Include personality traits
  • Define communication style
  • Provide context and background
  • Set clear boundaries
  • Give examples in prompt
Don’t:
  • Be vague or generic
  • Use conflicting traits
  • Make prompt too short
  • Forget to test different scenarios
  • Overload with instructions

Model Selection

Choose based on:
  • Response quality needs: GPT-4o, Claude 3.5 Sonnet for best quality
  • Speed requirements: GPT-4o mini, Groq for fast responses
  • Cost constraints: Local models, GPT-4o mini for economy
  • Privacy needs: Local models (Ollama) for complete privacy
  • Specific capabilities: Claude for long context, Gemini for multimodal

Voice Matching

Match voice characteristics to personality:
  • Energetic character → Higher pitch, faster rate
  • Calm character → Lower pitch, slower rate
  • Professional → Clear, neutral voice
  • Playful → Expressive voice with emotion

Advanced Configuration

Multi-Language Characters

{
  "name": "Yuki",
  "description": "A bilingual character (English/Japanese)",
  "personality": "Friendly, helpful, bilingual",
  "systemPrompt": "You are Yuki. You can speak both English and Japanese fluently. When the user speaks Japanese, respond in Japanese. When they speak English, respond in English.",
  
  "extensions": {
    "airi": {
      "modules": {
        "speech": {
          "provider": "elevenlabs",
          "model": "eleven_multilingual_v2",
          "voice_id": "yuki-japanese",
          "language": "ja"
        }
      }
    }
  }
}

Context-Aware Personalities

Use postHistoryInstructions for dynamic behavior:
# Post-History Instructions

Based on the conversation history:

- If the user seems stressed, be more comforting and supportive
- If discussing technical topics, use more precise language
- If the user is joking, match their playful tone
- Maintain consistency with your established personality
- Remember user preferences mentioned earlier

Specialized Knowledge Characters

{
  "name": "Dr. Code",
  "systemPrompt": "You are Dr. Code, an expert programming tutor with 20 years of experience in software engineering.\n\n## Expertise\n- Python, JavaScript, Rust, Go\n- System design and architecture\n- Algorithm optimization\n- Code review\n\n## Teaching Style\n- Explain concepts clearly\n- Provide code examples\n- Ask follow-up questions\n- Encourage best practices\n- Patient with beginners",
  
  "extensions": {
    "airi": {
      "modules": {
        "consciousness": {
          "provider": "anthropic",
          "model": "claude-3-5-sonnet-20241022"
        }
      }
    }
  }
}

Troubleshooting

Character Not Responding Correctly

Possible causes:
  1. Vague system prompt
  2. Conflicting instructions
  3. Model doesn’t support required features
  4. Context window exceeded
Solutions:
  1. Refine system prompt with specifics
  2. Remove contradictions
  3. Switch to capable model
  4. Clear conversation history

Inconsistent Personality

Causes:
  • Temperature too high
  • Insufficient personality definition
  • Model switching between responses
Solutions:
  • Lower temperature (0.3-0.5)
  • Add more personality examples
  • Use consistent provider/model

Voice Doesn’t Match Personality

Solution: Adjust voice settings:
{
  "speech": {
    "pitch": 1.2,      // Higher for energetic
    "rate": 1.1        // Faster for enthusiastic
  }
}

Code Reference

Character implementation:
  • Character store: packages/stage-ui/src/stores/modules/airi-card.ts
  • Character interface: packages/stage-ui/src/stores/character/index.ts
  • Database: packages/stage-ui/src/database/repos/characters.repo.ts
  • CCV3 support: packages/ccc (Character Card Codec)

Providers

Configure AI providers

Voice Synthesis

Configure character voice

Memory

Configure conversation memory

Build docs developers (and LLMs) love