Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.maximem.ai/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Before your application can ingest memories or retrieve context, you must initialize the Synap SDK. Initialization validates your API key, establishes a secure connection, and prepares local caching. The SDK follows a strict initialize, use, shutdown lifecycle.

Basic Initialization

The simplest way to get started requires only your SYNAP_API_KEY environment variable. Generate an API key from the Synap Dashboard and set it in your environment.
from synap import MaximemSynapSDK

sdk = MaximemSynapSDK(
    api_key="synap_your_key_here"
)

await sdk.initialize()
You must call await sdk.initialize() before invoking any SDK operations. Calling methods like sdk.memories.create() before initialization raises an AuthenticationError.

What initialize() Does

When you call initialize(), the SDK performs the following steps in order:
1

Resolve API Key

The SDK picks up the API key from the api_key= argument (if passed) or the SYNAP_API_KEY environment variable.
2

Connection Establishment

The SDK opens an authenticated REST connection to Synap Cloud and, if streaming is configured, a gRPC channel. Both send the API key as Authorization: Bearer synap_....
3

Cache Initialization

If a cache_backend is configured (default: sqlite), the SDK sets up the local cache database at the storage path.

Initialization with Custom Configuration

Pass an SDKConfig object to customize SDK behavior at construction time.
from synap import MaximemSynapSDK, SDKConfig, TimeoutConfig, RetryPolicy

config = SDKConfig(
    storage_path="/var/lib/myapp/synap",
    cache_backend="sqlite",
    session_timeout_minutes=60,
    timeouts=TimeoutConfig(
        connect=10.0,
        read=45.0,
        write=15.0,
        stream_idle=120.0
    ),
    retry_policy=RetryPolicy(
        max_attempts=5,
        backoff_base=1.5,
        backoff_max=30.0,
        backoff_jitter=True
    ),
    log_level="INFO"
)

sdk = MaximemSynapSDK(
    api_key="synap_your_key_here",
    config=config
)

await sdk.initialize()
See SDK Configuration for a complete reference of all configuration options.

Singleton Pattern

By default, the SDK maintains a single instance per instance_id. If you construct a second MaximemSynapSDK with the same instance_id, you receive a reference to the existing instance rather than creating a new one.
sdk_a = MaximemSynapSDK(api_key="synap_key_1")
sdk_b = MaximemSynapSDK(api_key="synap_key_1")

# sdk_a and sdk_b point to the same SDK instance
assert sdk_a is sdk_b
This prevents accidental duplication of connections and caches in applications that construct the SDK from multiple modules.

Overriding the Singleton for Testing

In test environments, use _force_new=True to bypass the singleton cache and create a fresh SDK instance each time.
sdk = MaximemSynapSDK(
    api_key="synap_test_key",
    _force_new=True
)
The _force_new parameter is intended for testing only. Using it in production can lead to multiple SDK instances competing for the same credential files and cache database.

Environment Variable Initialization

For CI/CD, containers, serverless, and production — just set the environment variable:
export SYNAP_API_KEY="synap_your_key_here"
from maximem_synap import MaximemSynapSDK

sdk = MaximemSynapSDK()
await sdk.initialize()
The SDK reads SYNAP_API_KEY automatically and resolves the instance ID from the server.

The configure() Method

If you need to adjust configuration after constructing the SDK but before calling initialize(), use the configure() method.
sdk = MaximemSynapSDK(
    api_key="synap_your_key_here"
)

# Adjust config before initialization
sdk.configure(
    log_level="DEBUG",
    session_timeout_minutes=120
)

await sdk.initialize()
Calling configure() after initialize() has no effect. All configuration must be finalized before the SDK is initialized.

SDK Lifecycle

The SDK follows a strict three-phase lifecycle:
SDK lifecycle: initialize, use, shutdown

1. Initialize

Call await sdk.initialize() to validate the API key and establish connections.

2. Use

Invoke SDK operations: sdk.memories.*, sdk.conversation.context.*, sdk.cache.*, etc. All operations are async and must be awaited.

3. Shutdown

Call await sdk.shutdown() to gracefully tear down the SDK.
await sdk.shutdown()
Always call shutdown() before your application exits to ensure pending telemetry is flushed and active gRPC streams are closed cleanly. Failing to call shutdown() may result in lost telemetry data and lingering connections.

Async Context Manager Pattern

For cleaner lifecycle management, use the SDK as an async context manager with try/finally.
from synap import MaximemSynapSDK

sdk = MaximemSynapSDK(
    api_key="synap_your_key_here"
)

try:
    await sdk.initialize()

    # Your application logic
    response = await sdk.memories.create(
        document="User asked about project deadlines...",
        user_id="user_12345"
    )
    print(f"Ingestion ID: {response.ingestion_id}")

finally:
    await sdk.shutdown()

Full Example with Error Handling

The following example demonstrates a production-ready initialization pattern with comprehensive error handling.
import logging
from synap import MaximemSynapSDK, SDKConfig, TimeoutConfig, RetryPolicy
from synap.errors import (
    AuthenticationError,
    NetworkTimeoutError,
    SynapError,
)

logger = logging.getLogger(__name__)


async def create_synap_sdk() -> MaximemSynapSDK:
    """Initialize the Synap SDK with production-ready configuration."""
    config = SDKConfig(
        storage_path="/var/lib/myapp/synap",
        cache_backend="sqlite",
        session_timeout_minutes=60,
        timeouts=TimeoutConfig(connect=10.0, read=30.0),
        retry_policy=RetryPolicy(max_attempts=3),
        log_level="WARNING",
    )

    sdk = MaximemSynapSDK(
        api_key="synap_your_key_here",
        config=config,
    )

    try:
        await sdk.initialize()
        logger.info("Synap SDK initialized successfully")
        return sdk

    except AuthenticationError as e:
        logger.error(
            "Authentication failed: %s (correlation_id=%s)",
            e, e.correlation_id
        )
        raise

    except NetworkTimeoutError:
        logger.error(
            "Could not reach Synap Cloud. Check network connectivity."
        )
        raise

    except SynapError as e:
        logger.error(
            "Unexpected Synap error during init: %s (correlation_id=%s)",
            e, e.correlation_id
        )
        raise


async def main():
    sdk = await create_synap_sdk()
    try:
        # Application logic here
        context = await sdk.conversation.context.fetch(
            conversation_id="conv_abc123",
            mode="fast"
        )
        print(f"Retrieved {len(context.facts)} facts")
    finally:
        await sdk.shutdown()
        logger.info("Synap SDK shut down cleanly")
The API key is read fresh on every start. There is no one-time setup step — the same SYNAP_API_KEY works forever (until you revoke it in the Dashboard).

Next Steps

Ingesting Memories

Send conversations and documents into Synap’s memory system.

Retrieving Memories

Query contextual memories for your AI agent.

SDK Configuration

Explore all configuration options in detail.