How to Customize the System Prompt and Prompt Variables in AnythingLLM

You can customize AnythingLLM's system prompt globally via the /system/default-system-prompt REST endpoint or per-workspace through the openAiPrompt field, while dynamic variables like {user.name} and {date} are automatically expanded at runtime through the SystemPromptVariables model.

AnythingLLM is an open-source document management and LLM interaction platform that allows deep customization of AI behavior through system prompts. Understanding how to customize the system prompt and prompt variables in AnythingLLM enables you to tailor responses based on user context, workspace purpose, and temporal information without modifying the core codebase.

Understanding the System Prompt Architecture

Global Default System Prompt

AnythingLLM stores the global default system prompt in the SystemSettings model within server/models/systemSettings.js. Administrators retrieve and modify this value through the default_system_prompt setting. When no custom prompt is specified, the system falls back to a hard-coded sane default.

The REST endpoints in server/endpoints/system.js expose this functionality:

  • GET /system/default-system-prompt returns the current default and fallback prompts
  • POST /system/default-system-prompt allows administrators to update the global default

Per-Workspace Prompt Overrides

Individual workspaces can override the global default through the openAiPrompt field in the Workspace model (server/models/workspace.js). During workspace creation (lines 96-102), if a global default exists, it is copied into openAiPrompt; otherwise, the workspace receives the hard-coded defaultPrompt.

This design ensures that modifying the global default only affects new workspaces, preserving existing workspace configurations unless explicitly updated through the workspace settings UI or API.

How Prompt Variables Work

Built-in Variables

The SystemPromptVariables model in server/models/systemPromptVariables.js defines built-in variables under DEFAULT_VARIABLES. These include:

  • {time} - Current time in LTS format
  • {date} - Current date in LL format
  • {datetime} - Full date-time in LLLL format
  • {user.id} - ID of the current user (multi-user mode)
  • {user.name} - Username of the current user
  • {workspace.id} - Workspace identifier
  • {workspace.name} - Human-readable workspace name

Custom Variable Creation

Administrators can create custom variables through the System Prompt Variables UI or API. These are stored in the system_prompt_variables database table. Each variable has a key, value, description, and type (static or dynamic).

The Variable Expansion Engine

The expansion logic resides in SystemPromptVariables.expandSystemPromptVariables(). The algorithm:

  1. Identifies all {variable} patterns using regex /\{([^}]+)\}/g
  2. Looks up each key in the combined built-in and custom variables
  3. Resolves values by calling appropriate functions (system vars return static values, user/workspace vars fetch from database using provided IDs)
  4. Replaces placeholders with resolved values

This expansion occurs in chatPrompt() within server/utils/chats/index.js immediately before sending the request to the LLM provider.

Implementation Details and Code Flow

The chatPrompt Function

Located in server/utils/chats/index.js, the chatPrompt() function orchestrates prompt assembly:

// server/utils/chats/index.js
async function chatPrompt(workspace, user = null) {
  const { SystemSettings } = require("../../models/systemSettings");
  const basePrompt =
    workspace?.openAiPrompt ?? SystemSettings.saneDefaultSystemPrompt;
  return await SystemPromptVariables.expandSystemPromptVariables(
    basePrompt,
    user?.id,
    workspace?.id
  );
}

This function retrieves the base prompt from either the workspace's openAiPrompt or the global SystemSettings.saneDefaultSystemPrompt, then calls SystemPromptVariables.expandSystemPromptVariables() to substitute all {variable} placeholders with actual values.

REST API Endpoints

The backend exposes several endpoints for prompt management:

System-level endpoints (server/endpoints/system.js):

  • GET /system/default-system-prompt - Retrieves current and default prompts
  • POST /system/default-system-prompt - Updates global default (admin only)

Workspace endpoints:

  • PATCH /api/workspaces/:id - Updates workspace-specific openAiPrompt

Variable management endpoints:

  • GET /api/system-prompt-variables - Lists all variables
  • POST /api/system-prompt-variables - Creates custom variables
  • DELETE /api/system-prompt-variables/:key - Removes custom variables

Frontend Integration

The React frontend accesses these capabilities through frontend/src/models/system.js:

import System from '@/models/system';

// Load the current global prompt when the settings page mounts
useEffect(() => {
  System.fetchDefaultSystemPrompt().then(({ defaultSystemPrompt }) => {
    setPromptText(defaultSystemPrompt);
  });
}, []);

