Skip to main content

Backend-Controlled API Flow


Backend-Controlled, UI-Compatible API Flow

warning

This tutorial is a community contribution and is not supported by the Open WebUI team. It serves only as a demonstration on how to customize Open WebUI for your specific use case. Want to contribute? Check out the contributing tutorial.

This tutorial demonstrates how to implement server-side orchestration of Open WebUI conversations while ensuring that assistant replies appear properly in the frontend UI. This approach requires zero frontend involvement and allows complete backend control over the chat flow. This tutorial has been verified to work with Open WebUI version v0.6.15. Future versions may introduce changes in behavior or API structure.

Prerequisites

Before following this tutorial, ensure you have:

  • A running Open WebUI instance
  • Valid API authentication token
  • Access to the Open WebUI backend APIs
  • Basic understanding of REST APIs and JSON
  • Command-line tools: curl, jq (optional for JSON parsing)

Overview

This tutorial describes a comprehensive 6-step process that enables server-side orchestration of Open WebUI conversations while ensuring that assistant replies appear properly in the frontend UI.

Process Flow

The essential steps are:

  1. Create a new chat with user and assistant messages — Initialize the conversation with the user's input and an empty assistant placeholder
  2. Trigger the assistant completion — Generate the actual AI response (with optional knowledge integration)
  3. Wait for response completion — Monitor the assistant response until fully generated
  4. Fetch and process the final chat — Retrieve and parse the completed conversation

This enables server-side orchestration while still making replies show up in the frontend UI exactly as if they were generated through normal user interaction.

Important Concepts

Message IDs Are Caller-Generated

All message IDs (user-msg-id, assistant-msg-id) must be generated by the caller as valid UUIDs before making API calls. Open WebUI does not assign message IDs for you. Use any UUID v4 generator to create them.

Example (bash):

USER_MSG_ID=$(uuidgen || python3 -c "import uuid; print(uuid.uuid4())")
ASSISTANT_MSG_ID=$(uuidgen || python3 -c "import uuid; print(uuid.uuid4())")

The childrenIds Field

The Open WebUI frontend renders messages as a tree structure. Each message must include a childrenIds array that lists the IDs of its direct child messages. Without this field, the frontend cannot walk the message tree and messages will not render, even if they exist in the database.

  • A user message must list its assistant reply IDs in childrenIds
  • An assistant message typically has childrenIds: [] (empty) unless there are follow-up messages

The currentId Field

The history object must use currentId (camelCase, not current_id). This tells the frontend which message is at the end of the active conversation thread.

Implementation Guide

Critical Step: Enrich Chat Response with Assistant Message

The assistant message needs to exist in the chat data as a critical prerequisite before triggering the completion. This step is essential because the Open WebUI frontend expects assistant messages to exist in a specific structure.

The assistant message must appear in both locations:

  • chat.messages[] — The main message array (used for legacy compatibility)
  • chat.history.messages[<assistantId>] — The indexed message history (used by the frontend to render the tree)

Expected structure of the assistant message:

{
  "id": "<uuid>",
  "role": "assistant",
  "content": "",
  "parentId": "<user-msg-id>",
  "childrenIds": [],
  "model": "gpt-4o",
  "modelName": "gpt-4o",
  "modelIdx": 0,
  "done": false,
  "timestamp": 1720000001
}

Without this enrichment, the assistant's response will not appear in the frontend interface, even if the completion is successful.

Step-by-Step Implementation

Step 1: Create Chat with User and Assistant Messages

This creates the chat with both the user message and an empty assistant placeholder in a single request. The response returns a chatId (in the id field) that will be used in subsequent requests.

tip

You can combine chat creation and assistant enrichment into this single step. The key is to include both the user message and an empty assistant message in the initial payload, with proper parentId, childrenIds, and currentId fields.

USER_MSG_ID=$(uuidgen || python3 -c "import uuid; print(uuid.uuid4())")
ASSISTANT_MSG_ID=$(uuidgen || python3 -c "import uuid; print(uuid.uuid4())")
TIMESTAMP=$(date +%s)

