Skip to main content
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.

Special Arguments

When developping your own Tools, Functions (Filters, Pipes or Actions), Pipelines etc, you can use special arguments explore the full spectrum of what Open-WebUI has to offer.

This page aims to detail the type and structure of each special argument as well as provide an example.

body

A dict usually destined to go almost directly to the model. Although it is not strictly a special argument, it is included here for easier reference and because it contains itself some special arguments.

Example

{
  "stream": true,
  "model": "my-cool-model",
  # lowercase string with - separated words: this is the ID of the model
  "messages": [
    {
      "role": "user",
      "content": [
        {
          "type": "text",
          "text": "What is in this picture?"
        },
        {
          "type": "image_url",
          "image_url": {
            "url": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAdYAAAGcCAYAAABk2YF[REDACTED]"
            # Images are passed as base64 encoded data
          }
        }
      ]
    },
    {
      "role": "assistant",
      "content": "The image appears to be [REDACTED]"
    },
  ],
  "features": {
    "image_generation": false,
    "code_interpreter": false,
    "web_search": false
  },
  "stream_options": {
    "include_usage": true
  },
  "metadata": "[The exact same dict as __metadata__, present for Filters, removed before a Pipe sees it]",
  "files": "[The exact same list as __files__]"
}

__user__

A dict with user information.

Note that if the UserValves class is defined, its instance has to be accessed via __user__["valves"]. Otherwise, the valves keyvalue is missing entirely from __user__.

Example
{
  "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "email": "[email protected]",
  "name": "Patrick",
  "role": "user",
  # role can be either `user` or `admin`
  "valves": "[the UserValve instance]"
}

__metadata__

A dict with wide ranging information about the chat, model, files, etc.

Example
{
  "user_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "chat_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "message_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "session_id": "xxxxxxxxxxxxxxxxxxxx",
  "user_prompt": "What is in this picture?",
  # the user's most recent message, captured before any source citation wrap.
  # this is what the native tool call loop and Pipes should read.
  "system_prompt": "You are a helpful assistant.",
  # the chat's system message, captured at the same point.
  "sources": [],
  # resolved sources for this turn (e.g. file context).
  # Empty when no sources are attached.
  "tool_ids": null,
  # tool_ids is a list of str.
  "tool_servers": [],
  "files": "[Same as in body['files']]",
  # If no files are given, the files key exists in __metadata__ and its value is []
  "features": {
    "image_generation": false,
    "code_interpreter": false,
    "web_search": false
  },
  "variables": {
    "{{USER_NAME}}": "cheesy_username",
    "{{USER_LOCATION}}": "Unknown",
    "{{CURRENT_DATETIME}}": "2025-02-02 XX:XX:XX",
    "{{CURRENT_DATE}}": "2025-02-02",
    "{{CURRENT_TIME}}": "XX:XX:XX",
    "{{CURRENT_WEEKDAY}}": "Monday",
    "{{CURRENT_TIMEZONE}}": "Europe/Berlin",
    "{{USER_LANGUAGE}}": "en-US"
  },
  "model": "[The exact same dict as __model__]",
  "direct": false,
  "params": {
    "stream_delta_chunk_size": 1,
    "reasoning_tags": null,
    "compact_token_threshold": null,
    "function_calling": "native"
  }
}
Detecting Request Source

Nothing in the metadata names the caller. What distinguishes them is the chat context: a request from the web interface always carries a chat_id and a session_id, while a direct API call gets an empty chat_id and a null session_id unless the client sets them itself. Both keys are always present, so test their values rather than their presence:

async def inlet(self, body: dict, __metadata__: dict = None) -> dict:
    metadata = __metadata__ or {}

    if metadata.get("chat_id") and metadata.get("session_id"):
        # Request from a chat session
        pass
    else:
        # Direct API request
        pass
    return body
Reading the user's message before the wrap

