---
title: Agent Chat Panel
description: Real-time chat interface for AI agents with streaming responses
sidebar_position: 12
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import Admonition from '@theme/Admonition';

# Agent Chat Panel

## Overview

The Agent Chat Panel provides a real-time interface for interacting with AI agents. It uses Socket.IO for reliable bidirectional communication and supports streaming responses from agents.

<Admonition type="success" title="Key Features">
- **Real-time streaming**: See agent responses as they're generated
- **Socket.IO reliability**: Automatic reconnection and state management
- **Multiple agent types**: Support for RAG, Document, and Task agents
- **Session persistence**: Chat history maintained across connections
- **Simple architecture**: Socket.IO ↔ Server ↔ SSE ↔ Agents
</Admonition>

## Architecture

```mermaid
graph LR
    UI[React UI] <--> |Socket.IO| Server[FastAPI Server]
    Server --> |HTTP/SSE| Agents[PydanticAI Agents]
    Agents --> |SSE Stream| Server
    Server --> |Socket.IO Events| UI
```

### Communication Flow

1. **UI to Server**: Socket.IO events and REST endpoints
2. **Server to Agents**: HTTP requests with SSE streaming responses
3. **Agents to Server**: Server-Sent Events (SSE) for streaming
4. **Server to UI**: Socket.IO events for real-time updates

## Frontend Usage

<Tabs>
<TabItem value="component" label="React Component">

```tsx
import { ArchonChatPanel } from '@/components/layouts/ArchonChatPanel';

function App() {
  return (
    <div className="flex h-screen">
      {/* Your main content */}
      <div className="flex-1">
        {/* ... */}
      </div>
      
      {/* Chat Panel */}
      <ArchonChatPanel />
    </div>
  );
}
```

</TabItem>
<TabItem value="service" label="Service Usage">

```typescript
import { agentChatService } from '@/services/agentChatService';

// Create a chat session
const { session_id } = await agentChatService.createSession(
  undefined,  // project_id (optional)
  'rag'       // agent_type: 'rag' | 'document' | 'task'
);

// Connect WebSocket for real-time updates
await agentChatService.connectWebSocket(
  session_id,
  (message) => {
    // Handle incoming messages
    console.log('Agent:', message.content);
  },
  (isTyping) => {
    // Handle typing indicator
    console.log('Agent is typing:', isTyping);
  },
  (chunk) => {
    // Handle streaming chunks
    console.log('Chunk:', chunk);
  },
  () => {
    // Handle stream completion
    console.log('Stream complete');
  }
);

// Send a message
await agentChatService.sendMessage(
  session_id,
  'What is Archon?',
  { match_count: 5 }  // Optional context
);
```

</TabItem>
</Tabs>

## Backend Implementation

### Socket.IO Events

The chat system uses Socket.IO events with room-based isolation:

<Tabs>
<TabItem value="events" label="Event Handlers">

```python
from ..socketio_app import get_socketio_instance
sio = get_socketio_instance()

@sio.event
async def join_chat(sid, data):
    """Join a chat room."""
    session_id = data.get('session_id')
    await sio.enter_room(sid, f'chat_{session_id}')

@sio.event
async def chat_message(sid, data):
    """Handle incoming chat messages."""
    session_id = data.get('session_id')
    message = data.get('message')
    context = data.get('context', {})
    
    # Process with agent
    await process_agent_response(session_id, message, context)
```

</TabItem>
<TabItem value="streaming" label="SSE Proxy">

```python
async def process_agent_response(session_id: str, message: str, context: dict):
    """Stream agent response via SSE and emit to Socket.IO."""
    room = f'chat_{session_id}'
    
    # Call agents service with SSE streaming
    async with httpx.AsyncClient() as client:
        async with client.stream(
            "POST",
            f"http://archon-agents:8052/agents/rag/stream",
            json={
                "prompt": message,
                "context": context
            }
        ) as response:
            # Stream SSE chunks to Socket.IO
            async for line in response.aiter_lines():
                if line.startswith("data: "):
                    chunk_data = json.loads(line[6:])
                    
                    # Emit streaming chunk
                    await sio.emit('stream_chunk', {
                        "type": "stream_chunk",
                        "content": chunk_data.get('content', '')
                    }, room=room)
```

</TabItem>
</Tabs>

### REST Endpoints

Minimal REST endpoints for session management:

| Endpoint | Method | Purpose |
|----------|--------|---------|
| `/api/agent-chat/sessions` | POST | Create chat session |
| `/api/agent-chat/sessions/{id}` | GET | Get session info |
| `/api/agent-chat/sessions/{id}/messages` | POST | Send message (triggers Socket.IO) |

## Agent Types

### RAG Agent
- **Purpose**: Knowledge base Q&A with context retrieval
- **Context**: `{ match_count: 5, source_filter: "docs.archon.com" }`
- **Best for**: Documentation queries, technical questions

### Document Agent
- **Purpose**: Document analysis and content generation
- **Context**: `{ format: "markdown", style: "technical" }`
- **Best for**: Creating documentation, analyzing documents

### Task Agent
- **Purpose**: Task decomposition and project planning
- **Context**: `{ project_id: "uuid", detail_level: "high" }`
- **Best for**: Breaking down features, planning implementation

## Socket.IO Message Types

### Client to Server

