Skip to main content

Overview

When RecallrAI processes sessions, it may detect conflicts between new memories and existing ones. The SDK provides comprehensive tools to handle these merge conflicts through clarifying questions.

MergeConflict Class

The MergeConflict class represents a conflict between memories that requires resolution.

Properties

conflict_id
string
Unique identifier for the merge conflict.
user_id
string
ID of the user this conflict belongs to.
status
MergeConflictStatus
Current status: PENDING, IN_QUEUE, RESOLVING, RESOLVED, or FAILED
new_memory_content
string
Content of the new memory that conflicts with existing ones.
conflicting_memories
list
List of existing memories that conflict with the new memory. Each contains:
  • content: Memory content
  • reason: Explanation of why it conflicts
clarifying_questions
list
List of questions to help resolve the conflict. Each contains:
  • question: The question text
  • options: List of possible answers
created_at
datetime
UTC timestamp when the conflict was created.
resolved_at
datetime | None
UTC timestamp when resolved, or None if not yet resolved.
resolution_data
dict | None
Additional data about the resolution, or None if not resolved.

List Merge Conflicts

List merge conflicts for a user with optional filtering.
from recallrai.models import MergeConflictStatus

user = client.get_user("user123")

conflicts = user.list_merge_conflicts(
    offset=0,
    limit=10,
    status=MergeConflictStatus.PENDING,
    sort_by="created_at",
    sort_order="desc"
)

print(f"Total conflicts: {conflicts.total}")
print(f"Has more: {conflicts.has_more}")

for conf in conflicts.conflicts:
    print(f"Conflict ID: {conf.conflict_id}")
    print(f"Status: {conf.status}")
    print(f"New memory: {conf.new_memory_content}")
    print(f"Conflicting memories: {len(conf.conflicting_memories)}")
    print(f"Questions: {len(conf.clarifying_questions)}")
offset
integer
Number of conflicts to skip. Default: 0
limit
integer
Maximum number of conflicts to return. Default: 10
status
MergeConflictStatus
Filter by status. Options:
  • PENDING: Conflict detected and waiting for resolution
  • IN_QUEUE: Queued for automated processing
  • RESOLVING: Being processed
  • RESOLVED: Successfully resolved
  • FAILED: Resolution failed
sort_by
string
Sort field: created_at or resolved_at. Default: created_at
sort_order
string
Sort order: asc or desc. Default: desc
Returns: MergeConflictList object with conflicts, total, and has_more fields

Get a Specific Merge Conflict

Retrieve detailed information about a specific merge conflict.
from recallrai.exceptions import MergeConflictNotFoundError

try:
    user = client.get_user("user123")
    conflict = user.get_merge_conflict("conflict-uuid")
    
    print(f"Status: {conflict.status.value}")
    print(f"New memory: {conflict.new_memory_content}")
    
    # Examine conflicting memories
    print("\nConflicting memories:")
    for mem in conflict.conflicting_memories:
        print(f"  Content: {mem.content}")
        print(f"  Reason: {mem.reason}")
    
    # View clarifying questions
    print("\nClarifying questions:")
    for ques in conflict.clarifying_questions:
        print(f"  Question: {ques.question}")
        print(f"  Options: {ques.options}")
        
except MergeConflictNotFoundError as e:
    print(f"Error: {e}")
conflict_id
string
required
The UUID of the merge conflict to retrieve.
Returns: MergeConflict object Raises: UserNotFoundError, MergeConflictNotFoundError

Resolve a Merge Conflict

Resolve a merge conflict by answering the clarifying questions.
from recallrai.exceptions import (
    MergeConflictNotFoundError,
    MergeConflictAlreadyResolvedError,
    MergeConflictInvalidQuestionsError,
    MergeConflictMissingAnswersError,
    MergeConflictInvalidAnswerError,
)
from recallrai.models import MergeConflictAnswer

