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:

  1. Authenticated with the API β€” Follow the Authentication & Setup guide to get your accessToken and workspaceId

  2. Configured your GraphQL client β€” Your Apollo Client must include the required authentication headers

  3. 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 response

  • limit (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 ID

  • searchQuery (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 sessions

Create 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:

Parameter

Type

Required

Description

title

string

No

Session title (max 200 characters)

todoId

number

Yes

The container ID from authentication

defaultBotId

number

No

Default agent ID for this session

createFromChatAsDataSourceId

number

No

Create session from a datasource

fromBotPromptId

number

No

Initialize session with a predefined prompt

chatCollectionId

number

No

Associate with a collection

uiLayout

string

No

UI layout preference ("DEFAULT" or "COMPACT")

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 update

  • data (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:

Parameter

Type

Required

Description

botId

number

Yes

The bot/agent ID

sessionId

number

No

Session ID (if session-specific)

model

string

No

LLM model name (e.g., "gpt-4", "claude-3")

temperature

number

No

Temperature setting (0-1, controls randomness)

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

  1. Use starter session for simple cases β€” If you only need one conversation per user, use getOrCreateUserStartTodoChatSession to skip manual session creation.

  2. Organize sessions by purpose β€” Create separate sessions for different topics or user intents to keep conversations focused.

  3. Implement pagination β€” When listing sessions, use limit and offset to handle large numbers of sessions efficiently.

  4. Clean up old sessions β€” Periodically delete archived or completed sessions to keep the user's session list manageable.

  5. Store session IDs β€” Keep track of important session IDs in your UI state or local storage for quick access.

  6. Handle session not found errors β€” Always check if a session exists before trying to fetch its details.

  7. Batch delete when possible β€” Use deleteManyTodoChatSession instead of deleting one at a time for better performance.

  8. Set meaningful titles β€” Use descriptive session titles so users can identify conversations easily.