| Event | Purpose | Data |
|-------|---------|------|
| `join_chat` | Join chat room | `{session_id: string}` |
| `chat_message` | Send message | `{session_id, message, context}` |
| `leave_chat` | Leave room | `{session_id: string}` |

### Server to Client

| Event | Purpose | Data |
|-------|---------|------|
| `connection_confirmed` | Confirm connection | `{session_id: string}` |
| `message` | Complete message | `{type: "message", data: ChatMessage}` |
| `stream_chunk` | Streaming chunk | `{type: "stream_chunk", content: string}` |
| `stream_complete` | Stream finished | `{type: "stream_complete"}` |
| `typing` | Typing indicator | `{type: "typing", is_typing: boolean}` |
| `error` | Error occurred | `{type: "error", error: string}` |

## Error Handling

<Admonition type="warning" title="Connection Management">
The chat service handles various connection scenarios:

- **Automatic reconnection**: Socket.IO reconnects with exponential backoff
- **Session recovery**: Creates new session if old one is invalid
- **Error propagation**: Errors from agents are forwarded to UI
- **Graceful degradation**: Shows offline state when server unavailable
</Admonition>

### Common Error Scenarios

1. **Agent Service Unavailable**
   ```json
   {
     "type": "error",
     "error": "Agent service error: 503"
   }
   ```

2. **Invalid Session**
   - Automatically creates new session
   - Transfers handlers to new session
   - Notifies UI of session change

3. **Network Disconnection**
   - Socket.IO handles reconnection
   - UI shows "connecting" state
   - Messages queued until reconnected

## Best Practices

<Tabs>
<TabItem value="frontend" label="Frontend">

1. **Handle connection states**
   ```typescript
   agentChatService.onStatusChange(sessionId, (status) => {
     switch(status) {
       case 'online': showOnlineIndicator(); break;
       case 'offline': showOfflineMessage(); break;
       case 'connecting': showLoadingSpinner(); break;
     }
   });
   ```

2. **Clean up on unmount**
   ```typescript
   useEffect(() => {
     return () => {
       agentChatService.disconnectWebSocket(sessionId);
       agentChatService.offStatusChange(sessionId);
     };
   }, [sessionId]);
   ```

3. **Handle streaming properly**
   ```typescript
   let accumulatedContent = '';
   
   const onStreamChunk = (chunk: string) => {
     accumulatedContent += chunk;
     updateDisplay(accumulatedContent);
   };
   ```

</TabItem>
<TabItem value="backend" label="Backend">

1. **Use rooms for isolation**
   ```python
   # Always use room pattern
   room = f'chat_{session_id}'
   await sio.emit('message', data, room=room)
   ```

2. **Handle SSE errors gracefully**
   ```python
   try:
     async for line in response.aiter_lines():
       # Process line
   except httpx.ReadTimeout:
     await sio.emit('error', {
       'error': 'Agent response timeout'
     }, room=room)
   ```

3. **Clean up sessions periodically**
   ```python
   # Remove old sessions after 24 hours
   for session_id, session in list(sessions.items()):
     if is_expired(session['created_at']):
       sessions.pop(session_id, None)
   ```

</TabItem>
</Tabs>

## Configuration

### Environment Variables

```bash
# Agent service configuration
AGENT_SERVICE_URL=http://archon-agents:8052

# Socket.IO configuration
SOCKETIO_PING_TIMEOUT=60
SOCKETIO_PING_INTERVAL=25

# Session configuration
SESSION_TTL_HOURS=24
MAX_MESSAGES_PER_SESSION=1000
```

### Frontend Configuration

```typescript
// Adjust WebSocket settings
const wsConfig = {
  maxReconnectAttempts: 5,
  reconnectInterval: 1000,
  heartbeatInterval: 30000,
  enableAutoReconnect: true,
  enableHeartbeat: true,
};
```

## Testing

### Manual Testing
1. Open the UI and verify chat panel appears
2. Check connection status indicator
3. Send a test message
4. Verify streaming response appears
5. Test reconnection by restarting server

### Integration Testing
```python
# Test Socket.IO events
async def test_chat_flow():
    # Create session
    response = await client.post("/api/agent-chat/sessions")
    session_id = response.json()["session_id"]
    
    # Connect Socket.IO
    sio_client = socketio.AsyncClient()
    await sio_client.connect("http://localhost:8080")
    
    # Join room
    await sio_client.emit("join_chat", {"session_id": session_id})
    
    # Send message
    await sio_client.emit("chat_message", {
        "session_id": session_id,
        "message": "Hello",
        "context": {}
    })
    
    # Verify response
    # ...
```

## Troubleshooting

<Admonition type="tip" title="Common Issues">

**Chat shows "offline"**
- Check if agents container is running: `docker ps | grep agents`
- Verify server logs: `docker logs archon-server`
- Check Socket.IO connection in browser DevTools

**Messages not streaming**
- Verify SSE endpoint is accessible
- Check agent logs for errors
- Ensure proper CORS configuration

**Session errors**
- Sessions are in-memory and lost on server restart
- Frontend will create new session automatically
- Check session_id in requests matches server state

</Admonition>

## Summary

The Agent Chat Panel provides a robust, real-time interface for AI agent interaction with:
- Socket.IO for reliable bidirectional communication
- SSE streaming for agent responses
- Simple session management
- Automatic error recovery
- Clean room-based isolation

Total implementation: ~250 lines of elegant, maintainable code.