Skip to content

🚀 Traylinx Cortex v2.2.0 - Frontend Integration Guide

What's New

Cortex v2.2.0 introduces automatic memory deduplication to prevent storing redundant information. The system now automatically detects and prevents duplicate facts like:

  • ❌ "User's name is Sebastian" (stored 5 times)
  • ❌ "User has a dog named Olivia" (stored 7 times)
  • ❌ "User is interested in the current date and time" (stored 4 times)

✅ Now each fact is stored only once, keeping the oldest version.


🎯 What You Need to Implement

Add a one-time cleanup button to help users clean up existing duplicates.

Where to add it: - Settings page - Memory management section - Admin panel

What it does: 1. Shows users how many duplicate memories they have 2. Lets them merge duplicates with one click 3. Displays results (e.g., "Deleted 15 duplicate memories")


📋 Implementation Steps

Step 1: Add "Find Duplicates" Button

// React/TypeScript example
async function findDuplicates() {
  const response = await fetch(
    `${API_BASE_URL}/v1/memory/duplicates?app_id=${appId}`,
    {
      headers: {
        'Authorization': `Bearer ${userToken}`
      }
    }
  );

  const data = await response.json();
  // data.groups = array of duplicate groups
  // data.total_duplicates = total count

  return data;
}

Response format:

{
  "groups": [
    {
      "canonical_id": "uuid-1",
      "canonical_content": "User's name is Sebastian",
      "duplicates": [
        {
          "id": "uuid-2",
          "content": "User is called Sebastian",
          "created_at": "2025-12-02T14:30:00Z",
          "similarity_to_canonical": 0.92
        }
      ]
    }
  ],
  "total_duplicates": 15
}

Display what will be merged:

{duplicateGroups.map(group => (
  <div key={group.canonical_id} className="duplicate-group">
    <div className="canonical">
       Keep: {group.canonical_content}
    </div>
    {group.duplicates.map(dup => (
      <div key={dup.id} className="duplicate">
         Delete: {dup.content} (similarity: {(dup.similarity_to_canonical * 100).toFixed(0)}%)
      </div>
    ))}
  </div>
))}

Step 3: Add "Merge Duplicates" Button

async function mergeDuplicates() {
  const response = await fetch(
    `${API_BASE_URL}/v1/memory/deduplicate?app_id=${appId}`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${userToken}`
      }
    }
  );

  const result = await response.json();
  // result.deleted_count = number of memories deleted
  // result.groups_merged = number of groups merged

  return result;
}

Response format:

{
  "success": true,
  "deleted_count": 15,
  "groups_merged": 5
}


🎨 UI/UX Recommendations

Simple Approach (Minimal UI)

┌─────────────────────────────────────┐
│ Memory Cleanup                      │
├─────────────────────────────────────┤
│ Found 15 duplicate memories         │
│                                     │
│ [Clean Up Duplicates]               │
└─────────────────────────────────────┘

Advanced Approach (With Preview)

┌─────────────────────────────────────┐
│ Memory Cleanup                      │
├─────────────────────────────────────┤
│ Found 5 groups with 15 duplicates   │
│                                     │
│ Group 1:                            │
│ ✅ Keep: User's name is Sebastian   │
│ ❌ Delete: User is called Sebastian │
│ ❌ Delete: User is referred to as...│
│                                     │
│ [Show All Groups] [Merge All]       │
└─────────────────────────────────────┘

📝 Sample Code (Complete Component)

import { useState } from 'react';

interface DuplicateGroup {
  canonical_id: string;
  canonical_content: string;
  duplicates: Array<{
    id: string;
    content: string;
    similarity_to_canonical: number;
  }>;
}

export function MemoryCleanup({ token, appId }: { token: string; appId: string }) {
  const [loading, setLoading] = useState(false);
  const [groups, setGroups] = useState<DuplicateGroup[]>([]);
  const [totalDuplicates, setTotalDuplicates] = useState(0);
  const [result, setResult] = useState<{ deleted: number; merged: number } | null>(null);

  async function findDuplicates() {
    setLoading(true);
    try {
      const response = await fetch(
        `https://api.traylinx.com/v1/memory/duplicates?app_id=${appId}`,
        { headers: { 'Authorization': `Bearer ${token}` } }
      );
      const data = await response.json();
      setGroups(data.groups);
      setTotalDuplicates(data.total_duplicates);
    } catch (error) {
      console.error('Failed to find duplicates:', error);
    } finally {
      setLoading(false);
    }
  }

  async function mergeDuplicates() {
    if (!confirm(`Delete ${totalDuplicates} duplicate memories?`)) return;

    setLoading(true);
    try {
      const response = await fetch(
        `https://api.traylinx.com/v1/memory/deduplicate?app_id=${appId}`,
        {
          method: 'POST',
          headers: { 'Authorization': `Bearer ${token}` }
        }
      );
      const data = await response.json();
      setResult({ deleted: data.deleted_count, merged: data.groups_merged });
      setGroups([]);
      setTotalDuplicates(0);
    } catch (error) {
      console.error('Failed to merge duplicates:', error);
    } finally {
      setLoading(false);
    }
  }

  return (
    <div className="memory-cleanup">
      <h2>Memory Cleanup</h2>

      {!groups.length && !result && (
        <button onClick={findDuplicates} disabled={loading}>
          {loading ? 'Scanning...' : 'Find Duplicates'}
        </button>
      )}

      {groups.length > 0 && (
        <>
          <p>Found {totalDuplicates} duplicate memories in {groups.length} groups</p>
          <button onClick={mergeDuplicates} disabled={loading}>
            {loading ? 'Merging...' : 'Clean Up Duplicates'}
          </button>
        </>
      )}

      {result && (
        <div className="success">
           Deleted {result.deleted} duplicate memories ({result.merged} groups merged)
        </div>
      )}
    </div>
  );
}

🔧 Configuration (Optional)

If you want to expose deduplication settings to admins, these are the backend env vars:

MEMORY_DEDUP_SIMILARITY_THRESHOLD=0.85  # How similar = duplicate (0-1)
MEMORY_DEDUP_LLM_CHECK_ENABLED=true     # Use AI to verify borderline cases

You don't need to expose these in the UI - defaults work well.


✅ Testing Checklist

  • [ ] Can find duplicates (GET endpoint works)
  • [ ] Shows correct count of duplicates
  • [ ] Can merge duplicates (POST endpoint works)
  • [ ] Shows success message after merge
  • [ ] Handles errors gracefully
  • [ ] Works with user authentication
  • [ ] Respects app_id filtering

📚 Documentation References

  • Full API Docs: docs/./api_reference.md (search for "duplicates")
  • Quick Reference: docs/memory/README.md (see "Memory Deduplication" section)
  • Changelog: docs/memory/CHANGELOG.md (v2.2.0 section)

🎯 Priority

Low Priority - This is a cleanup feature for existing users. New facts are automatically deduplicated, so this is only needed to clean up historical duplicates.

Suggested Timeline: - Week 1: Add simple "Find & Merge" button - Week 2: Add preview UI (optional) - Week 3: Add to settings/admin panel


❓ Questions?

  • Check docs/./api_reference.md for complete endpoint documentation
  • See docs/memory/README.md for code examples
  • Backend is already deployed and working - just add the UI!

TL;DR: Add two buttons: "Find Duplicates" (GET) and "Clean Up" (POST). Show count and success message. That's it! 🎉