Skip to main content
Every SDK method returns a Pydantic model. This page lists them all in one place so you can grep for field names without hunting through individual method docs.
Type-specific field names. The Pydantic models below intentionally use type-specific field names — Preference.strength (not confidence) and Episode.summary (not content) — because each memory type has different semantics. The SDK handles transport-level field mapping internally; you only work with these typed models in application code.
All types live in maximem_synap and are importable from the top-level package:
from maximem_synap import (
    Fact, Preference, Episode, Emotion, TemporalEvent,
    ContextResponse, ConversationContextModel, ResponseMetadata,
    CreateMemoryResponse, MemoryStatusResponse, IngestStatus, IngestMode,
    CompactionResponse, CompactionTriggerResponse, CompactionStatusResponse,
    ContextForPromptResponse, RecentMessage,
    CompactionLevel,
)

Memory item types

These are the atomic units of structured memory. A ContextResponse is a bag of these.

Fact

class Fact(BaseModel):
    id: str                                    # opaque identifier
    content: str                               # natural-language fact
    confidence: float                          # 0.0 – 1.0
    source: str                                # memory ID this fact was extracted from
    extracted_at: datetime
    metadata: Dict[str, Any] = {}
    event_date: Optional[datetime] = None      # when the fact became true, if known
    valid_until: Optional[datetime] = None     # when the fact stopped being true, if known
    temporal_category: Optional[str] = None    # "perpetual" | "temporal_fact" | "episode"
    temporal_confidence: float = 0.0
    source_evidence: Optional[List[str]] = None

Preference

class Preference(BaseModel):
    id: str
    category: str                              # e.g., "communication", "dietary", "ui"
    content: str
    strength: float                            # 0.0 – 1.0 — NOT named `confidence`
    source: str = ""
    extracted_at: datetime
    metadata: Dict[str, Any] = {}
    event_date: Optional[datetime] = None
    valid_until: Optional[datetime] = None
    temporal_category: Optional[str] = None
    temporal_confidence: float = 0.0
    source_evidence: Optional[List[str]] = None

Episode

class Episode(BaseModel):
    id: str
    summary: str                               # narrative description — NOT `content`
    occurred_at: datetime
    significance: float                        # 0.0 – 1.0
    participants: List[str] = []               # entity IDs involved
    metadata: Dict[str, Any] = {}
    event_date: Optional[datetime] = None
    valid_until: Optional[datetime] = None
    temporal_category: Optional[str] = None
    temporal_confidence: float = 0.0
    source_evidence: Optional[List[str]] = None

Emotion

class Emotion(BaseModel):
    id: str
    emotion_type: str                          # "frustrated" | "satisfied" | "confused" | …
    intensity: float                           # 0.0 – 1.0
    detected_at: datetime
    context: str                               # what triggered the emotion
    metadata: Dict[str, Any] = {}
    event_date: Optional[datetime] = None
    valid_until: Optional[datetime] = None
    temporal_category: Optional[str] = None
    temporal_confidence: float = 0.0
    source_evidence: Optional[List[str]] = None

TemporalEvent

class TemporalEvent(BaseModel):
    id: str
    content: str
    event_date: datetime                       # REQUIRED — when the event occurred
    valid_until: Optional[datetime] = None
    temporal_category: str                     # REQUIRED — "perpetual" | "temporal_fact" | "episode"
    temporal_confidence: float                 # REQUIRED — 0.0 – 1.0
    confidence: float = 0.0
    source: str = ""
    extracted_at: Optional[datetime] = None
    metadata: Dict[str, Any] = {}
    source_evidence: Optional[List[str]] = None

Context responses

ContextResponse

Returned by conversation.context.fetch, user.context.fetch, customer.context.fetch, client.context.fetch.
class ContextResponse(BaseModel):
    facts: List[Fact] = []
    preferences: List[Preference] = []
    episodes: List[Episode] = []
    emotions: List[Emotion] = []
    temporal_events: List[TemporalEvent] = []
    metadata: ResponseMetadata

    # Optional rolling conversation context window (recent messages, summary)
    conversation_context: Optional[ConversationContextModel] = None
Iterate over all items in priority order:
for item in ctx.facts + ctx.preferences + ctx.episodes + ctx.emotions + ctx.temporal_events:
    print(item)
The atomized lists above are the primary surface. The optional conversation_context carries the rolling session view (compacted summary plus recent turns) as a single coherent block rather than atomized items — it is None unless the conversation has a compaction available.

ConversationContextModel

The current-session context attached to a ContextResponse as conversation_context. It bundles the compacted narrative summary, current state, key extractions, and the most recent raw turns together, instead of splitting them into the typed item lists. It is None when no compacted/session context exists for the conversation (e.g. a fresh conversation).
class ConversationContextModel(BaseModel):
    summary: Optional[str] = None                                   # compacted narrative summary
    current_state: Dict[str, Any] = {}                              # rolling "where things stand" state
    key_extractions: Dict[str, List[Dict[str, Any]]] = {}           # grouped facts/decisions/preferences
    recent_turns: List[Dict[str, Any]] = []                         # most recent raw conversation turns
    compaction_id: Optional[str] = None                             # source compaction, if any
    compacted_at: Optional[str] = None                              # when that compaction ran
    conversation_id: Optional[str] = None
conversation_context is the coherent-block view; facts / preferences / episodes / emotions / temporal_events are the atomized view of retrieval. Most integrations read the atomized lists; reach for conversation_context when you want the pre-assembled session narrative. For prompt-ready compacted text specifically, prefer get_context_for_prompt() (see Context Compaction).

