How to Set Up Workspace Thread Management and Chat History in AnythingLLM

AnythingLLM uses a three-tier hierarchy of workspace → thread → chat to organize conversations, with dedicated middleware, Prisma models, and REST endpoints handling validation, CRUD operations, and history retrieval.

Setting up workspace thread management and chat history in AnythingLLM requires understanding how the Mintplex-Labs/anything-llm repository structures conversation data. The platform isolates discussions into workspaces (top-level containers), threads (sub-conversations), and individual chat messages, with each layer protected by specific middleware and database models.

Understanding the Workspace-Thread-Chat Hierarchy

AnythingLLM organizes conversations hierarchically to support multi-project deployments and isolated user sessions.

  • Workspace – A top-level container defined in the Workspace Prisma model, accessed via /workspace/:slug/... endpoints.
  • Thread – A sub-conversation within a workspace, stored in the workspace_threads table and managed through the WorkspaceThread model helper.
  • Chat – Individual message-response pairs persisted in the workspace_chats table, linked to both workspace and thread IDs.

Core Architecture and Key Files

Middleware Validation

Request validation happens in server/utils/middleware/validWorkspace.js. Two primary middleware functions protect thread-related routes:

  • validWorkspaceSlug – Validates the workspace slug, loads the workspace into res.locals.workspace, and handles multi-user isolation.
  • validWorkspaceAndThreadSlug – Extends workspace validation to also load the thread into res.locals.thread using the WorkspaceThread helper.

Thread Management Models

The server/models/workspaceThread.js file provides the WorkspaceThread class, which wraps Prisma operations for the workspace_threads table. It exposes methods for creation, updates, deletion, and automatic renaming based on message content via autoRenameThread.

Chat Storage and Retrieval

Chat persistence relies on two files:

Setting Up Thread Management

Creating New Threads

To programmatically create a thread, send a POST request to the thread creation endpoint. The server uses validWorkspaceSlug middleware to validate access, then invokes WorkspaceThread.new to insert a record into workspace_threads.

curl -X POST "https://your-instance.com/workspace/my-workspace/thread/new" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <your-session-token>" \
  -d '{}'

The endpoint returns a JSON object containing the created thread and a success message.

Listing and Updating Threads

Retrieve all threads for a specific workspace using the list endpoint, which queries WorkspaceThread methods filtered by workspace and user ID in multi-user mode.

async function listThreads(workspaceSlug) {
  const res = await fetch(
    `https://your-instance.com/workspace/${workspaceSlug}/threads`,
    {
      method: "GET",
      headers: { Authorization: `Bearer ${token}` },
    }
  );
  const data = await res.json(); // { threads: [...] }
  return data.threads;
}

Update thread metadata (currently limited to the name field as defined in WorkspaceThread.writable) via the update endpoint:

curl -X POST "https://your-instance.com/workspace/my-workspace/thread/old-slug/update" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{"name":"New Thread Title"}'

Deleting Threads

Remove individual threads or perform bulk deletions using WorkspaceThread.delete. The DELETE endpoint requires both workspace and thread slugs, validated by validWorkspaceAndThreadSlug middleware.

Managing Chat History

Storing Chat Messages

When users send messages through POST /workspace/:slug/thread/:threadSlug/stream-chat, the streamChatWithWorkspace function streams the LLM response while simultaneously persisting the conversation via WorkspaceChats.new. This method stores the raw prompt, JSON-stringified LLM response, optional attachments, and the associated thread_id in the workspace_chats table.

Retrieving Thread History

Fetch historical messages for a specific thread using the chat history endpoint. The server executes WorkspaceChats.where filtered by workspaceId, user_id, and thread_id, then passes results through convertToChatHistory in server/utils/helpers/chat/responses.js to format them for the UI.

async function getChatHistory(workspaceSlug, threadSlug) {
  const res = await fetch(
    `https://your-instance.com/workspace/${workspaceSlug}/thread/${threadSlug}/chats`,
    {
      method: "GET",
      headers: { Authorization: `Bearer ${token}` },
    }
  );
  const { history } = await res.json(); // array of formatted chat objects
  return history;
}

Disabling Chat History Access

For privacy compliance or administrative control, set the environment variable DISABLE_VIEW_CHAT_HISTORY to any value in your server configuration or Docker environment. This activates the chatHistoryViewable middleware in server/utils/middleware/chatHistoryViewable.js, which rejects all history retrieval requests with HTTP 422 and the message "This feature has been disabled by the administrator."

DISABLE_VIEW_CHAT_HISTORY=true

Summary

  • Workspace thread management and chat history in AnythingLLM rely on a strict hierarchy: workspaces contain threads, which contain individual chat messages.
  • Validation middleware (validWorkspaceSlug, validWorkspaceAndThreadSlug) protects all thread-related routes by loading objects into res.locals.
  • CRUD operations use the WorkspaceThread helper (server/models/workspaceThread.js) for thread lifecycle management and WorkspaceChats (server/models/workspaceChats.js) for message persistence.
  • History retrieval flows through convertToChatHistory in server/utils/helpers/chat/responses.js to format database records for the UI.
  • Privacy controls allow administrators to disable history viewing entirely via the DISABLE_VIEW_CHAT_HISTORY environment variable and chatHistoryViewable middleware.

Frequently Asked Questions

What is the difference between a workspace and a thread in AnythingLLM?

A workspace is the top-level container that groups related conversations and configurations, while a thread is a sub-conversation within that workspace representing a specific topic or project. The Workspace model handles workspace-level settings, whereas the WorkspaceThread model in server/models/workspaceThread.js manages individual discussion threads linked to a workspace ID.

How does AnythingLLM handle chat history storage?

Chat history is stored in the workspace_chats table via the WorkspaceChats helper in server/models/workspaceChats.js. When a user sends a message, the streamChatWithWorkspace function calls WorkspaceChats.new to persist the raw prompt, JSON-stringified LLM response, optional attachments, and the associated thread_id while streaming the response to the client.

Can I disable chat history viewing for privacy compliance?

Yes, set the DISABLE_VIEW_CHAT_HISTORY environment variable to any value in your server configuration or Docker environment. This activates the chatHistoryViewable middleware in server/utils/middleware/chatHistoryViewable.js, which blocks all history retrieval requests with HTTP 422 and returns the message "This feature has been disabled by the administrator."

How do I programmatically create threads via the API?

Send a POST request to /workspace/:slug/thread/new with proper authorization headers. The endpoint uses the validWorkspaceSlug middleware to validate access, then invokes WorkspaceThread.new to insert a record into the workspace_threads table. The endpoint returns the created thread object and a success message, automatically handling multi-user isolation if enabled.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →