Skip to content

Messages

Throughout the code you’ll be working with the Message interface. We create Message objects when a user or LLM sends a message.

Every message has at least these core properties:

  • created: Timestamp when the message was created
  • role: Either “user” or “assistant”
  • content: The text content of the message
  • level: (optional) A number indicating which level this message was created in
  • input: The original prompt that triggered this response (only for assistant messages)

For complete type definitions, check the ./web/src/lib/messages.js file.

┌─────────────┐ ┌───────────────┐ ┌─────────────────┐
│ User Input │────▶│ ask() Function│────▶│ AI API (Claude) │
└─────────────┘ └───────────────┘ └─────────────────┘
│ │
│ │
▼ ▼
┌─────────────┐ ┌───────────────┐ ┌─────────────────┐
│ UI Display │◀────│ Memory System │◀────│ Message Object │
└─────────────┘ └───────────────┘ └─────────────────┘
│ (optional delay)
┌─────────────────┐
│ Pending Queue │
│ (deliverAt) │
└─────────────────┘

When possible, AI responses are parsed into structured data in the contentJson property, which can include whatever the prompt requested. The structure is flexible and determined by the system prompt instructions given to the AI. Common examples include:

  • reply: The main response text
  • innerMonologue: The AI’s thought process (visible when showThoughts is enabled)
  • mood: Emotional state indicator (e.g., “happy”, “confused”, “surprised”)

For example, a response might contain:

contentJson: {
reply: "I found the hidden key!",
innerMonologue: "The user asked where the key is. Based on the game context, it's under the red carpet.",
mood: "excited"
}

The primary flow for AI text generation:

  • <MessageForm> component → /?/ask form action → ask() function
  • Alternative: Direct API calls to /api/chat (used in some levels)

Both routes through the core ask() function in /lib/server/ask.js.

For delayed message delivery (humanization), use memory.scheduleMessage():

// Immediate delivery (delay = 0)
memory.scheduleMessage(message, 0)
// Delayed delivery (5 seconds)
memory.scheduleMessage(message, 5000)
// System messages with delay
memory.scheduleMessage(systemMessage, 3000, 'systemMessages')

The pending queue automatically processes messages when their deliverAt time is reached, ensuring delivery survives page navigation and refresh.

The core function powering message generation accepts these parameters:

ask(userPrompt, systemPrompt, messageContext, settings, level, traceType)
  • userPrompt: The user’s input text
  • systemPrompt: An optional system prompt to guide the AI
  • messageContext: An optional list of previous Message objects (conversation history)
  • settings: Configuration options for the AI including model selection
  • level: The level number (optional)
  • traceType: Type of trace to be added to the message (optional)

By default, AI messages are NOT given any context or knowledge. You must provide:

  • systemPrompt: Character instructions (e.g., from promptSystemChat() or promptHumanChat())
  • messageContext: Previous conversation history

Behind the scenes, the ask() function performs these operations:

  1. Message Formatting: Messages are transformed to be compatible with the Anthropic API format, which requires:

    • Messages must alternate between ‘user’ and ‘assistant’ roles
    • The first message must be from a ‘user’
    • Empty messages are filtered out
  2. API Interaction: The function makes a request to Claude with the formatted messages.

  3. Response Processing:

    • It extracts the text content from the API response
    • It attempts to parse JSON from the response into contentJson
    • It calculates usage statistics and costs
  4. Storage: The resulting message is returned and stored in:

    • memory.messages: Human NPC conversations (context: ‘human’)
    • memory.systemMessages: System NPC conversations (context: ‘system’)
    • memory.pendingMessages: Messages scheduled for delayed delivery (automatically processed into the above arrays when their deliverAt time is reached)

For complete type definitions, check the ./web/src/lib/messages.js file.