try:
    user = client.get_user("user123")
    conflict = user.get_merge_conflict("conflict-uuid")
    
    # Prepare answers to the clarifying questions
    answers = []
    for ques in conflict.clarifying_questions:
        print(f"Question: {ques.question}")
        print(f"Options: {ques.options}")
        
        # Select an option (in this example, we select the first one)
        answer = MergeConflictAnswer(
            question=ques.question,
            answer=ques.options[0],
            message="User prefers this option based on recent conversation"
        )
        answers.append(answer)
    
    # Resolve the conflict
    conflict.resolve(answers)
    
    print(f"Conflict resolved! Status: {conflict.status}")
    print(f"Resolved at: {conflict.resolved_at}")
    
    if conflict.resolution_data:
        print(f"Resolution data: {conflict.resolution_data}")
        
except MergeConflictNotFoundError as e:
    print(f"Conflict not found: {e}")
except MergeConflictAlreadyResolvedError as e:
    print(f"Conflict already resolved: {e}")
except MergeConflictInvalidQuestionsError as e:
    print(f"Invalid questions provided: {e}")
    if e.invalid_questions:
        print(f"Invalid questions: {e.invalid_questions}")
except MergeConflictMissingAnswersError as e:
    print(f"Missing answers: {e}")
    if e.missing_questions:
        print(f"Missing answers for: {e.missing_questions}")
except MergeConflictInvalidAnswerError as e:
    print(f"Invalid answer: {e}")
    if e.question and e.valid_options:
        print(f"Question: {e.question}")
        print(f"Valid options: {e.valid_options}")

resolve() Method

answers
list[MergeConflictAnswer]
required
List of answers to the clarifying questions. Each answer must include:
  • question: The question text (must match exactly)
  • answer: Selected option (must be one of the valid options)
  • message: Optional explanation for the choice
Returns: None (updates the instance in place) Raises:
  • MergeConflictNotFoundError: Conflict doesn’t exist
  • MergeConflictAlreadyResolvedError: Conflict already processed
  • MergeConflictInvalidQuestionsError: Questions don’t match original questions
  • MergeConflictMissingAnswersError: Not all questions have been answered
  • MergeConflictInvalidAnswerError: Answer is not a valid option
All clarifying questions must be answered, and each answer must match one of the provided options exactly.

Refresh Merge Conflict

Refresh the merge conflict instance to get the latest status from the server.
user = client.get_user("user123")
conflict = user.get_merge_conflict("conflict-uuid")

# Refresh to get latest status
conflict.refresh()
print(f"Current status: {conflict.status}")
print(f"Resolved at: {conflict.resolved_at}")
Returns: None (updates the instance in place) Raises: UserNotFoundError, MergeConflictNotFoundError

MergeConflictAnswer Model

When resolving conflicts, you need to create MergeConflictAnswer objects:
from recallrai.models import MergeConflictAnswer

answer = MergeConflictAnswer(
    question="Which food preference is correct?",
    answer="User prefers vegetarian meals",
    message="User explicitly mentioned being vegetarian in last conversation"
)
question
string
required
The exact question text from the conflict’s clarifying questions.
answer
string
required
The selected option. Must be one of the valid options from the question.
message
string
Optional explanation for why this answer was selected.

Merge Conflict Statuses

Conflict has been detected and is waiting for resolution. You can call resolve() to provide answers.
Conflict is queued for automated processing by the system.
Conflict is currently being processed.
Conflict has been successfully resolved. The memories have been updated accordingly.
Conflict resolution failed. You may need to contact support or try resolving again.

Async Merge Conflicts

For async applications, all merge conflict methods support async/await:
from recallrai import AsyncRecallrAI

client = AsyncRecallrAI(api_key="rai_yourapikey", project_id="project-uuid")
user = await client.get_user("user123")

# All methods are the same, just use await
conflicts = await user.list_merge_conflicts(status=MergeConflictStatus.PENDING)
conflict = await user.get_merge_conflict("conflict-uuid")
await conflict.resolve(answers)
await conflict.refresh()

Best Practices

Regular Monitoring: Check for pending merge conflicts regularly, especially after processing sessions with important conversations.
Contextual Answers: When resolving conflicts, use the message field to provide context about why you selected a particular answer. This helps improve the accuracy of future memory updates.
Error Handling: Always handle the specific merge conflict exceptions to provide appropriate user feedback and recovery options.