When sources are attached, the chat-completions middleware wraps the user's most recent message with the default citation template. The wrap happens before a Pipe or pipe() call sees the body. It only fires when sources are attached. A Pipe that reads body["messages"][-1]["content"] directly will see the wrapped form.

__metadata__["user_prompt"] holds the user's message before the wrap fires. Native tool call loops and Pipes both read from it, so it's safe whether sources are attached or not. Use it for any Pipe that hands the user's turn to a downstream model.

async def pipe(self, body: dict, __metadata__: dict, __user__: dict) -> str:
    user_prompt = __metadata__.get("user_prompt") or ""
    system_prompt = __metadata__.get("system_prompt")

    messages = []
    if system_prompt:
        messages.append({"role": "system", "content": system_prompt})
    messages.append({"role": "user", "content": user_prompt})
    # pass messages to your downstream model

If your Pipe runs through a path that skips the standard preprocessing (direct API callers, some test fixtures), __metadata__ may be absent. In that case, scan body["messages"] for the last user message.

__model__

A dict with information about the model.

Example
{
  "id": "my-cool-model",
  "name": "My Cool Model",
  "object": "model",
  "created": 1746000000,
  "owned_by": "openai",
  # openai, ollama, anthropic, arena or unknown
  "info": {
      "id": "my-cool-model",
      "user_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "base_model_id": "gpt-5.6-sol",
      # this is the name of model that the model endpoint serves
      "name": "My Cool Model",
      "params": {
      "system": "You are my best assistant. You answer [REDACTED]",
      "function_calling": "native"
      # custom options appear here, for example "Top K"
      },
      "meta": {
      "profile_image_url": "/static/favicon.png",
      "description": "Description of my-cool-model",
      "capabilities": {
          "vision": true,
          "usage": true,
          "citations": true
      },
      "position": 17,
      "tags": [
          {
          "name": "for_friends"
          },
          {
          "name": "vision_enabled"
          }
      ],
      "suggestion_prompts": null
      },
      "access_control": {
      "read": {
          "group_ids": [],
          "user_ids": []
      },
      "write": {
          "group_ids": [],
          "user_ids": []
      }
      },
      "is_active": true,
      "updated_at": 1740000000,
      "created_at": 1740000000
  },
  "preset": true,
  "actions": [],
  "tags": [
      {
          "name": "for_friends"
      },
      {
          "name": "vision_enabled"
      }
  ]
}

__messages__

A list of the previous messages. Only Tools receive it; Pipes and Filters read the same list from body["messages"].

See the body["messages"] value above.

__chat_id__

The str of the chat_id, representing the unique identifier of the current chat/conversation.

Pipes, Tools and a Filter's inlet() receive it, for invocations that originate from a chat context, including:

  • Regular user messages
  • Internal task calls (title generation, query generation, tag generation, etc.)

A Filter's stream() and outlet() do not get it, and neither do Actions. Read body["chat_id"] there instead.

This allows stateful functions/pipes/manifolds to maintain per-chat state without fragmentation.

See also __metadata__["chat_id"] for accessing the same value via the metadata dict.

__session_id__

The str of the session_id.

See the __metadata__["session_id"] value above.

__message_id__

The str of the message_id.

See the __metadata__["message_id"] value above.

__event_emitter__

A Callable that delivers an event for the active chat turn through socket.io to any subscribed clients (the WebUI is the standard subscriber). The same message_id Open WebUI tracks for the active assistant turn is included automatically.

The most familiar event is the status pill:

await __event_emitter__({
    "type": "status",
    "data": {"description": "Working...", "done": False},
})

The type field isn't restricted to the rendered ones. Events with arbitrary type strings are forwarded through socket.io with the original type preserved. It's useful when a Pipe needs to send a control signal or a custom UI marker that a frontend listener (e.g. a userscript) reacts to without rendering as content in the streamed message:

await __event_emitter__({
    "type": "my-pipe:phase-changed",
    "data": {"phase": "reasoning"},
})

