> ## Documentation Index
> Fetch the complete documentation index at: https://docs.elizaos.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Message Processing Flow

> Step-by-step breakdown of how messages flow through the bootstrap plugin system

# Message Processing Flow - Detailed Breakdown

This document provides a step-by-step breakdown of how messages flow through the plugin-bootstrap system.

## Complete Message Flow Diagram

```mermaid theme={null}
flowchart TD
    Start([Message Received]) --> A[Event: MESSAGE_RECEIVED]

    A --> B{Is from Self?}
    B -->|Yes| End1[Skip Processing]
    B -->|No| C[Generate Response ID]

    C --> D[Start Run Tracking]
    D --> E[Save to Memory & Embeddings]

    E --> F{Has Attachments?}
    F -->|Yes| G[Process Attachments]
    F -->|No| H[Check Agent State]
    G --> H

    H --> I{Is Agent Muted?}
    I -->|Yes & No Name Mention| End2[Ignore Message]
    I -->|No or Name Mentioned| J[Compose Initial State]

    J --> K{Should Bypass<br/>shouldRespond?}
    K -->|Yes| L[Skip to Response]
    K -->|No| M[Evaluate shouldRespond]

    M --> N[Generate shouldRespond Prompt]
    N --> O[LLM Decision]
    O --> P{Should Respond?}

    P -->|No| Q[Save Ignore Decision]
    Q --> End3[End Processing]

    P -->|Yes| L
    L --> R[Compose Full State]
    R --> S[Generate Response Prompt]
    S --> T[LLM Response Generation]

    T --> U{Valid Response?}
    U -->|No| V[Retry up to 3x]
    V --> T
    U -->|Yes| W[Parse XML Response]

    W --> X{Still Latest Response?}
    X -->|No| End4[Discard Response]
    X -->|Yes| Y[Create Response Message]

    Y --> Z{Is Simple Response?}
    Z -->|Yes| AA[Direct Callback]
    Z -->|No| AB[Process Actions]

    AA --> AC[Run Evaluators]
    AB --> AC

    AC --> AD[Reflection Evaluator]
    AD --> AE[Extract Facts]
    AE --> AF[Update Relationships]
    AF --> AG[Save Reflection State]

    AG --> AH[Emit RUN_ENDED]
    AH --> End5[Complete]
```

## Detailed Step Descriptions

### 1. Initial Message Reception

```typescript theme={null}
// Event triggered by platform (Discord, Telegram, etc.)
EventType.MESSAGE_RECEIVED → messageReceivedHandler
```

### 2. Self-Check

```typescript theme={null}
if (message.entityId === runtime.agentId) {
  logger.debug('Skipping message from self');
  return;
}
```

### 3. Response ID Generation

```typescript theme={null}
// Prevents duplicate responses for rapid messages
const responseId = v4();
latestResponseIds.get(runtime.agentId).set(message.roomId, responseId);
```

### 4. Run Tracking

```typescript theme={null}
const runId = runtime.startRun();
await runtime.emitEvent(EventType.RUN_STARTED, {...});
```

### 5. Memory Storage

```typescript theme={null}
await Promise.all([
  runtime.addEmbeddingToMemory(message), // Vector embeddings
  runtime.createMemory(message, 'messages'), // Message history
]);
```

### 6. Attachment Processing

```typescript theme={null}
if (message.content.attachments?.length > 0) {
  // Images: Generate descriptions
  // Documents: Extract text
  // Other: Process as configured
  message.content.attachments = await processAttachments(message.content.attachments, runtime);
}
```

### 7. Agent State Check

```typescript theme={null}
const agentUserState = await runtime.getParticipantUserState(message.roomId, runtime.agentId);

if (
  agentUserState === 'MUTED' &&
  !message.content.text?.toLowerCase().includes(runtime.character.name.toLowerCase())
) {
  return; // Ignore if muted and not mentioned
}
```

### 8. Should Respond Evaluation

#### Bypass Conditions

