diff --git a/backend/open_webui/main.py b/backend/open_webui/main.py
index ecba6407f3..0ff61fbc14 100644
--- a/backend/open_webui/main.py
+++ b/backend/open_webui/main.py
@@ -1277,6 +1277,7 @@ async def chat_completion(
'variables': form_data.get('variables', {}),
'chat_variables': chat_variables,
'model': model,
+ 'model_system_prompt': model_info_params.get('system'),
'direct': model_item.get('direct', False),
'params': {
'stream_delta_chunk_size': stream_delta_chunk_size,
@@ -1787,7 +1788,7 @@ async def chat_completion(
'session_id': metadata.get('session_id'),
'tool_ids': metadata.get('tool_ids') or [],
'skill_ids': metadata.get('skill_ids') or [],
- 'system_prompt': metadata.get('system_prompt'),
+ 'system_prompt': metadata.get('chat_system_prompt'),
'filter_ids': metadata.get('filter_ids') or [],
'terminal_id': metadata.get('terminal_id'),
'features': metadata.get('features') or {},
diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py
index 6a3e4b6f5b..138c37494e 100644
--- a/backend/open_webui/utils/middleware.py
+++ b/backend/open_webui/utils/middleware.py
@@ -2531,6 +2531,7 @@ async def process_chat_payload(request, form_data, user, metadata, model):
) # Required to handle system prompt variables
except Exception:
pass
+ chat_system_prompt = get_content_from_message(system_message) if system_message else None
form_data = await convert_url_images_to_base64(form_data, user=user)
@@ -2665,6 +2666,8 @@ async def process_chat_payload(request, form_data, user, metadata, model):
except Exception as e:
raise Exception(f'{e}')
+ delegate_system_prompt = get_content_from_message(get_system_message(form_data['messages']) or {})
+
features = form_data.pop('features', None) or {}
extra_params['__features__'] = features
if features:
@@ -2823,11 +2826,15 @@ async def process_chat_payload(request, form_data, user, metadata, model):
skill_manifest = ''
for skill in available_skills:
if skill.id in mentioned_skill_ids or not use_builtin_tools:
+ skill_context = f'\n{skill.content}\n'
form_data['messages'] = add_or_update_system_message(
- f'\n{skill.content}\n',
+ skill_context,
form_data['messages'],
append=True,
)
+ delegate_system_prompt = (
+ f'{delegate_system_prompt}\n{skill_context}' if delegate_system_prompt else skill_context
+ )
else:
view_skill_ids.append(skill.id)
skill_manifest += (
@@ -2855,11 +2862,15 @@ async def process_chat_payload(request, form_data, user, metadata, model):
skill_name = unquote(sid.removeprefix(terminal_skill_prefix))
loaded = await get_terminal_skill(request, user.model_dump(), metadata, skill_name, extra_params)
if loaded:
+ skill_context = format_terminal_skill_context(loaded)
form_data['messages'] = add_or_update_system_message(
- format_terminal_skill_context(loaded),
+ skill_context,
form_data['messages'],
append=True,
)
+ delegate_system_prompt = (
+ f'{delegate_system_prompt}\n{skill_context}' if delegate_system_prompt else skill_context
+ )
else:
view_skill_ids.append(sid)
skill_manifest += format_terminal_skill_manifest_entry(skill)
@@ -3193,6 +3204,22 @@ async def process_chat_payload(request, form_data, user, metadata, model):
f'{resolved_model_system_prompt}\n{system_content}' if system_content else resolved_model_system_prompt
)
metadata['system_prompt'] = system_content or None
+ # Timers/follow-ups continue this chat, sub-agents start their own; the model's own prompt is added in each run
+ sent_with_request = model_system_prompt != metadata.get('model_system_prompt')
+ already_in_chat = resolved_model_system_prompt == chat_system_prompt
+ if resolved_model_system_prompt and sent_with_request and not already_in_chat:
+ chat_system_prompt = (
+ f'{resolved_model_system_prompt}\n{chat_system_prompt}'
+ if chat_system_prompt
+ else resolved_model_system_prompt
+ )
+ delegate_system_prompt = (
+ f'{resolved_model_system_prompt}\n{delegate_system_prompt}'
+ if delegate_system_prompt
+ else resolved_model_system_prompt
+ )
+ metadata['chat_system_prompt'] = chat_system_prompt
+ metadata['delegate_system_prompt'] = delegate_system_prompt
metadata['user_prompt'] = get_last_user_message(form_data['messages'])
metadata['sources'] = sources[:] if sources else []
diff --git a/backend/open_webui/utils/subagents.py b/backend/open_webui/utils/subagents.py
index 13b9699216..7014cb04b0 100644
--- a/backend/open_webui/utils/subagents.py
+++ b/backend/open_webui/utils/subagents.py
@@ -319,7 +319,8 @@ async def delegate(
'session_id': metadata.get('session_id'),
'tool_ids': copy.deepcopy(metadata.get('tool_ids') or []),
'skill_ids': copy.deepcopy(metadata.get('skill_ids') or []),
- 'system_prompt': metadata.get('system_prompt'),
+ 'system_prompt': metadata.get('chat_system_prompt'),
+ 'delegate_system_prompt': metadata.get('delegate_system_prompt'),
'tool_servers': [] if background else copy.deepcopy(metadata.get('tool_servers') or []),
'filter_ids': copy.deepcopy(metadata.get('filter_ids') or []),
'terminal_id': metadata.get('terminal_id'),
@@ -449,7 +450,7 @@ async def delegate(
try:
child_request = _build_request(request, user.id, internal=True)
child_request.state.max_tool_call_iterations = max_iterations
- parent_system_prompt = run.get('system_prompt') or ''
+ parent_system_prompt = run.get('delegate_system_prompt') or ''
subagent_system_prompt = (
str(config.get('subagents.system_prompt') or '').strip() or DEFAULT_SUBAGENT_SYSTEM_PROMPT
)
diff --git a/backend/open_webui/utils/timers.py b/backend/open_webui/utils/timers.py
index 15a6b898db..17c7e1bc55 100644
--- a/backend/open_webui/utils/timers.py
+++ b/backend/open_webui/utils/timers.py
@@ -108,7 +108,7 @@ async def create_timer(
'session_id': metadata.get('session_id'),
'tool_ids': copy.deepcopy(metadata.get('tool_ids') or []),
'skill_ids': copy.deepcopy(metadata.get('skill_ids') or []),
- 'system_prompt': metadata.get('system_prompt'),
+ 'system_prompt': metadata.get('chat_system_prompt'),
'filter_ids': copy.deepcopy(metadata.get('filter_ids') or []),
'terminal_id': metadata.get('terminal_id'),
'features': copy.deepcopy(metadata.get('features') or {}),