// Save the edited prompt
const savePrompt = async () => {
  const { success, message } = await System.updateDefaultSystemPrompt(promptText);
  if (success) toast.success('Prompt updated');
  else toast.error(message);
};

This model provides fetchDefaultSystemPrompt() to wrap the GET endpoint and updateDefaultSystemPrompt(prompt) to wrap the POST endpoint.

Practical Examples

Updating the Global System Prompt via API

To set a new default prompt for all future workspaces:

curl -X POST https://your-anything-llm.com/api/system/default-system-prompt \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer <ADMIN_TOKEN>" \
     -d '{"defaultSystemPrompt":"You are a helpful assistant. Today is {date}. Use the user name {user.name} when addressing them."}'

Setting a Workspace-Specific Prompt

To override the global default for a specific workspace:

curl -X PATCH https://your-anything-llm.com/api/workspaces/42 \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer <ADMIN_OR_MANAGER_TOKEN>" \
     -d '{"openAiPrompt":"You are a finance analyst for {workspace.name}. Answer queries concisely."}'

Now workspace #42 always uses that prompt, regardless of the global default.

Creating Custom Variables

To add a static company name variable:

curl -X POST https://your-anything-llm.com/api/system-prompt-variables \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer <ADMIN_TOKEN>" \
     -d '{
           "key":"company.name",
           "value":"Acme Corp",
           "description":"Static company name used in prompts",
           "type":"static"
         }'

You can then reference it in any prompt as {company.name} and it will be replaced with Acme Corp.

Frontend Usage in React

Integrating prompt management into a React component:

import System from '@/models/system';

// Load the current global prompt when the settings page mounts
useEffect(() => {
  System.fetchDefaultSystemPrompt().then(({ defaultSystemPrompt }) => {
    setPromptText(defaultSystemPrompt);
  });
}, []);

// Save the edited prompt
const savePrompt = async () => {
  const { success, message } = await System.updateDefaultSystemPrompt(promptText);
  if (success) toast.success('Prompt updated');
  else toast.error(message);
};

This mirrors the code in frontend/src/models/system.js (see lines 91-123).

Summary

  • Global defaults are stored in SystemSettings (default_system_prompt) and affect all new workspaces via the /system/default-system-prompt endpoint.
  • Workspace overrides use the openAiPrompt field in the Workspace model, allowing specific contexts to deviate from the global default.
  • Variable expansion is handled by SystemPromptVariables.expandSystemPromptVariables() in server/models/systemPromptVariables.js, supporting built-in variables like {date}, {user.name}, and {workspace.name}.
  • Custom variables can be created via the API or UI and stored in the system_prompt_variables table for static or dynamic values.
  • Frontend integration uses the System model in frontend/src/models/system.js to fetch and update prompts via REST endpoints.

Frequently Asked Questions

What is the difference between the global system prompt and a workspace system prompt?

The global system prompt is stored in SystemSettings and serves as the default for all newly created workspaces. A workspace system prompt, stored in the openAiPrompt field of the Workspace model, overrides the global default for that specific workspace only. Existing workspaces retain their prompts even if the global default changes later, ensuring stability for active projects.

Which built-in prompt variables are available in AnythingLLM?

AnythingLLM provides several built-in variables defined in server/models/systemPromptVariables.js: {time} for current time in LTS format, {date} for current date in LL format, {datetime} for full date-time in LLLL format, {user.id} and {user.name} for user context in multi-user mode, and {workspace.id} and {workspace.name} for workspace context. These are automatically expanded at runtime before sending to the LLM.

How do I create a custom prompt variable?

Custom variables can be created via the System Prompt Variables UI or by posting to the /api/system-prompt-variables endpoint with a JSON payload containing key, value, description, and type (static or dynamic). Once created, reference the variable in any prompt using curly braces, such as {company.name}, and it will be replaced with the stored value during the expansion phase handled by SystemPromptVariables.expandSystemPromptVariables().

Where in the codebase is the system prompt assembled before sending to the LLM?

The final prompt assembly occurs in server/utils/chats/index.js within the chatPrompt() function. This function retrieves the base prompt from either the workspace's openAiPrompt or the global SystemSettings.saneDefaultSystemPrompt, then calls SystemPromptVariables.expandSystemPromptVariables() to substitute all {variable} placeholders with actual values before passing the completed prompt to the LLM provider.

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 →