```typescript theme={null}
function shouldBypassShouldRespond(runtime, room, source) {
  // Default bypass types
  const bypassTypes = [ChannelType.DM, ChannelType.VOICE_DM, ChannelType.SELF, ChannelType.API];

  // Default bypass sources
  const bypassSources = ['client_chat'];

  // Plus any configured in environment
  return bypassTypes.includes(room.type) || bypassSources.includes(source);
}
```

#### LLM Evaluation

```typescript theme={null}
if (!shouldBypassShouldRespond) {
  const state = await runtime.composeState(message, [
    'ANXIETY',
    'SHOULD_RESPOND',
    'ENTITIES',
    'CHARACTER',
    'RECENT_MESSAGES',
    'ACTIONS',
  ]);

  const prompt = composePromptFromState({
    state,
    template: shouldRespondTemplate,
  });

  const response = await runtime.useModel(ModelType.TEXT_SMALL, { prompt });
  const parsed = parseKeyValueXml(response);

  shouldRespond = parsed?.action && !['IGNORE', 'NONE'].includes(parsed.action.toUpperCase());
}
```

### 9. Response Generation

#### State Composition with Providers

```typescript theme={null}
state = await runtime.composeState(message, ['ACTIONS']);

// Each provider adds context:
// - RECENT_MESSAGES: Conversation history
// - CHARACTER: Personality traits
// - ENTITIES: User information
// - TIME: Temporal context
// - RELATIONSHIPS: Social connections
// - WORLD: Environment details
// - etc.
```

#### LLM Response

```typescript theme={null}
const prompt = composePromptFromState({
  state,
  template: messageHandlerTemplate,
});

let response = await runtime.useModel(ModelType.TEXT_LARGE, { prompt });

// Expected XML format:
/*
<thought>Agent's internal reasoning</thought>
<actions>REPLY,FOLLOW_ROOM</actions>
<providers>TECHNICAL_DOCS,FAQ</providers>
<text>The actual response text</text>
<simple>false</simple>
*/
```

### 10. Response Validation

```typescript theme={null}
// Retry logic for missing fields
while (retries < 3 && (!responseContent?.thought || !responseContent?.actions)) {
  // Regenerate response
  retries++;
}

// Check if still the latest response
if (latestResponseIds.get(runtime.agentId).get(message.roomId) !== responseId) {
  return; // Newer message is being processed
}
```

### 11. Action Processing

#### Simple Response

```typescript theme={null}
// Simple = REPLY action only, no providers
if (responseContent.simple && responseContent.text) {
  await callback(responseContent);
}
```

#### Complex Response

```typescript theme={null}
// Multiple actions or providers
await runtime.processActions(message, responseMessages, state, callback);
```

### 12. Evaluator Execution

#### Reflection Evaluator

```typescript theme={null}
// Runs after response generation
await runtime.evaluate(message, state, shouldRespond, callback, responseMessages);

// Reflection evaluator:
// 1. Analyzes conversation quality
// 2. Extracts new facts
// 3. Updates relationships
// 4. Self-reflects on performance
```

## Key Decision Points

### 1. Should Respond Decision Tree

```text theme={null}
Is DM? → YES → Respond
Is Voice DM? → YES → Respond
Is API Call? → YES → Respond
Is Muted + Name Mentioned? → YES → Respond
Is Muted? → NO → Ignore
Run shouldRespond LLM →
  - Action = REPLY/etc → Respond
  - Action = IGNORE/NONE → Ignore
```

### 2. Response Type Decision

```text theme={null}
Actions = [REPLY] only AND Providers = [] → Simple Response
Otherwise → Complex Response with Action Processing
```

### 3. Evaluator Trigger Conditions

```text theme={null}
Message Count > ConversationLength / 4 → Run Reflection
New Interaction → Update Relationships
Facts Mentioned → Extract and Store
```

## Performance Optimizations

### 1. Response ID Tracking

* Prevents duplicate responses when multiple messages arrive quickly
* Only processes the latest message per room

### 2. Parallel Operations

