Managing chat sessions
Written By Stanislas
Last updated 16 days ago
Chat sessions represent individual conversations with your AI agent. Learn how to create, retrieve, update, and delete sessions to organize multiple conversations for your users.
Overview
Each chat session maintains its own message history and configuration. Think of a session as a separate conversation thread β you can have multiple sessions per user, each with its own context and messages. Sessions are stored persistently, so users can return to previous conversations anytime.
This guide covers how to list sessions, create new ones, retrieve session details with message history, update session properties, and delete sessions when no longer needed.
Prerequisites
Before working with sessions, ensure you have:
Authenticated with the API β Follow the Authentication & Setup guide to get your
accessTokenandworkspaceIdConfigured your GraphQL client β Your Apollo Client must include the required authentication headers
A todo ID β Received in the authentication response as
todoId(this is the container for all sessions)
Getting started
Here's the minimal setup to create and list sessions:
Step 1: List existing sessions
Retrieve a paginated list of all chat sessions for a user.
import { gql } from '@apollo/client';
const GET_SESSIONS = gql`
query GetTodoChatSessions($todoId: Float!, $limit: Int, $offset: Int) {
getTodoChatSessions(todoId: $todoId, limit: $limit, offset: $offset) {
sessions {
id
title
createdAt
updatedAt
defaultBotId
}
totalCount
}
}
`;
const listSessions = async (client, todoId, limit = 20, offset = 0) => {
const { data } = await client.query({
query: GET_SESSIONS,
variables: { todoId, limit, offset },
});
return data.getTodoChatSessions;
};
// Usage
const result = await listSessions(client, 12345);
console.log(`Found ${result.totalCount} sessions`);
result.sessions.forEach(session => {
console.log(`- ${session.title} (ID: ${session.id})`);
});
Step 2: Create a new session
Create a new chat session for a conversation.
const CREATE_SESSION = gql`
mutation CreateTodoChatSession($data: TodoChatSessionInput!) {
createTodoChatSession(data: $data) {
id
title
createdAt
defaultBotId
todoId
}
}
`;
const createSession = async (client, todoId, title = 'New Chat') => {
const { data } = await client.mutate({
mutation: CREATE_SESSION,
variables: {
data: {
todoId,
title,
},
},
});
return data.createTodoChatSession;
};
// Usage
const newSession = await createSession(client, 12345, 'Customer Support');
console.log('Created session:', newSession.id);
Step 3: Get session details with messages
Retrieve a specific session including all its messages.
const GET_SESSION = gql`
query GetOneTodoChatSession($sessionId: Float!) {
getOneTodoChatSession(sessionId: $sessionId) {
id
title
createdAt
updatedAt
defaultBotId
todoId
messages {
id
message
createdAt
sentBy {
id
firstName
}
isBotReply
}
}
}
`;
const getSessionDetails = async (client, sessionId) => {
const { data } = await client.query({
query: GET_SESSION,
variables: { sessionId },
});
return data.getOneTodoChatSession;
};
// Usage
const session = await getSessionDetails(client, 67890);
console.log(`Session: ${session.title}`);
console.log(`Messages: ${session.messages.length}`);
session.messages.forEach(msg => {
const sender = msg.isBotReply ? 'Bot' : msg.sentBy.firstName;
console.log(`${sender}: ${msg.message}`);
});
Querying sessions
Get sessions list
Retrieve a paginated list of chat sessions for a user.
GraphQL Query:
query GetTodoChatSessions($todoId: Float!, $limit: Int, $offset: Int) {
getTodoChatSessions(todoId: $todoId, limit: $limit, offset: $offset) {
sessions {
id
title
createdAt
updatedAt
defaultBotId
}
totalCount
}
}
Parameters:
todoId(required) β The container ID from your authentication responselimit(optional) β Number of sessions per page (default: 20)offset(optional) β Pagination offset for fetching pages (default: 0)
Returns: Object containing sessions array and totalCount
Example with pagination:
const listSessionsWithPagination = async (client, todoId) => {
const pageSize = 10;
let offset = 0;
let allSessions = [];
let totalCount = 0;
// Fetch first page
const { data } = await client.query({
query: GET_SESSIONS,
variables: { todoId, limit: pageSize, offset },
});
totalCount = data.getTodoChatSessions.totalCount;
allSessions = data.getTodoChatSessions.sessions;
// Fetch remaining pages if needed
while (allSessions.length < totalCount) {
offset += pageSize;
const { data: nextPage } = await client.query({
query: GET_SESSIONS,
variables: { todoId, limit: pageSize, offset },
});
allSessions = [...allSessions, ...nextPage.getTodoChatSessions.sessions];
}
return allSessions;
};
Get single session details
Retrieve complete details of a specific session, including all messages.
GraphQL Query:
query GetOneTodoChatSession($sessionId: Float!) {
getOneTodoChatSession(sessionId: $sessionId) {
id
title
createdAt
updatedAt
defaultBotId
todoId
messages {
id
message
createdAt
sentBy {
id
firstName
}
isBotReply
}
}
}
Parameters:
sessionId(required) β The ID of the session to retrieve
Returns: Complete session object with message history
Get or create starter session
Retrieve or create the default starter session for a user. This is useful if you want a quick "get started" experience without explicitly creating a session.
GraphQL Query:
query GetOrCreateUserStartTodoChatSession($botSlug: String) {
getOrCreateUserStartTodoChatSession(botSlug: $botSlug) {
id
title
defaultBotId
todoId
}
}
Parameters:
botSlug(optional) β The slug of your agent
Returns: The starter session (created if it doesn't exist)
Example:
const GET_STARTER_SESSION = gql`
query GetOrCreateUserStartTodoChatSession($botSlug: String) {
getOrCreateUserStartTodoChatSession(botSlug: $botSlug) {
id
title
defaultBotId
}
}
`;
const getStarterSession = async (client, botSlug) => {
const { data } = await client.query({
query: GET_STARTER_SESSION,
variables: { botSlug },
});
return data.getOrCreateUserStartTodoChatSession;
};
// Usage - useful for quick start without creating a new session
const starterSession = await getStarterSession(client, 'my-agent-slug');
console.log('Using starter session:', starterSession.id);
Search sessions
Search through chat sessions by title or content.
GraphQL Query:
query GetSearchTodoChatSessions($todoId: Float!, $searchQuery: String) {
getSearchTodoChatSessions(todoId: $todoId, searchQuery: $searchQuery) {
id
title
createdAt
}
}
Parameters:
todoId(required) β The container IDsearchQuery(optional) β Search term to filter sessions
Returns: Array of matching sessions
Example:
const SEARCH_SESSIONS = gql`
query GetSearchTodoChatSessions($todoId: Float!, $searchQuery: String) {
getSearchTodoChatSessions(todoId: $todoId, searchQuery: $searchQuery) {
id
title
createdAt
}
}
`;
const searchSessions = async (client, todoId, query) => {
const { data } = await client.query({
query: SEARCH_SESSIONS,
variables: { todoId, searchQuery: query },
});
return data.getSearchTodoChatSessions;
};
// Usage
const results = await searchSessions(client, 12345, 'billing');
console.log(`Found ${results.length} sessions matching "billing"`);
Creating and updating sessionsCreate a new session
Create a new chat session with optional bot configuration.
GraphQL Mutation:
mutation CreateTodoChatSession($data: TodoChatSessionInput!) {
createTodoChatSession(data: $data) {
id
title
createdAt
defaultBotId
todoId
}
}
Input parameters:
Example:
const CREATE_SESSION = gql`
mutation CreateTodoChatSession($data: TodoChatSessionInput!) {
createTodoChatSession(data: $data) {
id
title
createdAt
defaultBotId
}
}
`;
// Basic session
const basicSession = await client.mutate({
mutation: CREATE_SESSION,
variables: {
data: {
todoId: 12345,
title: 'Product Questions',
},
},
});
// Session with specific bot
const botSession = await client.mutate({
mutation: CREATE_SESSION,
variables: {
data: {
todoId: 12345,
title: 'Support Chat',
defaultBotId: 789,
},
},
});
// Session with custom layout
const compactSession = await client.mutate({
mutation: CREATE_SESSION,
variables: {
data: {
todoId: 12345,
title: 'Quick Chat',
uiLayout: 'COMPACT',
},
},
});
Update a session
Update properties of an existing session (like title or configuration).
GraphQL Mutation:
mutation UpdateTodoChatSession($data: TodoChatSessionInput!, $id: Float!) {
updateTodoChatSession(data: $data, id: $id) {
id
title
updatedAt
}
}
Parameters:
id(required) β Session ID to updatedata(required) β Object with fields to update (same as creation input)
Example:
const UPDATE_SESSION = gql`
mutation UpdateTodoChatSession($data: TodoChatSessionInput!, $id: Float!) {
updateTodoChatSession(data: $data, id: $id) {
id
title
updatedAt
}
}
`;
const updateSession = async (client, sessionId, updates) => {
const { data } = await client.mutate({
mutation: UPDATE_SESSION,
variables: {
id: sessionId,
data: updates,
},
});
return data.updateTodoChatSession;
};
// Usage
const updated = await updateSession(client, 67890, {
title: 'Updated Session Title',
});
console.log('Session updated:', updated.title);
Update custom bot configuration
Configure custom LLM parameters for a specific session (like model and temperature).
GraphQL Mutation:
mutation UpdateCustomBotConfig($data: BotCustomConfigInput!) {
updateTodoChatSessionCustomBotConfig(data: $data) {
id
}
}
Input parameters:
Example:
const UPDATE_BOT_CONFIG = gql`
mutation UpdateCustomBotConfig($data: BotCustomConfigInput!) {
updateTodoChatSessionCustomBotConfig(data: $data) {
id
}
}
`;
// Set model and temperature for a session
const configResult = await client.mutate({
mutation: UPDATE_BOT_CONFIG,
variables: {
data: {
botId: 123,
sessionId: 67890,
model: 'gpt-4',
temperature: 0.7,
},
},
});
console.log('Bot config updated for session:', configResult.data.updateTodoChatSessionCustomBotConfig.id);
Deleting sessions
Delete a single session
Delete one chat session and all its messages.
GraphQL Mutation:
mutation DeleteTodoChatSession($id: Float!) {
deleteTodoChatSession(id: $id) {
id
}
}
Parameters:
id(required) β Session ID to delete
Example:
const DELETE_SESSION = gql`
mutation DeleteTodoChatSession($id: Float!) {
deleteTodoChatSession(id: $id) {
id
}
}
`;
const deleteSession = async (client, sessionId) => {
const { data } = await client.mutate({
mutation: DELETE_SESSION,
variables: { id: sessionId },
});
return data.deleteTodoChatSession;
};
// Usage
const deleted = await deleteSession(client, 67890);
console.log('Session deleted:', deleted.id);
Delete multiple sessions
Delete multiple sessions in a single operation for efficiency.
GraphQL Mutation:
mutation DeleteManyTodoChatSession($ids: [Int!]!) {
deleteManyTodoChatSession(ids: $ids)
}
Parameters:
ids(required) β Array of session IDs to delete
Example:
const DELETE_MANY_SESSIONS = gql`
mutation DeleteManyTodoChatSession($ids: [Int!]!) {
deleteManyTodoChatSession(ids: $ids)
}
`;
const deleteManySessions = async (client, sessionIds) => {
const { data } = await client.mutate({
mutation: DELETE_MANY_SESSIONS,
variables: { ids: sessionIds },
});
return data.deleteManyTodoChatSession;
};
// Usage
const result = await deleteManySessions(client, [101, 102, 103]);
console.log(`Deleted ${result} sessions`);
Complete session manager class
Here's a reusable class that encapsulates all session operations:
class SessionManager {
constructor(client, todoId) {
this.client = client;
this.todoId = todoId;
}
async listSessions(limit = 20, offset = 0) {
const query = gql`
query GetTodoChatSessions($todoId: Float!, $limit: Int, $offset: Int) {
getTodoChatSessions(todoId: $todoId, limit: $limit, offset: $offset) {
sessions {
id
title
createdAt
defaultBotId
}
totalCount
}
}
`;
const { data } = await this.client.query({
query,
variables: { todoId: this.todoId, limit, offset },
});
return data.getTodoChatSessions;
}
async createSession(title = 'New Chat', options = {}) {
const mutation = gql`
mutation CreateTodoChatSession($data: TodoChatSessionInput!) {
createTodoChatSession(data: $data) {
id
title
createdAt
defaultBotId
}
}
`;
const { data } = await this.client.mutate({
mutation,
variables: {
data: {
todoId: this.todoId,
title,
...options,
},
},
});
return data.createTodoChatSession;
}
async getSessionDetails(sessionId) {
const query = gql`
query GetOneTodoChatSession($sessionId: Float!) {
getOneTodoChatSession(sessionId: $sessionId) {
id
title
createdAt
updatedAt
defaultBotId
messages {
id
message
createdAt
isBotReply
sentBy {
firstName
}
}
}
}
`;
const { data } = await this.client.query({
query,
variables: { sessionId },
});
return data.getOneTodoChatSession;
}
async updateSession(sessionId, updates) {
const mutation = gql`
mutation UpdateTodoChatSession($data: TodoChatSessionInput!, $id: Float!) {
updateTodoChatSession(data: $data, id: $id) {
id
title
updatedAt
}
}
`;
const { data } = await this.client.mutate({
mutation,
variables: {
id: sessionId,
data: updates,
},
});
return data.updateTodoChatSession;
}
async deleteSession(sessionId) {
const mutation = gql`
mutation DeleteTodoChatSession($id: Float!) {
deleteTodoChatSession(id: $id) {
id
}
}
`;
await this.client.mutate({
mutation,
variables: { id: sessionId },
});
}
async deleteManySessions(sessionIds) {
const mutation = gql`
mutation DeleteManyTodoChatSession($ids: [Int!]!) {
deleteManyTodoChatSession(ids: $ids)
}
`;
const { data } = await this.client.mutate({
mutation,
variables: { ids: sessionIds },
});
return data.deleteManyTodoChatSession;
}
async searchSessions(query) {
const gqlQuery = gql`
query GetSearchTodoChatSessions($todoId: Float!, $searchQuery: String) {
getSearchTodoChatSessions(todoId: $todoId, searchQuery: $searchQuery) {
id
title
createdAt
}
}
`;
const { data } = await this.client.query({
query: gqlQuery,
variables: { todoId: this.todoId, searchQuery: query },
});
return data.getSearchTodoChatSessions;
}
async getStarterSession(botSlug) {
const query = gql`
query GetOrCreateUserStartTodoChatSession($botSlug: String) {
getOrCreateUserStartTodoChatSession(botSlug: $botSlug) {
id
title
defaultBotId
}
}
`;
const { data } = await this.client.query({
query,
variables: { botSlug },
});
return data.getOrCreateUserStartTodoChatSession;
}
async updateBotConfig(botId, sessionId, config) {
const mutation = gql`
mutation UpdateCustomBotConfig($data: BotCustomConfigInput!) {
updateTodoChatSessionCustomBotConfig(data: $data) {
id
}
}
`;
const { data } = await this.client.mutate({
mutation,
variables: {
data: {
botId,
sessionId,
...config,
},
},
});
return data.updateTodoChatSessionCustomBotConfig;
}
}
// Usage example
const sessionManager = new SessionManager(client, 12345);
// Create a new session
const session = await sessionManager.createSession('Customer Support');
console.log('Created session:', session.id);
// Get session details
const details = await sessionManager.getSessionDetails(session.id);
console.log('Messages in session:', details.messages.length);
// Update session
await sessionManager.updateSession(session.id, { title: 'Premium Support' });
// Search sessions
const results = await sessionManager.searchSessions('support');
console.log('Found sessions:', results.length);
// Delete session
await sessionManager.deleteSession(session.id);
Practical use cases
Multi-threaded support system
Organize customer support conversations into separate sessions by topic:
const sessionManager = new SessionManager(client, todoId);
// Create sessions for different support categories
const billingSession = await sessionManager.createSession('Billing Inquiry');
const technicalSession = await sessionManager.createSession('Technical Support');
const salesSession = await sessionManager.createSession('Sales Question');
// Each session maintains its own conversation history
// User can switch between sessions without losing context
Session recovery
Retrieve previous conversations when a user returns:
// List all sessions for the user
const { sessions } = await sessionManager.listSessions();
// Display session list in UI
sessions.forEach(session => {
console.log(`${session.title} - Last updated: ${session.updatedAt}`);
});
// User selects a session to continue
const selectedSession = sessions[0];
const details = await sessionManager.getSessionDetails(selectedSession.id);
// Display message history
details.messages.forEach(msg => {
console.log(`${msg.isBotReply ? 'Bot' : 'User'}: ${msg.message}`);
});
Session cleanup
Periodically delete old or completed sessions:
// Get all sessions
const { sessions } = await sessionManager.listSessions(100, 0);
// Filter old sessions (older than 30 days)
const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
const oldSessions = sessions.filter(s => new Date(s.createdAt) < thirtyDaysAgo);
// Delete old sessions in batch
if (oldSessions.length > 0) {
const sessionIds = oldSessions.map(s => s.id);
await sessionManager.deleteManySessions(sessionIds);
console.log(`Deleted ${oldSessions.length} old sessions`);
}
Quick start with starter session
For simple use cases, use the auto-created starter session:
// Get or create the default starter session
const starterSession = await sessionManager.getStarterSession('my-agent-slug');
// Start chatting immediately without creating a new session
console.log('Ready to chat in session:', starterSession.id);
Best practices
Use starter session for simple cases β If you only need one conversation per user, use
getOrCreateUserStartTodoChatSessionto skip manual session creation.Organize sessions by purpose β Create separate sessions for different topics or user intents to keep conversations focused.
Implement pagination β When listing sessions, use
limitandoffsetto handle large numbers of sessions efficiently.Clean up old sessions β Periodically delete archived or completed sessions to keep the user's session list manageable.
Store session IDs β Keep track of important session IDs in your UI state or local storage for quick access.
Handle session not found errors β Always check if a session exists before trying to fetch its details.
Batch delete when possible β Use
deleteManyTodoChatSessioninstead of deleting one at a time for better performance.Set meaningful titles β Use descriptive session titles so users can identify conversations easily.