curl -X POST https://<host>/api/v1/chats/new \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "chat": {
      "title": "New Chat",
      "models": ["gpt-4o"],
      "messages": [
        {
          "id": "'"$USER_MSG_ID"'",
          "role": "user",
          "content": "Hi, what is the capital of France?",
          "timestamp": '"$TIMESTAMP"',
          "models": ["gpt-4o"],
          "childrenIds": ["'"$ASSISTANT_MSG_ID"'"]
        },
        {
          "id": "'"$ASSISTANT_MSG_ID"'",
          "role": "assistant",
          "content": "",
          "parentId": "'"$USER_MSG_ID"'",
          "childrenIds": [],
          "model": "gpt-4o",
          "modelName": "gpt-4o",
          "modelIdx": 0,
          "done": false,
          "timestamp": '"$((TIMESTAMP + 1))"'
        }
      ],
      "history": {
        "currentId": "'"$ASSISTANT_MSG_ID"'",
        "messages": {
          "'"$USER_MSG_ID"'": {
            "id": "'"$USER_MSG_ID"'",
            "role": "user",
            "content": "Hi, what is the capital of France?",
            "timestamp": '"$TIMESTAMP"',
            "models": ["gpt-4o"],
            "childrenIds": ["'"$ASSISTANT_MSG_ID"'"]
          },
          "'"$ASSISTANT_MSG_ID"'": {
            "id": "'"$ASSISTANT_MSG_ID"'",
            "role": "assistant",
            "content": "",
            "parentId": "'"$USER_MSG_ID"'",
            "childrenIds": [],
            "model": "gpt-4o",
            "modelName": "gpt-4o",
            "modelIdx": 0,
            "done": false,
            "timestamp": '"$((TIMESTAMP + 1))"'
          }
        }
      }
    }
  }'

Save the id field from the response — this is your chatId for all subsequent steps.

note

The messages[] array at the top level is a flat list used for legacy compatibility. The history.messages{} object is the authoritative structure — it is a dictionary keyed by message ID that the frontend uses to build the conversation tree via parentId and childrenIds.

Step 2: Trigger Assistant Completion

Generate the actual AI response using the completion endpoint. Use the chatId from Step 1:

curl -X POST https://<host>/api/chat/completions \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": "<chatId>",
    "id": "'"$ASSISTANT_MSG_ID"'",
    "messages": [
      {
        "role": "user",
        "content": "Hi, what is the capital of France?"
      }
    ],
    "model": "gpt-4o",
    "stream": true,
    "background_tasks": {
      "title_generation": true,
      "tags_generation": false,
      "follow_up_generation": false
    },
    "features": {
      "code_interpreter": false,
      "web_search": false,
      "image_generation": false,
      "memory": false
    },
    "variables": {
      "{{USER_NAME}}": "",
      "{{USER_LANGUAGE}}": "en-US",
      "{{CURRENT_DATETIME}}": "2025-07-14T12:00:00Z",
      "{{CURRENT_TIMEZONE}}": "Europe"
    },
    "session_id": "<session-uuid>"
  }'
note

The session_id should be a unique UUID that you generate for this session. It helps maintain conversation context and is also used for WebSocket event routing if the frontend is open.

Step 2.1: Trigger Assistant Completion with Knowledge Integration (RAG)

For advanced use cases involving knowledge bases or document collections, include knowledge files in the completion request:

curl -X POST https://<host>/api/chat/completions \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": "<chatId>",
    "id": "'"$ASSISTANT_MSG_ID"'",
    "messages": [
      {
        "role": "user",
        "content": "Hi, what is the capital of France?"
      }
    ],
    "model": "gpt-4o",
    "stream": true,
    "files": [
      {
        "id": "knowledge-collection-id",
        "type": "collection",
        "status": "processed"
      }
    ],
    "background_tasks": {
      "title_generation": true,
      "tags_generation": false,
      "follow_up_generation": false
    },
    "features": {
      "code_interpreter": false,
      "web_search": false,
      "image_generation": false,
      "memory": false
    },
    "variables": {
      "{{USER_NAME}}": "",
      "{{USER_LANGUAGE}}": "en-US",
      "{{CURRENT_DATETIME}}": "2025-07-14T12:00:00Z",
      "{{CURRENT_TIMEZONE}}": "Europe"
    },
    "session_id": "<session-uuid>"
  }'

Step 3: Wait for Assistant Response Completion

Assistant responses can be handled in two ways depending on your implementation needs:

If using stream: true in the completion request, you can process the streamed response in real-time and wait for the stream to complete. This is the approach used by the OpenWebUI web interface and provides immediate feedback.

Option B: Polling Approach

