type: task id: MCP_ANALYST_AGENT-CHAT_CONVERSATION_PERSISTENCE_AND_HISTORY title: Chat Conversation Persistence and History description: Add ChatSession and ChatMessage Django models so chat conversations survive page refreshes. Show recent conversations in a sidebar. Allow resuming previous conversations. Required for the chat-first home page to be useful beyond one-shot questions. milestone: m2-internal-adoption-design-partners owner: data-ai-engineer-architect status: completed priority: p2 initiative: ai-agent-surfaces completed_at: '2026-03-18T02:15:30-07:00' completed_by: dave
The chat-first home page has no memory. When a user refreshes the page or comes back later, their conversation is gone. For the chat to be a real working interface (not a toy demo), conversations must persist.
Without persistence: - Users lose context mid-analysis ("I was looking at revenue by region, now it's gone") - No way to resume a multi-step exploration across sessions - No history to reference or share - The AI loses conversation context on every page load
Existing patterns in the Cloud app:
- Django ORM models in apps/cloud/apps/ — standard model/migration pattern
- User→Organization→Project hierarchy already exists
- DashboardSnapshot model shows the pattern for storing rendered artifacts
Conversation state needed: - Session metadata (org, user, title, timestamps) - Messages (role, content, tool calls, tool results, rendered artifacts) - The YAML content produced by tool calls (for dashboard embeds that can be saved later)
Standard Django ORM. ChatSession belongs to an org+user. ChatMessage stores each message with role, content, and optional structured data (tool calls, rendered dashboards).
Trade-offs: Simple, consistent with existing patterns. Easy to query for history. Adds DB rows per message but conversations are not high-volume.
Store conversations in the session backend rather than the database.
Trade-offs: Simpler schema. But sessions expire, can't be shared, can't be queried server-side for suggestions.
Files to create:
- apps/cloud/apps/chat/models.py — ChatSession, ChatMessage models
- apps/cloud/apps/chat/migrations/ — initial migration
Models:
class ChatSession(models.Model):
organization = models.ForeignKey(Organization)
user = models.ForeignKey(User)
title = models.CharField(max_length=200, blank=True) # auto-generated from first message
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class ChatMessage(models.Model):
session = models.ForeignKey(ChatSession, related_name="messages")
role = models.CharField(choices=[("user", "User"), ("assistant", "Assistant"), ("system", "System")])
content = models.TextField()
tool_calls = models.JSONField(null=True) # structured tool call data
rendered_artifacts = models.JSONField(null=True) # dashboard SVGs, render IDs
created_at = models.DateTimeField(auto_now_add=True)
Steps:
1. Create models + migration
2. Update chat SSE endpoint to save messages as they stream
3. Add GET /org/<slug>/chat/history/ endpoint — returns recent sessions (htmx partial)
4. Add GET /org/<slug>/chat/<session_id>/ — loads a previous conversation
5. Sidebar in chat home template showing recent conversations (htmx-loaded)
6. Auto-generate session titles from the first user message
Estimated effort: ~1-2 days
Not yet started.
<!-- For UI/browser tasks: use Playwright MCP to explore the running app. Record bugs found, fixes applied, and suggestions for future work. Skip for non-UI tasks (mark N/A). -->
<!-- Reviewer comments, what was changed in response, and sign-off. -->