Messages & History
How message persistence works, lazy loading history, and restoring conversations on mount.
How are messages stored?
Messages are stored per thread in the 21st Agents database. On each turn, the relay appends the newest user message and the agent's response to the existing thread history. You can retrieve the full stored history via client.threads.get({ sandboxId, threadId }).
How does message sending work under the hood?
On each sendMessage call, you can pass the AI SDK's current messages array, but the relay uses only the last user message as the next turn. Existing history is loaded from the stored thread, and the new turn is appended server-side instead of replacing the full message list in the database.
How do I restore history on page mount?
After mounting your chat component, fetch the existing messages using client.threads.get({ sandboxId, threadId }) and pass them to the AI SDK. This lets users see previous conversation when they return to the page. If you intentionally use one thread per sandbox and omit threadId on send, look up the latest thread for that sandbox before hydrating the UI.
Is lazy loading of message history supported?
Lazy loading for scrolling through long histories is on the roadmap. Currently, you fetch the full thread history on mount. For most use cases this is sufficient since individual threads don't accumulate thousands of messages.
Can I have multiple conversation threads?
Yes. Threads are supported out of the box - create multiple threads within the same sandbox. Each thread has its own message history while sharing the same sandbox environment (files, state, tools). If you omit threadId, the relay resumes the latest thread in that sandbox, so for multiple parallel conversations you should create threads explicitly and store each threadId.