I have searched the existing issues and discussions.
Problem Description
Im managing a openwebui for my company, i was request to track spending by each department, at this time im able to inject in the request headers with only the user ID through the __user__ variable.
To keep things more anonymized i would like to track only the total department usage, since im using Oauth users get synced with their own Group from the identity manager so the data is already there, its just missing from the __user__ variable when making a function.
Desired Solution you'd like
__user__ should contain a list of the user groups, since the user can be part of more than one group
Alternatives Considered
No response
Additional Context
Code i currently use to inject the user id in the request headers
from pydantic import BaseModel, Field
from typing import Optional
class Filter:
class Valves(BaseModel):
enable_tracking: bool = Field(
default=True, description="Enable user tracking for OpenRouter"
)
def __init__(self):
self.valves = self.Valves()
def inlet(self, body: dict, __user__: Optional[dict] = None) -> dict:
if not self.valves.enable_tracking:
return body
# Use actual user info if available, otherwise use fallback
user_id = f"openwebui_{__user__['id']}"
# Add user parameter for OpenRouter tracking
body["user"] = user_id
print(f"OpenRouter tracking - User: {user_id}")
return body
Originally created by @AlexZorzi on GitHub (Sep 9, 2025).
Original GitHub issue: https://github.com/open-webui/open-webui/issues/17308
### Check Existing Issues
- [x] I have searched the existing issues and discussions.
### Problem Description
Im managing a openwebui for my company, i was request to track spending by each department, at this time im able to inject in the request headers with only the user ID through the `__user__` variable.
To keep things more anonymized i would like to track only the total department usage, since im using Oauth users get synced with their own Group from the identity manager so the data is already there, its just missing from the `__user__` variable when making a function.
### Desired Solution you'd like
`__user__` should contain a list of the user groups, since the user can be part of more than one group
### Alternatives Considered
_No response_
### Additional Context
Code i currently use to inject the user id in the request headers
```
from pydantic import BaseModel, Field
from typing import Optional
class Filter:
class Valves(BaseModel):
enable_tracking: bool = Field(
default=True, description="Enable user tracking for OpenRouter"
)
def __init__(self):
self.valves = self.Valves()
def inlet(self, body: dict, __user__: Optional[dict] = None) -> dict:
if not self.valves.enable_tracking:
return body
# Use actual user info if available, otherwise use fallback
user_id = f"openwebui_{__user__['id']}"
# Add user parameter for OpenRouter tracking
body["user"] = user_id
print(f"OpenRouter tracking - User: {user_id}")
return body
```
from open_webui.models.groups import Groups
class Pipe:
async def pipe(
self,
body: dict,
messages: dict | None = None,
__user__: Optional[dict] = None,
**kwargs,
) -> tuple:
user_id = (__user__ or {}).get(“id”)
if not user_id:
return {"groups": [], "note": "No user in context”}
# Member-of groups
member_groups = Groups.get_groups_by_member_id(user_id)
print(f"User {user_name} is member of these groups {[g.name for g in member_groups]}")
<!-- gh-comment-id:3312085044 -->
@hemzet commented on GitHub (Sep 19, 2025):
@AlexZorzi
Workaround:
```
from open_webui.models.groups import Groups
class Pipe:
async def pipe(
self,
body: dict,
messages: dict | None = None,
__user__: Optional[dict] = None,
**kwargs,
) -> tuple:
user_id = (__user__ or {}).get(“id”)
if not user_id:
return {"groups": [], "note": "No user in context”}
# Member-of groups
member_groups = Groups.get_groups_by_member_id(user_id)
print(f"User {user_name} is member of these groups {[g.name for g in member_groups]}")
```
Hi @hemzet , can you pls explain how to use this code and where to put it in, i have also done a workaround for bring groups to frontend and modifyed the core which i dont like because its a pain when new updates released.
Would it be possible to make this a function or a pipe so you dont have to change the core directly?
<!-- gh-comment-id:3342391314 -->
@Schnubl commented on GitHub (Sep 28, 2025):
Hi @hemzet , can you pls explain how to use this code and where to put it in, i have also done a workaround for bring groups to frontend and modifyed the core which i dont like because its a pain when new updates released.
Would it be possible to make this a function or a pipe so you dont have to change the core directly?
@Schnubl
The snippet shows usage in a pipe function. No modification of core required. Just import the group model and use it.
<!-- gh-comment-id:3343865910 -->
@hemzet commented on GitHub (Sep 28, 2025):
@Schnubl
The snippet shows usage in a pipe function. No modification of core required. Just import the group model and use it.
thx for the fast response.
i tried to creat a new function pipe and paste the code into it.
When try to svae it i get an error = "id"
here is the code that i pasted into the new function:
"""
title: Bring Usergroup to Frontend
author: hezmet
author_url: https://github.com/hemzet
version: 0.1
"""
from open_webui.models.groups import Groups
class Pipe:
async def pipe(
self,
body: dict,
messages: dict | None = None,
__user__: Optional[dict] = None,
**kwargs,
) -> tuple:
user_id = (__user__ or {}).get(“id”)
if not user_id:
return {"groups": [], "note": "No user in context”}
# Member-of groups
member_groups = Groups.get_groups_by_member_id(user_id)
print(f"User {user_name} is member of these groups {[g.name for g in member_groups]}")
Did i misunderstand you?
<!-- gh-comment-id:3347774597 -->
@Schnubl commented on GitHub (Sep 29, 2025):
thx for the fast response.
i tried to creat a new function pipe and paste the code into it.
When try to svae it i get an error = "id"
here is the code that i pasted into the new function:
```
"""
title: Bring Usergroup to Frontend
author: hezmet
author_url: https://github.com/hemzet
version: 0.1
"""
from open_webui.models.groups import Groups
class Pipe:
async def pipe(
self,
body: dict,
messages: dict | None = None,
__user__: Optional[dict] = None,
**kwargs,
) -> tuple:
user_id = (__user__ or {}).get(“id”)
if not user_id:
return {"groups": [], "note": "No user in context”}
# Member-of groups
member_groups = Groups.get_groups_by_member_id(user_id)
print(f"User {user_name} is member of these groups {[g.name for g in member_groups]}")
```
Did i misunderstand you?
Well, the provided code was simply a snippet to showcase the lines you need to add to your function for accessing group data. It's not the full code of a working function.
<!-- gh-comment-id:3350707168 -->
@hemzet commented on GitHub (Sep 30, 2025):
Well, the provided code was simply a snippet to showcase the lines you need to add to your function for accessing group data. It's not the full code of a working function.
@Schnubl edit my Function to your needs, i provide a list of groups to track since my users have multiple groups and you can only send one to openrouter.
"""
title: OpenRouter User Tracking Filter
author: AlexZorzi
description: Automatically adds user parameter to API requests for OpenRouter usage tracking
version: 1.0
"""
from pydantic import BaseModel, Field
from typing import Optional, List
from open_webui.models.groups import Groups
class Filter:
class Valves(BaseModel):
enable_tracking: bool = Field(
default=True, description="Enable user tracking for OpenRouter"
)
trackable_groups: List[str] = Field(
default=[
"Backoffice",
"WEB",
"EDP",
"Fewo",
"Marketing",
"HR",
],
description="List of groups to track for department spending",
)
def __init__(self):
self.valves = self.Valves()
def inlet(self, body: dict, __user__: Optional[dict] = None) -> dict:
if not self.valves.enable_tracking:
return body
user_id = __user__.get("id") if __user__ else None
user_email = __user__.get("email") if __user__ else None
if not user_id:
print("No user ID available for tracking")
return body
# Get user groups
try:
member_groups = Groups.get_groups_by_member_id(user_id)
group_names = [g.name for g in member_groups]
print(f"User {user_id} is member of groups: {group_names}")
except Exception as e:
print(f"Error getting user groups: {e}")
group_names = []
# Find trackable group
trackable_group = None
for group_name in group_names:
if group_name in self.valves.trackable_groups:
trackable_group = group_name
break
# Create tracking identifier
if trackable_group:
user_tracking_id = f"{trackable_group}"
print(f"Tracking by department: {trackable_group}")
else:
# Fallback to user email if no trackable group found
user_tracking_id = f"{user_email}" if user_email else f"{user_id}"
print(
f"No trackable group found, using user identifier: {user_email or user_id}"
)
# Add user parameter for OpenRouter tracking
body["user"] = user_tracking_id
print(f"OpenRouter tracking - User: {user_tracking_id}")
return body
<!-- gh-comment-id:3350844214 -->
@AlexZorzi commented on GitHub (Sep 30, 2025):
Thanks @hemzet for the workaround
@Schnubl edit my Function to your needs, i provide a list of groups to track since my users have multiple groups and you can only send one to openrouter.
```
"""
title: OpenRouter User Tracking Filter
author: AlexZorzi
description: Automatically adds user parameter to API requests for OpenRouter usage tracking
version: 1.0
"""
from pydantic import BaseModel, Field
from typing import Optional, List
from open_webui.models.groups import Groups
class Filter:
class Valves(BaseModel):
enable_tracking: bool = Field(
default=True, description="Enable user tracking for OpenRouter"
)
trackable_groups: List[str] = Field(
default=[
"Backoffice",
"WEB",
"EDP",
"Fewo",
"Marketing",
"HR",
],
description="List of groups to track for department spending",
)
def __init__(self):
self.valves = self.Valves()
def inlet(self, body: dict, __user__: Optional[dict] = None) -> dict:
if not self.valves.enable_tracking:
return body
user_id = __user__.get("id") if __user__ else None
user_email = __user__.get("email") if __user__ else None
if not user_id:
print("No user ID available for tracking")
return body
# Get user groups
try:
member_groups = Groups.get_groups_by_member_id(user_id)
group_names = [g.name for g in member_groups]
print(f"User {user_id} is member of groups: {group_names}")
except Exception as e:
print(f"Error getting user groups: {e}")
group_names = []
# Find trackable group
trackable_group = None
for group_name in group_names:
if group_name in self.valves.trackable_groups:
trackable_group = group_name
break
# Create tracking identifier
if trackable_group:
user_tracking_id = f"{trackable_group}"
print(f"Tracking by department: {trackable_group}")
else:
# Fallback to user email if no trackable group found
user_tracking_id = f"{user_email}" if user_email else f"{user_id}"
print(
f"No trackable group found, using user identifier: {user_email or user_id}"
)
# Add user parameter for OpenRouter tracking
body["user"] = user_tracking_id
print(f"OpenRouter tracking - User: {user_tracking_id}")
return body
```
I asked to bring the groups into the frontend, this function works in backend und send results to frontend.
<!-- gh-comment-id:3360730597 -->
@seppel123 commented on GitHub (Oct 2, 2025):
Im sorry i really misunderstood that.
I asked to bring the groups into the frontend, this function works in backend und send results to frontend.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Originally created by @AlexZorzi on GitHub (Sep 9, 2025).
Original GitHub issue: https://github.com/open-webui/open-webui/issues/17308
Check Existing Issues
Problem Description
Im managing a openwebui for my company, i was request to track spending by each department, at this time im able to inject in the request headers with only the user ID through the
__user__variable.To keep things more anonymized i would like to track only the total department usage, since im using Oauth users get synced with their own Group from the identity manager so the data is already there, its just missing from the
__user__variable when making a function.Desired Solution you'd like
__user__should contain a list of the user groups, since the user can be part of more than one groupAlternatives Considered
No response
Additional Context
Code i currently use to inject the user id in the request headers
@hemzet commented on GitHub (Sep 19, 2025):
@AlexZorzi
Workaround:
@Schnubl commented on GitHub (Sep 28, 2025):
Hi @hemzet , can you pls explain how to use this code and where to put it in, i have also done a workaround for bring groups to frontend and modifyed the core which i dont like because its a pain when new updates released.
Would it be possible to make this a function or a pipe so you dont have to change the core directly?
@hemzet commented on GitHub (Sep 28, 2025):
@Schnubl
The snippet shows usage in a pipe function. No modification of core required. Just import the group model and use it.
@Schnubl commented on GitHub (Sep 29, 2025):
thx for the fast response.
i tried to creat a new function pipe and paste the code into it.
When try to svae it i get an error = "id"
here is the code that i pasted into the new function:
Did i misunderstand you?
@hemzet commented on GitHub (Sep 30, 2025):
Well, the provided code was simply a snippet to showcase the lines you need to add to your function for accessing group data. It's not the full code of a working function.
@AlexZorzi commented on GitHub (Sep 30, 2025):
Thanks @hemzet for the workaround
@Schnubl edit my Function to your needs, i provide a list of groups to track since my users have multiple groups and you can only send one to openrouter.
@seppel123 commented on GitHub (Oct 2, 2025):
Im sorry i really misunderstood that.
I asked to bring the groups into the frontend, this function works in backend und send results to frontend.