Skip to main content

Overview

Before your application can ingest memories or retrieve context, you must initialize the Synap SDK. Initialization bootstraps credentials against Synap Cloud, 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 instance_id and bootstrap_token. Both are provided when you create an instance in the Synap Dashboard.
from synap import MaximemSynapSDK

sdk = MaximemSynapSDK(
    instance_id="inst_a1b2c3d4e5f67890",
    bootstrap_token="your-bootstrap-token"
)

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

Bootstrap Authentication

The SDK exchanges the bootstrap token for a short-lived API key and mTLS certificate pair via Synap Cloud. The bootstrap token is consumed on first use and cannot be reused.
2

Credential Storage

The obtained credentials (API key hash, mTLS certificate) are persisted locally in the configured storage_path. On subsequent starts, the SDK loads existing credentials instead of re-bootstrapping.
3

Connection Establishment

The SDK opens an authenticated REST connection to Synap Cloud and, if streaming is configured, a gRPC channel secured with mTLS.
4

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",
    credentials_source="file",
    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(
    instance_id="inst_a1b2c3d4e5f67890",
    bootstrap_token="your-bootstrap-token",
    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(instance_id="inst_a1b2c3d4e5f67890", bootstrap_token="token-1")
sdk_b = MaximemSynapSDK(instance_id="inst_a1b2c3d4e5f67890", bootstrap_token="token-2")

# 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(
    instance_id="inst_test_1234567890ab",
    bootstrap_token="test-token",
    _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

When deploying to environments where writing bootstrap tokens into code is undesirable (CI/CD, containers, serverless), set credentials_source="env" and provide credentials via environment variables.
export SYNAP_INSTANCE_ID="inst_a1b2c3d4e5f67890"
export SYNAP_BOOTSTRAP_TOKEN="your-bootstrap-token"
export SYNAP_API_KEY="your-api-key"        # After initial bootstrap
export SYNAP_CERT_PATH="/etc/synap/cert.pem"
export SYNAP_KEY_PATH="/etc/synap/key.pem"
from synap import MaximemSynapSDK, SDKConfig

sdk = MaximemSynapSDK(
    instance_id="inst_a1b2c3d4e5f67890",
    config=SDKConfig(credentials_source="env")
)

await sdk.initialize()
When credentials_source="env", the SDK reads credentials from environment variables instead of the local filesystem. The bootstrap_token constructor argument can be omitted if SYNAP_BOOTSTRAP_TOKEN is set.

The configure() Method

If you need to adjust configuration after constructing the SDK but before calling initialize(), use the configure() method.
sdk = MaximemSynapSDK(
    instance_id="inst_a1b2c3d4e5f67890",
    bootstrap_token="your-bootstrap-token"
)

# 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 bootstrap credentials 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(
    instance_id="inst_a1b2c3d4e5f67890",
    bootstrap_token="your-bootstrap-token"
)

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,
    BootstrapKeyInvalidError,
    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(
        instance_id="inst_a1b2c3d4e5f67890",
        bootstrap_token="your-bootstrap-token",
        config=config,
    )

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

    except BootstrapKeyInvalidError:
        logger.error(
            "Bootstrap token is invalid or already consumed. "
            "Generate a new one from the Synap Dashboard."
        )
        raise

    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")
After the first successful initialization, the bootstrap token is consumed. On subsequent application restarts, the SDK loads persisted credentials automatically and does not need the bootstrap token. You can remove it from your configuration after the first run.

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.