status events render natively in the chat, so use them for progress the user should see. Custom event types are for frontend listeners that react to events during a Pipe run without changing the visible message.

__event_call__

A Callable that sends an event and waits for the browser to answer it. Available to Pipes, Filters, Tools and Actions alike.

__files__

A list of files sent via the chat. Note that images are not considered files and are sent directly to the model as part of the body["messages"] list.

The actual binary of the file is not part of the arguments for performance reason, but the file remain nonetheless accessible by its path if needed. For example using docker the python syntax for the path could be:

from pathlib import Path

# `path` is a filesystem path under local storage; on S3, GCS or Azure it is a bucket URL
the_file = Path(__files__[0]["file"]["path"])
assert the_file.exists()

Note that the same files dict can also be accessed via __metadata__["files"] (and its value is [] if no files are sent) or via body["files"] (but the files key is missing entirely from body if no files are sent).

Example

[
  {
    "type": "file",
    "file": {
      "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "filename": "Napoleon - Wikipedia.pdf",
      "path": "/app/backend/data/uploads/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx_Napoleon - Wikipedia.pdf",
      "user_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "hash": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
      "data": {
        "content": "Napoleon - Wikipedia\n\n\nNapoleon I\n\nThe Emperor Napoleon in His Study at the\nTuileries, 1812\n\nEmperor of the French\n\n1st reign 18 May 1804 – 6 April 1814\n\nSuccessor Louis XVIII[a]\n\n2nd reign 20 March 1815 – 22 June 1815\n\nSuccessor Louis XVIII[a]\n\nFirst Consul of the French Republic\n\nIn office\n13 December 1799 – 18 May 1804\n\nBorn Napoleone Buonaparte\n15 August 1769\nAjaccio, Corsica, Kingdom of\nFrance\n\nDied 5 May 1821 (aged 51)\nLongwood, Saint Helena\n\nBurial 15 December 1840\nLes Invalides, Paris\n\nNapoleon\nNapoleon Bonaparte[b] (born Napoleone\nBuonaparte;[1][c] 15 August 1769 – 5 May 1821), later\nknown [REDACTED]",
        # The content value is the output of the document parser, the above example is with Tika as a document parser
      },
      "meta": {
        "name": "Napoleon - Wikipedia.pdf",
        "content_type": "application/pdf",
        "size": 10486578,
        # in bytes, here about 10Mb
        "data": {},
        "collection_name": "file-96xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
        # always begins by 'file'
      },
      "created_at": 1740000000,
      "updated_at": 1740000000
    },
    "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "url": "/api/v1/files/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "name": "Napoleon - Wikipedia.pdf",
    "collection_name": "file-96xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    "status": "uploaded",
    "size": 10486578,
    "error": "",
    "itemId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    # itemId is not the same as file["id"]
  }
]

__request__

An instance of fastapi.Request. You can read more in the migration page or in fastapi's documentation.

__task__

A str for the type of task. Its value is just a shorthand for __metadata__["task"] if present, otherwise None. Only Pipes receive it; a Filter or Tool that declares it never gets the value, even during a real task call.

Possible values

[
    "title_generation",
    "follow_up_generation",
    "tags_generation",
    "emoji_generation",
    "query_generation",
    "image_prompt_generation",
    "autocomplete_generation",
    "function_calling",
    "moa_response_generation",
    "context_compaction",
    "memory_review"
]

__task_body__

A dict containing the body needed to accomplish a given __task__. Its value is just a shorthand for __metadata__["task_body"] if present, otherwise None.

Its structure is the same as body above, with modifications like using the appropriate model and system message etc.

__tools__

A dict keyed by tool function name, injected for Pipes only. Each value carries tool_id, callable (the awaitable that runs the tool) and spec (the OpenAI function spec sent to the model). Entries for local Python tools also carry metadata, while builtin and external tool-server entries instead carry a type of builtin or external.

The dict is assembled by get_tools() in tools.py.

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.