# Message Types

The API sends different message types during streaming to provide rich context.

## AI Content

The main response text from the AI comes in the standard OpenAI format:

```json
{
  "choices": [{
    "delta": {
      "content": "text chunk"
    }
  }]
}
```

**How to handle it:**

```python
for chunk in stream:
    # Check for AI content
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
```

```javascript
for await (const chunk of stream) {
  // Check for AI content
  if (chunk.choices[0]?.delta?.content) {
    process.stdout.write(chunk.choices[0].delta.content);
  }
}
```

## Step Messages

Shows what the AI is doing in real-time (e.g., "Planning", "Searching documents", "Analyzing results"):

```json
{
  "custom_data": {
    "type": "step_message",
    "title": "Searching IRC Code",
    "status": "in_progress"
  }
}
```

**How to handle it:**

```python
if hasattr(chunk, 'custom_data'):
    if chunk.custom_data.get('type') == 'step_message':
        title = chunk.custom_data.get('title')
        print(f"\nStep: {title}")
```

```javascript
if (chunk.custom_data?.type === 'step_message') {
  const title = chunk.custom_data.title;
  console.log(`\nStep: ${title}`);
}
```

**Status values:**
- `in_progress` - Currently running
- `completed` - Finished successfully
- `failed` - Encountered an error

## Source Messages

Shows which documents were referenced to generate the answer. This helps verify the answer's accuracy:

```json
{
  "custom_data": {
    "type": "source_message",
    "content": [
      {
        "node_id": "source_123",
        "text": "Section 179 allows businesses...",
        "metadata": {
          "file_name": "IRC_Code.pdf",
          "page": 42
        },
        "score": 0.95
      }
    ]
  }
}
```

**How to handle it:**

```python
if chunk.custom_data.get('type') == 'source_message':
    sources = chunk.custom_data.get('content', [])
    print(f"\nFound {len(sources)} sources:")
    for source in sources:
        file_name = source.get('metadata', {}).get('file_name', 'Unknown')
        page = source.get('metadata', {}).get('page', 'N/A')
        print(f"  {file_name} (page {page})")
```

```javascript
if (chunk.custom_data?.type === 'source_message') {
  const sources = chunk.custom_data.content || [];
  console.log(`\nFound ${sources.length} sources:`);
  sources.forEach(source => {
    const fileName = source.metadata?.file_name || 'Unknown';
    const page = source.metadata?.page || 'N/A';
    console.log(`  ${fileName} (page ${page})`);
  });
}
```

:::tip Advanced Usage
For detailed information on how to use **Page Labels** for navigation and **Source Origin** links, see the [Page Labels and Source Origin](./coordinates-and-origins) guide.
:::

## Suggestions

Follow-up questions that users might want to ask based on the current conversation:

```json
{
  "custom_data": {
    "type": "suggestions",
    "suggestions": [
      "What are the dollar limits for section 179?",
      "What types of property qualify for section 179?",
      "How does section 179 differ from bonus depreciation?"
    ]
  }
}
```

**How to handle it:**

```python
if chunk.custom_data.get('type') == 'suggestions':
    suggestions = chunk.custom_data.get('suggestions', [])
    print(f"\nSuggested questions:")
    for i, suggestion in enumerate(suggestions, 1):
        print(f"  {i}. {suggestion}")
```

```javascript
if (chunk.custom_data?.type === 'suggestions') {
  const suggestions = chunk.custom_data.suggestions || [];
  console.log(`\nSuggested questions:`);
  suggestions.forEach((suggestion, i) => {
    console.log(`  ${i + 1}. ${suggestion}`);
  });
}
```

## Human Message

Echo of the user's question:

```json
{
  "type": "human_message",
  "content": "What is section 169?"
}
```

## AI Metadata

Additional information about the response:

```json
{
  "type": "ai_metadata",
  "metadata": {
    "model": "bizora-1.0",
    "tokens_used": 150,
    "processing_time_ms": 1250
  }
}
```

## Complete Example

Here's a complete example that handles all message types:

```python
# Enable streaming for complete message handling
stream = client.chat.completions.create(
    model="bizora-1.0",
    messages=[{"role": "human", "content": "What is section 179?"}],
    stream=True
)

for chunk in stream:
    # AI content - the actual answer
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
    
    # Custom messages - steps, sources, suggestions
    elif hasattr(chunk, 'custom_data'):
        msg_type = chunk.custom_data.get('type')
        
        if msg_type == 'step_message':
            print(f"\nStep: {chunk.custom_data.get('title')}")
        
        elif msg_type == 'source_message':
            sources = chunk.custom_data.get('content', [])
            print(f"\nFound {len(sources)} sources")
        
        elif msg_type == 'suggestions':
            suggestions = chunk.custom_data.get('suggestions', [])
            print(f"\n{len(suggestions)} suggested questions")
```

