Skip to content

issue: Multiple Tool Calling with UserValves fails #15569

Open
@SZegotaM

Description

@SZegotaM

Check Existing Issues

  • I have searched the existing issues and discussions.
  • I am using the latest version of Open WebUI.

Installation Method

Docker

Open WebUI Version

0.6.15

Ollama Version (if applicable)

No response

Operating System

macOS

Browser (if applicable)

Safari

Confirmation

  • I have read and followed all instructions in README.md.
  • I am using the latest version of both Open WebUI and Ollama.
  • I have included the browser console logs.
  • I have included the Docker container logs.
  • I have provided every relevant configuration, setting, and environment variable used in my setup.
  • I have clearly listed every relevant configuration, custom setting, environment variable, and command-line option that influences my setup (such as Docker Compose overrides, .env values, browser settings, authentication configurations, etc).
  • I have documented step-by-step reproduction instructions that are precise, sequential, and leave nothing to interpretation. My steps:
  • Start with the initial platform/version/OS and dependencies used,
  • Specify exact install/launch/configure commands,
  • List URLs visited, user input (incl. example values/emails/passwords if needed),
  • Describe all options and toggles enabled or changed,
  • Include any files or environmental changes,
  • Identify the expected and actual result at each stage,
  • Ensure any reasonably skilled user can follow and hit the same issue.

Expected Behavior

When using two tools each with their own UserValves, I would expect both tool calls to use their respective user valves.

Actual Behavior

When using two tools in a chat, each with their own UserValves, the following error will appear when the second tool call is done:

"'UserValves' object has no attribute "XXX"

Steps to Reproduce

  1. Start with a clean open web ui instance
  2. Add two tools with different User Valves.
  3. Set the UserValves values via the Open Web UI.
  4. Try to call these two tools in one chat with a model (GPT 4.1, native tool calling).
  5. Depending on the order of how the tools are added into the chat, one of the tools will fail to load the UserValves attributes.

Example Tool 1:

import html
import json
import re
from typing import Any, Awaitable, Callable, Dict, List, Optional
import requests
from pydantic import BaseModel, Field, validator
from typing import Literal

class Tools:
class Valves(BaseModel):

    test_valve: int = Field(
        default=4, description="A valve controlling a numberical value"
    )
    choice_option: Literal["choiceA", "choiceB"] = Field(
        default="choiceA",
        description="An example of a multi choice valve",
    )
    priority: int = Field(
        default=0,
        description="Priority level for the filter operations. Lower values are passed through first",
    )
    pass

class UserValves(BaseModel):
    test_user_valve: str = Field(
        default=False,
        description="Test valve",
    )
    pass

def __init__(self):
    self.valves = self.Valves()
    pass

def inlet(self, __user__: dict):
    return __user__["valves"].test_user_valve

Example Tool 2:

import html
import json
import re
from typing import Any, Awaitable, Callable, Dict, List, Optional
import requests
from pydantic import BaseModel, Field, validator
from typing import Literal

class Tools:
class Valves(BaseModel):

    test_valve: int = Field(
        default=4, description="A valve controlling a numberical value"
    )
    choice_option: Literal["choiceA", "choiceB"] = Field(
        default="choiceA",
        description="An example of a multi choice valve",
    )
    priority: int = Field(
        default=0,
        description="Priority level for the filter operations. Lower values are passed through first",
    )
    pass

class UserValves(BaseModel):
    test_user_valve2: str = Field(
        default=False,
        description="Test valve",
    )
    pass

def __init__(self):
    self.valves = self.Valves()
    pass

async def inlet2(self, __user__: dict):
    return __user__["valves"].test_user_valve2

Logs & Screenshots

Image

Additional Information

No response

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions