> ## Documentation Index
> Fetch the complete documentation index at: https://docs.thesys.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# UI state management

> Manage the UI state of the chat application using useThreadManager and useThreadListManager

Once you have the basic setup ready, users would expect their conversations to be saved upon refresh. This guide explains how to configure the `useThreadManager` and `useThreadListManager` hooks with your app's persistence logic.

<Tip>
  Import `useThreadManager` and `useThreadListManager` from `@thesysai/genui-sdk` package.
  They are wrapper around the `@crayonai/react-core` package with C1 specific logic.
</Tip>

## `useThreadManager`

A **Thread** is a single conversation session, maintaining its own history and context. The `ThreadManager`, obtained via the `useThreadManager` hook, controls its state and actions.

Key configurations:

<ResponseField name="threadListManager" type="ThreadListManager">
  The `ThreadListManager` object. For more information on how to get this object, see [useThreadListManager](#usethreadlistmanager).
</ResponseField>

<ResponseField name="loadThread" type="function">
  Load all messages for a specific thread.

  <Expandable title="Type Definition">
    <ResponseField name="threadId" type="string" pre={["Args"]}>
      The id of the thread.
    </ResponseField>

    <ResponseField name="messages" type="Message[]" pre={["Returns"]}>
      A list of messages in the current thread.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="onUpdateMessage" type="function">
  Save message updates (e.g., after a form submission).

  <Expandable title="Type Definition">
    <ResponseField name="props" type="{ message: Message }" pre={["Args"]}>
      Props object containing the message object that has been updated.
    </ResponseField>

    <ResponseField name="none" type="Promise<void>" pre={["Returns"]}>
      Returns nothing.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="apiUrl" type="string">
  A backend endpoint (e.g., `"/api/chat"`). Thesys GenUI SDK does a POST request to this endpoint with the following three arguments in the request body. If you need to pass additional arguments, use the `processMessage` function.
  Provide either `processMessage` or `apiUrl`.

  <Expandable title="Request Body">
    <ResponseField name="threadId" type="string" pre={["Args"]}>
      The id of the thread.
    </ResponseField>

    <ResponseField name="prompt" type="string" pre={["Args"]}>
      The latest user message in openai format.
    </ResponseField>

    <ResponseField name="responseId" type="string" pre={["Args"]}>
      Unique ID for the assistant's response.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="processMessage" type="function">
  A custom function for more control over sending messages and receiving AI responses. Provide either `processMessage` or `apiUrl`.

  <Expandable title="Type Definition">
    A param object containing the following properties:

    <ResponseField name="threadId" type="string" pre={["Args"]}>
      Current thread ID.
    </ResponseField>

    <ResponseField name="messages" type="Message[]" pre={["Args"]}>
      Conversation history (OpenAI format).
    </ResponseField>

    <ResponseField name="responseId" type="string" pre={["Args"]}>
      Unique ID for the assistant's response.
    </ResponseField>

    <ResponseField name="abortController" type="AbortController" pre={["Args"]}>
      For request cancellation.
    </ResponseField>

    <ResponseField name="Promise<Response>" type="Promise<Response>" pre={["Returns"]}>
      A promise that resolves with the Response object from your backend.
    </ResponseField>
  </Expandable>

  The `useThreadManager` hook uses the `Response` object from this function to handle streaming updates to the UI.
  <Tip>Application backend must use the `responseId` to set the final assistant's response message ID, as it's used for future updates to that message. </Tip>
</ResponseField>

## `useThreadListManager`

The **Thread List** displays multiple conversation threads, typically in a sidebar. The `ThreadListManager`, from the `useThreadListManager` hook, manages this list.

Key configurations:

<ResponseField name="fetchThreadList" type="function">
  Fetch all thread list.

  <Expandable title="Type Definition">
    <ResponseField name="threadList" type="Thread[]" pre={["Returns"]}>
      An array of thread objects.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="createThread" type="function">
  Create a new thread when the user sends the first message.

  <Expandable title="Type Definition">
    <ResponseField name="firstMessage" type="UserMessage" pre={["Args"]}>
      The initial user message that triggers thread creation.
    </ResponseField>

    <ResponseField name="thread" type="Thread" pre={["Returns"]}>
      The newly created thread.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="deleteThread" type="function">
  Delete a specific thread.

  <Expandable title="Type Definition">
    <ResponseField name="id" type="string" pre={["Args"]}>
      The ID of the thread to delete.
    </ResponseField>

    <ResponseField name="none" type="Promise<void>" pre={["Returns"]}>
      Returns nothing.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="updateThread" type="function">
  Update a thread's metadata, like its title.

  <Expandable title="Type Definition">
    <ResponseField name="updated" type="Thread" pre={["Args"]}>
      The updated thread object.
    </ResponseField>

    <ResponseField name="none" type="Promise<void>" pre={["Returns"]}>
      Returns nothing.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="onSelectThread" type="function">
  UI Callback function: called when a user selects a thread from the list.

  <Expandable title="Type Definition">
    <ResponseField name="threadId" type="string" pre={["Args"]}>
      The ID of the selected thread.
    </ResponseField>

    <ResponseField name="none" type="void" pre={["Returns"]}>
      Returns nothing.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="onSwitchToNew" type="function">
  UI Callback function: called to prepare for a new conversation.

  <Expandable title="Type Definition">
    <ResponseField name="" pre={["Args"]}>
      No arguments are required.
    </ResponseField>

    <ResponseField name="none" type="void" pre={["Returns"]}>
      Returns nothing.
    </ResponseField>
  </Expandable>
</ResponseField>

By configuring these hooks with your service functions, you integrate your application's data operations (like saving to or loading from the database) to enable persistent chat experiences.

For a detailed walkthrough of implementing service functions with a Firebase backend, see:

* [Example: Using Firebase](/guides/conversational/persistence)