```javascript
// Enable streaming for complete message handling
const stream = await client.chat.completions.create({
  model: 'bizora-1.0',
  messages: [{ role: 'human', content: 'What is section 179?' }],
  stream: true
});

for await (const chunk of stream) {
  // AI content - the actual answer
  if (chunk.choices[0]?.delta?.content) {
    process.stdout.write(chunk.choices[0].delta.content);
  }
  
  // Custom messages - steps, sources, suggestions
  else if (chunk.custom_data) {
    const { type } = chunk.custom_data;
    
    if (type === 'step_message') {
      console.log(`\nStep: ${chunk.custom_data.title}`);
    }
    else if (type === 'source_message') {
      const sources = chunk.custom_data.content || [];
      console.log(`\nFound ${sources.length} sources`);
    }
    else if (type === 'suggestions') {
      const suggestions = chunk.custom_data.suggestions || [];
      console.log(`\n${suggestions.length} suggested questions`);
    }
  }
}
```

### Deep Research Mode

Here's a complete example that handles all message types with deep research:

```python
# Enable streaming with deep research
stream = client.chat.completions.create(
    model="bizora-1.0",
    messages=[{"role": "human", "content": "Analyze the tax treatment of cryptocurrency staking rewards and airdrops."}],
    stream=True,
    extra_body={"askMode": "tax_research_deep_research"}
)

for chunk in stream:
    # AI content - the actual answer
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
    
    # Custom messages - steps, sources, suggestions
    elif hasattr(chunk, 'custom_data'):
        msg_type = chunk.custom_data.get('type')
        
        if msg_type == 'step_message':
            print(f"\nStep: {chunk.custom_data.get('title')}")
        
        elif msg_type == 'source_message':
            sources = chunk.custom_data.get('content', [])
            print(f"\nFound {len(sources)} sources")
        
        elif msg_type == 'suggestions':
            suggestions = chunk.custom_data.get('suggestions', [])
            print(f"\n{len(suggestions)} suggested questions")
```

```javascript
// Enable streaming with deep research
const stream = await client.chat.completions.create({
  model: 'bizora-1.0',
  messages: [{ role: 'human', content: 'Analyze the tax treatment of cryptocurrency staking rewards and airdrops.' }],
  stream: true,
  askMode: 'tax_research_deep_research'
});

for await (const chunk of stream) {
  // AI content - the actual answer
  if (chunk.choices[0]?.delta?.content) {
    process.stdout.write(chunk.choices[0].delta.content);
  }
  
  // Custom messages - steps, sources, suggestions
  else if (chunk.custom_data) {
    const { type } = chunk.custom_data;
    
    if (type === 'step_message') {
      console.log(`\nStep: ${chunk.custom_data.title}`);
    }
    else if (type === 'source_message') {
      const sources = chunk.custom_data.content || [];
      console.log(`\nFound ${sources.length} sources`);
    }
    else if (type === 'suggestions') {
      const suggestions = chunk.custom_data.suggestions || [];
      console.log(`\n${suggestions.length} suggested questions`);
    }
  }
}
```

### Audit Research Mode

Here's a complete example that handles all message types with audit research:

```python
# Enable streaming with audit research
stream = client.chat.completions.create(
    model="bizora-1.0",
    messages=[{"role": "human", "content": "Analyze the reporting requirements for lease modifications under ASC 842."}],
    stream=True,
    extra_body={"askMode": "audit_research"}
)

for chunk in stream:
    # AI content - the actual answer
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
    
    # Custom messages - steps, sources, suggestions
    elif hasattr(chunk, 'custom_data'):
        msg_type = chunk.custom_data.get('type')
        
        if msg_type == 'step_message':
            print(f"\nStep: {chunk.custom_data.get('title')}")
        
        elif msg_type == 'source_message':
            sources = chunk.custom_data.get('content', [])
            print(f"\nFound {len(sources)} sources")
        
        elif msg_type == 'suggestions':
            suggestions = chunk.custom_data.get('suggestions', [])
            print(f"\n{len(suggestions)} suggested questions")
```

```javascript
// Enable streaming with audit research
const stream = await client.chat.completions.create({
  model: 'bizora-1.0',
  messages: [{ role: 'human', content: 'Analyze the reporting requirements for lease modifications under ASC 842.' }],
  stream: true,
  askMode: 'audit_research'
});

for await (const chunk of stream) {
  // AI content - the actual answer
  if (chunk.choices[0]?.delta?.content) {
    process.stdout.write(chunk.choices[0].delta.content);
  }
  
  // Custom messages - steps, sources, suggestions
  else if (chunk.custom_data) {
    const { type } = chunk.custom_data;
    
    if (type === 'step_message') {
      console.log(`\nStep: ${chunk.custom_data.title}`);
    }
    else if (type === 'source_message') {
      const sources = chunk.custom_data.content || [];
      console.log(`\nFound ${sources.length} sources`);
    }
    else if (type === 'suggestions') {
      const suggestions = chunk.custom_data.suggestions || [];
      console.log(`\n${suggestions.length} suggested questions`);
    }
  }
}
```