```typescript theme={null}
// Parallel memory operations
await Promise.all([
  runtime.addEmbeddingToMemory(message),
  runtime.createMemory(message, 'messages')
]);

// Parallel data fetching in providers
const [entities, room, messages, interactions] = await Promise.all([
  getEntityDetails({ runtime, roomId }),
  runtime.getRoom(roomId),
  runtime.getMemories({ tableName: 'messages', roomId }),
  getRecentInteractions(...)
]);
```

### 3. Timeout Protection

```typescript theme={null}
const timeoutDuration = 60 * 60 * 1000; // 1 hour
await Promise.race([processingPromise, timeoutPromise]);
```

## Error Handling

### 1. Run Lifecycle Events

```typescript theme={null}
try {
  // Process message
  await runtime.emitEvent(EventType.RUN_ENDED, { status: 'completed' });
} catch (error) {
  await runtime.emitEvent(EventType.RUN_ENDED, {
    status: 'error',
    error: error.message,
  });
}
```

### 2. Graceful Degradation

* Missing attachments → Continue without them
* Provider errors → Use default values
* LLM failures → Retry with backoff
* Database errors → Log and continue

## Platform-Specific Handling

### Discord

* Channels → Rooms with ChannelType
* Servers → Worlds
* Users → Entities

### Telegram

* Chats → Rooms
* Groups → Worlds
* Users → Entities

### Message Bus

* Topics → Rooms
* Namespaces → Worlds
* Publishers → Entities

## Summary

The message flow through plugin-bootstrap is designed to be:

1. **Platform-agnostic** - Works with any message source
2. **Intelligent** - Makes context-aware response decisions
3. **Extensible** - Supports custom actions, providers, evaluators
4. **Resilient** - Handles errors gracefully
5. **Performant** - Uses parallel operations and caching

This flow ensures that every message is processed consistently, responses are contextual and appropriate, and the agent learns from each interaction.

## Template Usage in Message Flow

Understanding where templates are used helps you customize the right parts of the flow:

### 1. **shouldRespondTemplate** - Decision Point

Used at step 8 in the flow when evaluating whether to respond:

```
Message Received → shouldRespondTemplate → RESPOND/IGNORE/STOP
```

This template controls:

* When your agent engages in conversations
* What triggers a response
* When to stay silent

### 2. **messageHandlerTemplate** - Response Generation

Used at step 9 when generating the actual response:

```
Decision to Respond → messageHandlerTemplate → Response + Actions
```

This template controls:

* How responses are formulated
* Which actions are selected
* The agent's personality and tone
* Which providers to use for context

### 3. **reflectionTemplate** - Post-Interaction Analysis

Used at step 12 during evaluator execution:

```
Response Sent → reflectionTemplate → Learning & Memory Updates
```

This template controls:

* What the agent learns from interactions
* How facts are extracted
* Relationship tracking logic
* Self-improvement mechanisms

### 4. **postCreationTemplate** - Social Media Posts

Used when POST\_GENERATED event is triggered:

```
Post Request → postCreationTemplate → Social Media Content
```

This template controls:

* Post style and tone
* Content generation approach
* Image prompt generation

### Template Processing Pipeline

```mermaid theme={null}
graph TD
    A[Raw Template] --> B[Variable Injection]
    B --> C[Provider Data Integration]
    C --> D[Final Prompt Assembly]
    D --> E[LLM Processing]
    E --> F[Response Parsing]
    F --> G[Action Execution/Callback]
```

1. **Template Selection**: System picks the appropriate template
2. **Variable Replacement**: `{{agentName}}`, `{{providers}}`, etc. are replaced
3. **Provider Injection**: Provider data is formatted and inserted
4. **Prompt Assembly**: Complete prompt is constructed
5. **LLM Processing**: Sent to language model
6. **Response Parsing**: XML/JSON response is parsed
7. **Execution**: Actions are executed, callbacks are called

### Customization Impact

When you customize templates, you're modifying these key decision points:

* **shouldRespond**: Change engagement patterns
* **messageHandler**: Alter personality and response style
* **reflection**: Modify learning and memory formation
* **postCreation**: Adjust social media presence

Each template change cascades through the entire interaction flow, allowing deep customization of agent behavior while maintaining the robust message processing infrastructure.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.