tasks/workstreams/mcp-analyst-agent/tasks/chat-conversation-persistence-and-history.md


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


Chat Conversation Persistence and History

Problem

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

Context

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)

Possible Solutions

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.

Option B: Session storage (Django sessions or Redis)

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.

Plan

Files to create: - apps/cloud/apps/chat/models.pyChatSession, 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

Implementation Progress

Not yet started.

QA Exploration

<!-- 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). -->

Review Feedback

<!-- Reviewer comments, what was changed in response, and sign-off. -->