[GH-ISSUE #37] issue: /p/{policy_id}/system and /p/{policy_id}/api/config unreachable for Open WebUI (X-User-Id required, no system-container fallback) #13

Closed
opened 2026-10-18 21:13:23 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @Classic298 on GitHub (Jul 10, 2026).
Original GitHub issue: https://github.com/open-webui/terminals/issues/37

/p/{policy_id}/system and /p/{policy_id}/api/config unreachable for Open WebUI (X-User-Id required, no system-container fallback)

Summary

Open WebUI's backend fetches a terminal server's system prompt via GET {base}/api/config (feature probe) and GET {base}/system without an X-User-Id header. On the orchestrator, both paths fall into the generic policy proxy /p/{policy_id}/{path}, whose verify_user_id dependency declares X-User-Id as a required header — so the requests fail with 422 before auth even runs. Result: the system-prompt integration never works through the orchestrator, silently.

/p/{policy_id}/openapi.json already solves this exact problem for tool discovery: it's a dedicated route that serves the response via a system-user container without requiring X-User-Id. /system and /api/config need the same treatment.

Environment

  • Terminals: 0.0.5-dev (ghcr.io/open-webui/terminals:latest), Docker backend, API-key auth

Reproduction

# policy with a recognizable prompt
curl -X PUT http://localhost:3000/api/v1/policies/demo \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"env": {"OPEN_TERMINAL_SYSTEM_PROMPT": "MARKER-12345"}}'

# what Open WebUI's backend actually sends (no X-User-Id):
curl -i http://localhost:3000/p/demo/api/config
curl -i -H "Authorization: Bearer $KEY" http://localhost:3000/p/demo/system

Expected: /api/config returns the container's feature flags and /system returns {"prompt": "MARKER-12345"}, served via a system container (like /p/demo/openapi.json already does).

Actual: both return 422 {"detail":[{"type":"missing","loc":["header","X-User-Id"], ...}]}. With an X-User-Id header added, they work — but Open WebUI never sends one, so in practice the prompt is never delivered to chats.

Root cause

  • terminals/routers/proxy.py: policy_proxy (/p/{policy_id}/{path:path}) depends on verify_user_id.
  • terminals/routers/auth.py: verify_user_id declares x_user_id: str = Header(..., alias="X-User-Id") — required, so FastAPI 422s when absent.
  • Only /p/{policy_id}/openapi.json has a dedicated no-user route (policy_openapi_spec, served via _SYSTEM_USER_ID + _get_cached_spec).

Suggested fix

Add dedicated routes mirroring policy_openapi_spec:

  • GET /p/{policy_id}/api/config → proxy to a system-user instance of the policy (cacheable, small TTL).
  • GET /p/{policy_id}/system → proxy to a system-user instance of the policy.

Both should require the normal API-key/JWT auth (verify_api_key) but not X-User-Id. This makes the orchestrator interchangeable with a direct open-terminal instance for Open WebUI's config/system-prompt fetches, which is the proxy's stated design goal ("the path structure mirrors open-terminal exactly … so the two are interchangeable").

Caveat worth documenting: the prompt is then rendered by the system container, so {{home}}-style placeholders expand with that container's values.

Originally created by @Classic298 on GitHub (Jul 10, 2026). Original GitHub issue: https://github.com/open-webui/terminals/issues/37 # `/p/{policy_id}/system` and `/p/{policy_id}/api/config` unreachable for Open WebUI (X-User-Id required, no system-container fallback) ## Summary Open WebUI's backend fetches a terminal server's system prompt via `GET {base}/api/config` (feature probe) and `GET {base}/system` **without an `X-User-Id` header**. On the orchestrator, both paths fall into the generic policy proxy `/p/{policy_id}/{path}`, whose `verify_user_id` dependency declares `X-User-Id` as a **required** header — so the requests fail with 422 before auth even runs. Result: the system-prompt integration never works through the orchestrator, silently. `/p/{policy_id}/openapi.json` already solves this exact problem for tool discovery: it's a dedicated route that serves the response via a system-user container without requiring `X-User-Id`. `/system` and `/api/config` need the same treatment. ## Environment - Terminals: 0.0.5-dev (`ghcr.io/open-webui/terminals:latest`), Docker backend, API-key auth ## Reproduction ```bash # policy with a recognizable prompt curl -X PUT http://localhost:3000/api/v1/policies/demo \ -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \ -d '{"env": {"OPEN_TERMINAL_SYSTEM_PROMPT": "MARKER-12345"}}' # what Open WebUI's backend actually sends (no X-User-Id): curl -i http://localhost:3000/p/demo/api/config curl -i -H "Authorization: Bearer $KEY" http://localhost:3000/p/demo/system ``` **Expected:** `/api/config` returns the container's feature flags and `/system` returns `{"prompt": "MARKER-12345"}`, served via a system container (like `/p/demo/openapi.json` already does). **Actual:** both return `422 {"detail":[{"type":"missing","loc":["header","X-User-Id"], ...}]}`. With an `X-User-Id` header added, they work — but Open WebUI never sends one, so in practice the prompt is never delivered to chats. ## Root cause - `terminals/routers/proxy.py`: `policy_proxy` (`/p/{policy_id}/{path:path}`) depends on `verify_user_id`. - `terminals/routers/auth.py`: `verify_user_id` declares `x_user_id: str = Header(..., alias="X-User-Id")` — required, so FastAPI 422s when absent. - Only `/p/{policy_id}/openapi.json` has a dedicated no-user route (`policy_openapi_spec`, served via `_SYSTEM_USER_ID` + `_get_cached_spec`). ## Suggested fix Add dedicated routes mirroring `policy_openapi_spec`: - `GET /p/{policy_id}/api/config` → proxy to a system-user instance of the policy (cacheable, small TTL). - `GET /p/{policy_id}/system` → proxy to a system-user instance of the policy. Both should require the normal API-key/JWT auth (`verify_api_key`) but not `X-User-Id`. This makes the orchestrator interchangeable with a direct open-terminal instance for Open WebUI's config/system-prompt fetches, which is the proxy's stated design goal ("the path structure mirrors open-terminal exactly … so the two are interchangeable"). Caveat worth documenting: the prompt is then rendered by the *system* container, so `{{home}}`-style placeholders expand with that container's values.
Author
Owner

@owui-terminator[bot] commented on GitHub (Jul 10, 2026):

🔍 Related Issues Found

I found some existing issues that might be related. Please check if any of these are duplicates or contain helpful solutions:

  1. 🟢 #36 issue: Terminal system prompt is never injected for orchestrator connections (/system fetch omits X-User-Id)
    This is the same underlying problem: Open WebUI fetches /api/config and /system without X-User-Id, and the orchestrator's proxy requires that header, causing 422s and preventing the system prompt from being injected.
    by Classic298

  2. 🟣 #29 issue: system prompt env var not respected
    This closed issue reports the same user-visible symptom: OPEN_TERMINAL_SYSTEM_PROMPT not reaching models when terminals are enabled. It appears to be the earlier manifestation of the same system-prompt delivery bug.
    by Classic298


💡 If your issue is a duplicate, please close it and add any additional details to the existing issue instead.

This comment was generated automatically. React with 👍 if helpful, 👎 if not.

<!-- gh-comment-id:4939356980 --> @owui-terminator[bot] commented on GitHub (Jul 10, 2026): <!-- terminator-bot:related-issues-reply --> 🔍 **Related Issues Found** I found some existing issues that might be related. Please check if any of these are duplicates or contain helpful solutions: 1. 🟢 [#36](https://github.com/open-webui/terminals/issues/36) **issue: Terminal system prompt is never injected for orchestrator connections (`/system` fetch omits `X-User-Id`)** *This is the same underlying problem: Open WebUI fetches `/api/config` and `/system` without `X-User-Id`, and the orchestrator's proxy requires that header, causing 422s and preventing the system prompt from being injected.* *by Classic298* 2. 🟣 [#29](https://github.com/open-webui/terminals/issues/29) **issue: system prompt env var not respected** *This closed issue reports the same user-visible symptom: `OPEN_TERMINAL_SYSTEM_PROMPT` not reaching models when terminals are enabled. It appears to be the earlier manifestation of the same system-prompt delivery bug.* *by Classic298* --- 💡 If your issue is a duplicate, please close it and add any additional details to the existing issue instead. *This comment was generated automatically.* React with 👍 if helpful, 👎 if not.
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
open-webui/terminals#13
No description provided.