Files
Meister-Eder/openspec/changes/email-based-conversation-matching/design.md
T
gurixandClaude Opus 4.5 b10ff7a4fe Add change spec: email-based conversation matching
Replace thread-ID-based conversation matching with email-address-based
matching for more reliable conversation continuity. Key changes:

- One conversation per email address (simpler model)
- No data expiration (conversations persist indefinitely)
- Post-completion support (questions and registration updates)
- Versioned storage for registration updates (audit trail)
- Admin notifications for registration changes

This addresses the gap where parents sending new emails (instead of
replying) would lose their registration progress.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-20 22:00:21 +01:00

4.5 KiB

Context

The current implementation on branch claude/email-agent-multi-model-c3ShZ uses email threading headers to identify conversations. This is fragile—parents often send new emails instead of replying, breaking the thread association.

Current behavior:

Email 1 (new): "I want to register" → Thread ID: <abc@gmail.com> → New conversation
Email 2 (new): "Her name is Emma"  → Thread ID: <xyz@gmail.com> → NEW conversation (context lost!)

Desired behavior:

Email 1: parent@example.com → Conversation for parent@example.com (new)
Email 2: parent@example.com → Conversation for parent@example.com (continue)

Goals / Non-Goals

Goals:

  • Reliable conversation continuity regardless of email threading behavior
  • Simple mental model: one email address = one conversation
  • Support post-completion interactions (questions and updates)
  • Audit trail for registration changes

Non-Goals:

  • Supporting multiple registrations per email address (one parent, multiple children handled in single conversation)
  • Anonymous/guest conversations (email address is the identity)
  • Complex merge logic for duplicate conversations

Decisions

1. Conversation Key: Email Address

Decision: Use normalized sender email address as the conversation key.

Rationale: Email address is the only reliable identifier across email threads. Parents may use different devices, email clients, or simply compose new messages.

Normalization: Lowercase, trim whitespace. Consider: maria@Example.com = maria@example.com

Trade-off: A parent using multiple email addresses would have multiple conversations. This is acceptable—different address = different identity from the system's perspective.

2. Thread ID Usage

Decision: Store thread IDs for reply headers only, not for conversation matching.

Rationale: Thread IDs (Message-ID, In-Reply-To, References) are still needed for proper email client threading (so replies appear in the same thread in Gmail/Outlook). But matching uses email address.

Implementation: When sending a reply, use the most recent inbound message's ID for In-Reply-To.

3. No Data Expiration

Decision: Remove the 30-day retention limit for email conversations.

Rationale: With email-address-based matching, the conversation is a permanent record. There's no reason to delete it—if the parent returns in 6 months, their data should still be there.

Privacy consideration: If GDPR deletion is requested, admin can manually remove the conversation file.

4. Post-Completion Intent Detection

Decision: When a completed registration receives a new message, use the LLM to detect intent.

Intent categories:

  • Question: Parent asking about fees, schedule, policies → Answer from knowledge base
  • Update request: Parent wants to change registration data → Collect updates, version storage, notify admin
  • New registration: Parent wants to register another child → Continue in same conversation, add to booking

Implementation: Add prompt guidance for post-completion state; LLM returns intent field.

5. Versioned Registration Storage

Decision: Store registration updates as versions, not overwrites.

Structure:

data/registrations/
  parent_at_example.com/
    v1_2024-09-15.json  # Original registration
    v2_2024-10-03.json  # Updated (changed phone number)
    current.json        # Symlink or copy of latest

Rationale: Admin needs audit trail to see what changed and when. Original data preserved for compliance.

6. Admin Update Notifications

Decision: Send notification when registration is updated, including diff.

Email subject: "Registration Updated: [Child Name]" Body includes: What changed (old → new), when, conversation excerpt

Risks / Trade-offs

Multiple children per family → Single conversation handles this; booking can include multiple children. If needed later, extend the data model.

Parent changes email address → Creates new conversation. Admin would need to manually merge if needed. Acceptable for MVP.

Storage growth → Without expiration, conversations accumulate. Monitor disk usage; consider archival strategy later.

LLM intent detection accuracy → May misclassify. Err on the side of asking for clarification rather than making assumptions.

Open Questions

  • Should the system support explicit "delete my data" requests via email? (GDPR)
  • Should reminders stop after a certain count, or continue indefinitely for incomplete registrations?