For implementations that cannot handle streaming, poll the chat endpoint until the response is ready. Use a retry mechanism with exponential backoff:


# Poll every few seconds until assistant content is populated
while true; do
  response=$(curl -s -X GET https://<host>/api/v1/chats/<chatId> \
    -H "Authorization: Bearer <token>")

  # Check if assistant message has content (response is ready)
  assistant_content=$(echo "$response" | jq -r ".chat.history.messages[\"$ASSISTANT_MSG_ID\"].content // empty")
  if [ -n "$assistant_content" ]; then
    echo "Assistant response is ready!"
    echo "$assistant_content"
    break
  fi

  echo "Waiting for assistant response..."
  sleep 2
done

Step 4: Fetch Final Chat

Retrieve the completed conversation:

curl -X GET https://<host>/api/v1/chats/<chatId> \
  -H "Authorization: Bearer <token>"

Additional API Endpoints

Fetch Knowledge Collection

Retrieve knowledge base information for RAG integration:

curl -X GET https://<host>/api/v1/knowledge/<knowledge-id> \
  -H "Authorization: Bearer <token>"

Fetch Model Information

Get details about a specific model:

curl -X GET https://<host>/api/v1/models/model?id=<model-name> \
  -H "Authorization: Bearer <token>"

Send Additional Messages to an Existing Chat

For multi-turn conversations, you can add new messages to an existing chat. You must include the full updated message tree with proper parentId and childrenIds linkage:

NEW_USER_MSG_ID=$(uuidgen || python3 -c "import uuid; print(uuid.uuid4())")
NEW_ASSISTANT_MSG_ID=$(uuidgen || python3 -c "import uuid; print(uuid.uuid4())")

# First: update the chat to add the new user + assistant placeholder
# You need to link the previous assistant message to the new user message via childrenIds
curl -X POST https://<host>/api/v1/chats/<chatId> \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "chat": {
      "history": {
        "currentId": "'"$NEW_ASSISTANT_MSG_ID"'",
        "messages": {
          "'"$ASSISTANT_MSG_ID"'": {
            "childrenIds": ["'"$NEW_USER_MSG_ID"'"]
          },
          "'"$NEW_USER_MSG_ID"'": {
            "id": "'"$NEW_USER_MSG_ID"'",
            "role": "user",
            "content": "Can you tell me more about Paris?",
            "parentId": "'"$ASSISTANT_MSG_ID"'",
            "childrenIds": ["'"$NEW_ASSISTANT_MSG_ID"'"],
            "timestamp": '"$(date +%s)"',
            "models": ["gpt-4o"]
          },
          "'"$NEW_ASSISTANT_MSG_ID"'": {
            "id": "'"$NEW_ASSISTANT_MSG_ID"'",
            "role": "assistant",
            "content": "",
            "parentId": "'"$NEW_USER_MSG_ID"'",
            "childrenIds": [],
            "model": "gpt-4o",
            "modelName": "gpt-4o",
            "modelIdx": 0,
            "done": false,
            "timestamp": '"$(($(date +%s) + 1))"'
          }
        }
      }
    }
  }'

# Then: trigger completion for the new assistant message (same as Step 2)
curl -X POST https://<host>/api/chat/completions \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "chat_id": "<chatId>",
    "id": "'"$NEW_ASSISTANT_MSG_ID"'",
    "messages": [
      { "role": "user", "content": "Hi, what is the capital of France?" },
      { "role": "assistant", "content": "The capital of France is Paris." },
      { "role": "user", "content": "Can you tell me more about Paris?" }
    ],
    "model": "gpt-4o",
    "stream": true,
    "session_id": "<session-uuid>"
  }'
note

When updating an existing chat via POST /api/v1/chats/<chatId>, the payload is merged with the existing chat data. You only need to include the fields you are changing. For history.messages, you can pass partial updates — existing messages that are not included in the update will be preserved.

Response Processing

Parsing Assistant Responses

Assistant responses may be wrapped in markdown code blocks. Here's how to clean them:


# Example raw response from assistant
raw_response='```json
{
  "result": "The capital of France is Paris.",
  "confidence": 0.99
}
```'

# Clean the response (remove markdown wrappers)
cleaned_response=$(echo "$raw_response" | sed 's/^```json//' | sed 's/```$//' | sed 's/^[[:space:]]*//' | sed 's/[[:space:]]*$//')

