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