Storage Requirements: Message persistence requires both
userId
and
threadId
to be set. Without these IDs, storage operations are skipped and
messages remain in memory only.Quick Start
Cedar works out of the box with no storage (no persistence). To enable persistence, configure a storage adapter.Storage Options
Cedar supports three storage adapters:- Local Storage (default) - Browser localStorage
- No Storage - Disables persistence
- Custom Storage - Your own implementation
messageStorage
prop to CedarCopilot:
Additional Configuration Requirements by Storage Type
Local Storage & No Storage
No additional configuration needed - these options work out of the box.Custom Storage
Implement your own storage solution by providing a custom adapter:How Default Message Storage Works
Cedar preconfigures several storage methods that orchestrate your adapter’s functionality. Understanding these helps you work with Cedar’s storage system effectively.Preconfigured Storage Methods
Cedar provides these methods out of the box. These methods are automatically
called by Cedar at appropriate times - you don’t need to call them directly.
To customize their behavior, you can override them in your implementation.
1. initializeChat({threadId?: string, userId?: string})
This method orchestrates the initial loading of threads and messages. It’s automatically called:
- When the message storage adapter is first set
- When userId or threadId changes in Cedar state
2. persistMessageStorageMessage(message)
This method handles message persistence with intelligent thread management:
3. sendMessage()
Storage Actions
When a user sends a message, Cedar performs these storage operations:
Best practice: make your load endpoints idempotent. Implementations of
listThreads
or loadMessages
should NOT perform any mutations such as
creating threads or messages. Cedar may call these functions multiple times
during normal operation; if they create data each time you could end up with
duplicated threads or messages.Automatic Behaviors
Thread & Message Loading:- When storage adapter is set: Adapter is configured but chat initialization happens separately
- When user ID or thread ID changes: Triggers
initializeChat
which:- Loads all threads for the user
- May auto-select first thread if none selected
- Loads messages for the selected thread
- When userId is undefined: Storage operations are skipped entirely
- When threadId is undefined: A new UUID is generated during message persistence
User and Thread Management
User ID and thread ID are both stored as Cedar State variables and are
automatically sent to the backend for Mastra and Custom backends. See Agent
Backend Connection docs for more details.
Setting User ID
User ID is a Cedar State variable that can be set in two ways: Method 1: Initial Configuration (Recommended) Pass the user ID directly to CedarCopilot as a prop. This is the simplest and most common approach:When you pass
userId
to CedarCopilot, it automatically: - Registers it as a
Cedar State variable (null values become empty strings) - Triggers
initializeChat
which loads threads for that user - Makes it available
throughout your app via Cedar State- Cedar loads threads for the new user
- If no thread is selected, may auto-select first thread (if
listThreads
is implemented) - Messages are cleared and reloaded based on the user’s threads
Setting Thread ID
Thread ID is a Cedar State variable that can be set in three ways: Method 1: Initial Configuration Pass the thread ID directly to CedarCopilot as a prop. This is useful when you want to start with a specific thread:Like userId, threadId is registered as a Cedar State variable with null values
converted to empty strings. This triggers
initializeChat
to load messages
for the specified thread.listThreads
If you implement the listThreads
method in your storage adapter, Cedar will automatically select the first available thread when no thread is currently selected. This is perfect for app initialization:
- Clears the current messages from the UI
- Loads messages for the new thread from storage
- Updates the UI with the new thread’s messages
Next Steps
- Learn about custom message rendering for rich content
- Explore streaming responses for real-time interactions
- Set up agent backend connections for AI responses