echo "$cleaned_response" | jq '.'

This cleaning process handles:

  • Removal of ````json` prefix
  • Removal of ```` suffix
  • Trimming whitespace
  • JSON validation

API Reference

DTO Structures

Chat DTO (Complete Structure)

{
  "id": "chat-uuid-12345",
  "title": "New Chat",
  "models": ["gpt-4o"],
  "files": [],
  "tags": [],
  "params": {
    "temperature": 0.7,
    "max_tokens": 1000
  },
  "timestamp": 1720000000,
  "messages": [
    {
      "id": "user-msg-id",
      "role": "user",
      "content": "Hi, what is the capital of France?",
      "timestamp": 1720000000,
      "models": ["gpt-4o"],
      "childrenIds": ["assistant-msg-id"]
    },
    {
      "id": "assistant-msg-id",
      "role": "assistant",
      "content": "",
      "parentId": "user-msg-id",
      "childrenIds": [],
      "model": "gpt-4o",
      "modelName": "gpt-4o",
      "modelIdx": 0,
      "done": false,
      "timestamp": 1720000001
    }
  ],
  "history": {
    "currentId": "assistant-msg-id",
    "messages": {
      "user-msg-id": {
        "id": "user-msg-id",
        "role": "user",
        "content": "Hi, what is the capital of France?",
        "timestamp": 1720000000,
        "models": ["gpt-4o"],
        "childrenIds": ["assistant-msg-id"]
      },
      "assistant-msg-id": {
        "id": "assistant-msg-id",
        "role": "assistant",
        "content": "",
        "parentId": "user-msg-id",
        "childrenIds": [],
        "model": "gpt-4o",
        "modelName": "gpt-4o",
        "modelIdx": 0,
        "done": false,
        "timestamp": 1720000001
      }
    }
  },
  "currentId": "assistant-msg-id"
}

ChatCompletionsRequest DTO

{
  "chat_id": "chat-uuid-12345",
  "id": "assistant-msg-id",
  "messages": [
    {
      "role": "user",
      "content": "Hi, what is the capital of France?"
    }
  ],
  "model": "gpt-4o",
  "stream": true,
  "background_tasks": {
    "title_generation": true,
    "tags_generation": false,
    "follow_up_generation": false
  },
  "features": {
    "code_interpreter": false,
    "web_search": false,
    "image_generation": false,
    "memory": false
  },
  "variables": {
    "{{USER_NAME}}": "",
    "{{USER_LANGUAGE}}": "en-US",
    "{{CURRENT_DATETIME}}": "2025-07-14T12:00:00Z",
    "{{CURRENT_TIMEZONE}}": "Europe"
  },
  "session_id": "session-uuid-67890",
  "filter_ids": [],
  "files": [
    {
      "id": "knowledge-collection-id",
      "type": "collection",
      "status": "processed"
    }
  ]
}

ChatCompletionMessage DTO

{
  "role": "user",
  "content": "Hi, what is the capital of France?"
}

History DTO

{
  "currentId": "assistant-msg-id",
  "messages": {
    "user-msg-id": {
      "id": "user-msg-id",
      "role": "user",
      "content": "Hi, what is the capital of France?",
      "timestamp": 1720000000,
      "models": ["gpt-4o"],
      "childrenIds": ["assistant-msg-id"]
    },
    "assistant-msg-id": {
      "id": "assistant-msg-id",
      "role": "assistant",
      "content": "The capital of France is Paris.",
      "parentId": "user-msg-id",
      "childrenIds": [],
      "model": "gpt-4o",
      "modelName": "gpt-4o",
      "modelIdx": 0,
      "timestamp": 1720000001
    }
  }
}

Message DTO (Complete Structure)

User message:

{
  "id": "user-msg-id",
  "role": "user",
  "content": "Hi, what is the capital of France?",
  "timestamp": 1720000000,
  "models": ["gpt-4o"],
  "childrenIds": ["assistant-msg-id"]
}

Assistant message:

{
  "id": "assistant-msg-id",
  "role": "assistant",
  "content": "The capital of France is Paris.",
  "parentId": "user-msg-id",
  "childrenIds": [],
  "model": "gpt-4o",
  "modelName": "gpt-4o",
  "modelIdx": 0,
  "done": true,
  "timestamp": 1720000001
}

Response Examples

Create Chat Response

{
  "id": "chat-uuid-12345",
  "user_id": "user-uuid",
  "title": "New Chat",
  "chat": {
    "title": "New Chat",
    "models": ["gpt-4o"],
    "messages": [
      {
        "id": "user-msg-id",
        "role": "user",
        "content": "Hi, what is the capital of France?",
        "timestamp": 1720000000,
        "models": ["gpt-4o"],
        "childrenIds": ["assistant-msg-id"]
      },
      {
        "id": "assistant-msg-id",
        "role": "assistant",
        "content": "",
        "parentId": "user-msg-id",
        "childrenIds": [],
        "model": "gpt-4o",
        "modelName": "gpt-4o",
        "modelIdx": 0,
        "done": false,
        "timestamp": 1720000001
      }
    ],
    "history": {
      "currentId": "assistant-msg-id",
      "messages": {
        "user-msg-id": {
          "id": "user-msg-id",
          "role": "user",
          "content": "Hi, what is the capital of France?",
          "timestamp": 1720000000,
          "models": ["gpt-4o"],
          "childrenIds": ["assistant-msg-id"]
        },
        "assistant-msg-id": {
          "id": "assistant-msg-id",
          "role": "assistant",
          "content": "",
          "parentId": "user-msg-id",
          "childrenIds": [],
          "model": "gpt-4o",
          "modelName": "gpt-4o",
          "modelIdx": 0,
          "done": false,
          "timestamp": 1720000001
        }
      }
    },
    "currentId": "assistant-msg-id"
  },
  "updated_at": 1720000000,
  "created_at": 1720000000
}

Final Chat Response (After Completion)

{
  "id": "chat-uuid-12345",
  "title": "Capital of France Discussion",
  "chat": {
    "models": ["gpt-4o"],
    "history": {
      "currentId": "assistant-msg-id",
      "messages": {
        "user-msg-id": {
          "id": "user-msg-id",
          "role": "user",
          "content": "Hi, what is the capital of France?",
          "timestamp": 1720000000,
          "models": ["gpt-4o"],
          "childrenIds": ["assistant-msg-id"]
        },
        "assistant-msg-id": {
          "id": "assistant-msg-id",
          "role": "assistant",
          "content": "The capital of France is Paris. Paris is not only the capital but also the most populous city in France, known for its iconic landmarks such as the Eiffel Tower, the Louvre Museum, and Notre-Dame Cathedral.",
          "parentId": "user-msg-id",
          "childrenIds": [],
          "model": "gpt-4o",
          "modelName": "gpt-4o",
          "modelIdx": 0,
          "done": true,
          "timestamp": 1720000001
        }
      }
    },
    "currentId": "assistant-msg-id"
  }
}

OWUIKnowledge DTO (Knowledge Collection)

{
  "id": "knowledge-collection-id",
  "type": "collection",
  "status": "processed",
  "name": "Geography Knowledge Base",
  "description": "Contains information about world geography and capitals",
  "created_at": 1720000000,
  "updated_at": 1720000001
}

Model Information Response

{
  "id": "gpt-4o",
  "name": "GPT-4 Optimized",
  "model": "gpt-4o",
  "base_model_id": "gpt-4o",
  "meta": {
    "description": "Most advanced GPT-4 model optimized for performance",
    "capabilities": ["text", "vision", "function_calling"],
    "context_length": 128000,
    "max_output_tokens": 4096
  },
  "params": {
    "temperature": 0.7,
    "top_p": 1.0,
    "frequency_penalty": 0.0,
    "presence_penalty": 0.0
  },
  "created_at": 1720000000,
  "updated_at": 1720000001
}

Field Reference Guide

Required vs Optional Fields

Chat Creation - Required Fields:

  • title — Chat title (string)
  • models — Array of model names (string[])
  • messages — Initial message array
  • history — Message tree with currentId and messages map

Chat Creation - Optional Fields:

  • files — Knowledge files for RAG (defaults to empty array)
  • tags — Chat tags (defaults to empty array)
  • params — Model parameters (defaults to empty object)

Message Structure - User Message:

  • Required: id, role, content, timestamp, models, childrenIds
  • Optional: parentId (for threading; omit for the first message in a chat)

Message Structure - Assistant Message:

  • Required: id, role, content, parentId, childrenIds, model, modelName, modelIdx, timestamp
  • Optional: done (boolean, defaults to false), additional metadata fields

ChatCompletionsRequest - Required Fields:

  • chat_id — Target chat ID
  • id — Assistant message ID
  • messages — Array of ChatCompletionMessage
  • model — Model identifier
  • session_id — Session identifier (caller-generated UUID)

ChatCompletionsRequest - Optional Fields:

  • stream — Enable streaming (defaults to false)
  • background_tasks — Control automatic tasks
  • features — Enable/disable features
  • variables — Template variables
  • filter_ids — Pipeline filters
  • files — Knowledge collections for RAG

Field Constraints

Timestamps:

  • Format: Unix timestamp in seconds (not milliseconds) for message timestamps in history.messages
  • The top-level chat timestamp field uses milliseconds
  • Example: 1720000000 (July 3, 2024)

UUIDs:

  • All ID fields (id, parentId, session_id) should use valid UUID v4 format
  • Example: 550e8400-e29b-41d4-a716-446655440000
  • IDs are generated by the caller, not assigned by the server

Model Names:

  • Must match available models in your Open WebUI instance
  • Common examples: gpt-4o, gpt-3.5-turbo, claude-3-sonnet

Session IDs:

  • Can be any unique string identifier
  • Recommendation: Use UUID format for consistency

Knowledge File Status:

  • Valid values: "processed", "processing", "error"
  • Only use "processed" files for completions

Important Notes

  • This workflow is compatible with Open WebUI + backend orchestration scenarios
  • Critical: Use currentId (camelCase) in the history object, not current_id (snake_case)
  • Critical: Include childrenIds on every message — the frontend uses this to build the message tree
  • No frontend code changes are required for this approach
  • The stream: true parameter allows for real-time response streaming if needed
  • outlet() filters run inline during /api/chat/completions when chat_id and id (message ID) are present in the request body. Pure API callers that omit these fields will have outlet silently skipped — see Filter Functions: Enabling Outlet for Pure API Callers for a workaround. The separate /api/chat/completed endpoint is deprecated and no longer needed
  • Background tasks like title generation can be controlled via the background_tasks object
  • Session IDs help maintain conversation context across requests
  • Knowledge Integration: Use the files array to include knowledge collections for RAG capabilities
  • Response Parsing: Handle JSON responses that may be wrapped in markdown code blocks
  • Error Handling: Implement proper retry mechanisms for network timeouts and server errors

Common Pitfalls

SymptomCauseFix
Chat created but messages don't appear in UIMissing childrenIds on messagesAdd childrenIds array linking parent → child messages
Chat shows "How can I help you today?"Using current_id instead of currentIdUse camelCase currentId in the history object
Completion works but response only appears as notificationAssistant message not in chat history before triggering completionInclude empty assistant placeholder in Step 1
Messages exist in DB but frontend shows empty chatMissing parentId or broken tree linkageEnsure every message has correct parentId and parent's childrenIds includes the child

Summary

Use the Open WebUI backend APIs to:

  1. Start a chat with messages — Create the conversation with user input and an empty assistant placeholder (including proper childrenIds and currentId)
  2. Trigger a reply — Generate the AI response (with optional knowledge integration)
  3. Monitor completion — Wait for the assistant response using streaming or polling
  4. Fetch the final chat — Retrieve and parse the completed conversation

Enhanced Capabilities:

  • RAG Integration — Include knowledge collections for context-aware responses
  • Asynchronous Processing — Handle long-running AI operations with streaming or polling
  • Response Parsing — Clean and validate JSON responses from the assistant
  • Session Management — Maintain conversation context across requests

This enables backend-controlled workflows that still appear properly in the Web UI frontend chat interface, providing seamless integration between programmatic control and user experience.

The key advantage of this approach is that it maintains full compatibility with the Open WebUI frontend while allowing complete backend orchestration of the conversation flow, including advanced features like knowledge integration and asynchronous response handling.

Testing

You can test your implementation by following the step-by-step CURL examples provided above. Make sure to replace placeholder values with your actual:

  • Host URL
  • Authentication token
  • Chat IDs (from the create chat response)
  • Message IDs (UUIDs you generate)
  • Model names (matching your configured models)
tip

Start with a simple user message and gradually add complexity like knowledge integration and advanced features once the basic flow is working.

This content is for informational purposes only and does not constitute a warranty, guarantee, or contractual commitment. Open WebUI is provided "as is." See your license for applicable terms.