ResponseMetadata

class ResponseMetadata(BaseModel):
    correlation_id: str                                 # log this on errors
    ttl_seconds: int                                    # local-cache validity
    source: str                                         # "cache", "cloud", or "anticipation"
    compaction_applied: Optional[CompactionLevel] = None  # enum if compaction ran, else None
    retrieved_at: datetime
compaction_applied is not a bool — it’s None when no compaction ran, or a CompactionLevel enum value when one did. Test with if meta.compaction_applied is not None.

Ingestion responses

CreateMemoryResponse

Returned by memories.create. Ingestion is async — this comes back immediately with an ingestion_id you can poll.
class CreateMemoryResponse(BaseModel):
    ingestion_id: UUID                         # poll status with sdk.memories.status(ingestion_id)
    document_id: str
    status: IngestStatus                       # see enum below
    queued_at: datetime
    error_message: Optional[str] = None        # populated when status == FAILED

IngestStatus enum

class IngestStatus(str, Enum):
    QUEUED = "queued"
    PROCESSING = "processing"
    COMPLETED = "completed"
    FAILED = "failed"
    PARTIAL_SUCCESS = "partial_success"

MemoryStatusResponse

Returned by memories.status(ingestion_id).
class MemoryStatusResponse(BaseModel):
    ingestion_id: UUID
    document_id: str
    status: IngestStatus
    queued_at: datetime
    started_at: Optional[datetime] = None
    completed_at: Optional[datetime] = None
    memories_created: int = 0
    memory_ids: List[str] = []                 # IDs of memories produced by this ingestion
    error_message: Optional[str] = None

Compaction responses

CompactionTriggerResponse

Returned by conversation.context.compact. This call kicks off a compaction job asynchronously and returns this trigger confirmation, not the compacted content. To get the actual compacted text, call get_compacted() once the job completes (or poll get_compaction_status()).
class CompactionTriggerResponse(BaseModel):
    compaction_id: str                         # poll status with get_compaction_status
    conversation_id: str
    status: str                                # e.g. "queued" | "in_progress"
    trigger_type: str                          # "manual" | "scheduled" | "threshold" | …
    initiated_at: datetime
    estimated_completion_seconds: Optional[int] = None

    # Populated when a prior compaction already existed for this conversation
    previous_context: Optional[str] = None
    previous_context_age_seconds: Optional[int] = None
    previous_compaction_id: Optional[str] = None

CompactionResponse

Returned by conversation.context.get_compacted. Carries the actual compacted text and typed extractions.
class CompactionResponse(BaseModel):
    compacted_context: str                     # the actual compacted text
    original_token_count: int
    compacted_token_count: int
    compression_ratio: float
    level_applied: CompactionLevel
    metadata: ResponseMetadata

    compaction_id: Optional[str] = None
    strategy_used: Optional[str] = None
    validation_score: Optional[float] = None
    validation_passed: Optional[bool] = None
    quality_warning: Optional[bool] = None     # True if quality below threshold

    # Typed extractions surfaced from the underlying conversation
    facts: List[Dict[str, Any]] = []
    decisions: List[Dict[str, Any]] = []
    preferences: List[Dict[str, Any]] = []
    current_state: Optional[Dict[str, Any]] = None

CompactionStatusResponse

Returned by get_compaction_status. This is a Pydantic model — access fields as attributes, not dict keys.
class CompactionStatusResponse(BaseModel):
    conversation_id: str
    status: str                                # "completed" | "in_progress" | "failed" | "none"
    compaction_id: Optional[str] = None
    completed_at: Optional[datetime] = None
    compression_ratio: Optional[float] = None
    validation_score: Optional[float] = None
    estimated_completion_seconds: Optional[int] = None
    error_message: Optional[str] = None
    latest_version: Optional[int] = None
    latest_created_at: Optional[datetime] = None

ContextForPromptResponse

Returned by get_context_for_prompt. Optimized for direct injection into an LLM system prompt.
class ContextForPromptResponse(BaseModel):
    formatted_context: Optional[str] = None    # ready to splice into a system prompt
    available: bool = False                    # is there compacted context yet?
    is_stale: bool = False                     # new messages since the last compaction?
    compression_ratio: Optional[float] = None
    validation_score: Optional[float] = None
    compaction_age_seconds: Optional[int] = None
    quality_warning: bool = False              # default False, never None

    recent_messages: List[RecentMessage] = []
    recent_message_count: int = 0
    compacted_message_count: int = 0
    total_message_count: int = 0

CompactionLevel enum

class CompactionLevel(str, Enum):
    LOW = "low"
    MEDIUM = "medium"
    HIGH = "high"
    CONSERVATIVE = "conservative"
    BALANCED = "balanced"
    AGGRESSIVE = "aggressive"
    ADAPTIVE = "adaptive"
All seven values are equally canonical members of the enum.

Type-checking tips

  • Only ContextResponse and CompactionResponse have model_config = {"extra": "allow"} and expose the raw cloud payload via a .raw property; other models silently drop unknown fields. When the cloud adds a new field on those two models, you can read it from response.raw until a typed attribute ships.
  • Datetime fields are timezone-aware (UTC). When comparing, use datetime.now(timezone.utc), not datetime.utcnow().
  • For runtime validation (e.g., in your application boundary), call .model_validate(...) rather than constructing manually — Pydantic enforces all constraints.