--- name: open-webui-persona-setup description: Create new Hermes profiles and Open WebUI personas for the family Open WebUI instance. Covers the runbook creation pattern, substitution tables, API gotchas, and peer validation workflow. version: 1.0.0 author: Hermes Agent license: MIT metadata: hermes: tags: [open-webui, hermes-profiles, personas, runbooks] related_skills: [ask-hermes, hermes-minimal-profile-setup] --- # Open WebUI Persona Setup Create new Hermes profiles and Open WebUI personas for the family Open WebUI instance at 10.0.0.204:8080. Covers the full pattern: Hermes-side profile creation, runbook authoring, Open WebUI REST API configuration, and peer validation. ## When to Use - Adding a new family member or persona to the existing Open WebUI instance - Creating a new Hermes profile to back a new Open WebUI persona - Writing a runbook for a new persona following the established four-phase pattern ## Architecture One Open WebUI instance (10.0.0.204:8080, Docker), multiple Hermes profiles as API backends (10.0.0.42). Each persona gets: - A dedicated Hermes profile (open1, openz, openg, openj, ...) - A dedicated API server port (8653, 8654, 8655, 8656, ...) - An Open WebUI group, user account, preset, and LLM connection - Memory isolation via separate Hermes profiles (each profile has its own memory scope) Voice I/O (STT/TTS) happens in Open WebUI (browser/PWA). Hermes handles agent logic only. STT uses Web API (browser-native) or Local Whisper. TTS uses Kokoro at 10.0.0.16:8880. ## Runbook Creation Pattern When creating a runbook for a new persona, follow this exact sequence: ### 1. Read the sibling runbooks All runbooks live in `/home/n8n/workspace/open1/`: | File | Persona | Permission Level | |------|---------|-----------------| | `openz_runbook_for_zoe.md` | Zoe (kid) | Restricted — web + voice + memories only | | `openg_runbook.md` | Guest | Full access (Operators-level) | | `openj_runbook_for_jennifer.md` | Jennifer (wife) | Full access (Operators-level) | Pick the closest match as your template. For full-access personas, use `openg_runbook.md`. For restricted personas, use `openz_runbook_for_zoe.md`. ### 2. Build a substitution table Map every template value to the new persona's values: | Element | Template | New | |---------|----------|-----| | Profile name | openg | openX | | Port | 8655 | next available (see Port Registry) | | Model name | Hermes Agent (openg) | Hermes Agent (openX) | | Group name | Guests | | | Preset name/id | Hermes-Guest / hermes-guest | Hermes- / hermes- | | User display name | | | | User email | | | | User password | | | | TTS voice | af_heart | af_heart (or af_nova for kids) | | url_idx | 2 | previous + 1 | | System prompt | empty | empty (or guardrail prompt for kids) | | Permissions | Operators-level | Operators-level (or Kids-level) | ### 3. Write the runbook Substitute every value from the table. Check every occurrence of port numbers, model names, group names, preset IDs, and url_idx values. Do NOT leave placeholder values — fill in concrete credentials. ### 4. Add a "second member" section Include a section (like openg §10) documenting the one-call operation to add another user to the same group. Note the shared-memory implication: all users in the same group share the same Hermes profile's memory. ### 5. Validate with a peer See Validation Workflow below. ## Common API Gotchas These were discovered across all four phases (open1, openz, openg, openj). Every runbook MUST reflect these: 1. **List group users is POST, not GET.** The endpoint `POST /api/v1/groups/id/{id}/users` returns `list[UserInfoResponse]` (bare array of user objects with id/name/email/role), NOT `{user_ids: [...]}`. A GET returns HTTP 405. This bug existed in the first three runbooks and was fixed in openj. 2. **Add users to group returns GroupResponse, not `{success: true}`.** The response includes the group object with updated `member_count`. 3. **User creation endpoint is `POST /api/v1/auths/add`, NOT `/api/v1/users/add`.** The wrong endpoint returns HTTP 405. The response includes a JWT for the new user. 4. **access_grants field shape is critical.** Use `principal_type` (not `type` or `group_type`), `principal_id` (not `id` or `group_id`), `permission` (not `access` or `read_write`). Wrong field names are silently dropped by the API — HTTP 200 either way. Always verify with a read-back. The safe path: create without grants, then do a separate access-update, then verify. 5. **Open WebUI persists settings in SQLite, not env vars.** Editing `/root/.env` after first launch has no effect. Use the REST API (`/openai/config/update`) to change connections. 6. **Model discovery has a delay.** After adding a new connection via `/openai/config/update`, wait 5-10 seconds before listing models — Open WebUI discovers them asynchronously. 7. **The `meta.system` field layers on top of Hermes' default prompt.** Set to empty (`""`) for full-access personas. The Hermes default is still active underneath. 8. **Memory scope is per-profile, not per-preset.** The preset's `base_model_id` determines which Hermes profile handles the chat, which determines the memory scope. This is the entire reason for the multi-profile setup. 9. **Cross-grants break memory isolation.** Never grant one profile's base model to another persona's group. open1's base goes to Operators only, openz's to Kids only, openg's to Guests only, openj's to Family only. 10. **The `signin` endpoint returns a token, not a cookie.** All subsequent calls use `Authorization: Bearer `. Token expires — re-signin on 401. 11. **Passwords are bcrypt-hashed on creation.** Plaintext is fine in the POST body; never log it. 12. **Email uniqueness is enforced.** Reusing an email for a different account will fail. ## Validation Workflow After creating a runbook, validate it with a peer Hermes agent. The peer checks API behavior against the live Open WebUI source code at `github.com/open-webui/open-webui` (routers in `backend/open_webui/routers/auths.py`, `groups.py`, `models.py`). ``` hermes -p general chat -q "Validate the runbook at /home/n8n/workspace/open1/.md. Read the sibling runbooks for comparison. Check: correctness (API endpoints, payload shapes, field names for Open WebUI 0.10.2), completeness (all steps covered, second-member section present), consistency (ports, model names, group names, preset IDs, url_idx values), gotchas (all 12 carried forward, no missing), substitution errors (no stale template values left in). Use mcp_searxng_searxng_web_search to verify API behavior against the live Open WebUI source code. Cite source URLs. Return a structured report with sections for Correctness, Completeness, Consistency, Gotchas, and Substitution Errors." -Q --max-turns 20 --yolo ``` **After validation:** the peer may find bugs in ALL runbooks, not just the new one. When the peer flags an API issue (e.g., wrong HTTP method), check the sibling runbooks too — they likely share the same bug. Fix them all. ## Port Registry | Profile | Port | Model Name | Owner | |---------|------|------------|-------| | open1 | 8653 | Hermes Agent (open1) | Rob (operator) | | openz | 8654 | Hermes Agent (openz) | Zoe | | openg | 8655 | Hermes Agent (openg) | Guest | | openj | 8656 | Hermes Agent (openj) | Jennifer | Reserved ports to avoid: 8644 (webhook), 8645 (wecom-callback), 8646 (msgraph-webhook). Use 8650+ for custom profiles. Next available: 8657. ## Key Files All in `/home/n8n/workspace/open1/`: | File | Purpose | |------|---------| | `open_web_ui_plan.md` | Master plan — architecture, Docker install, voice config, multi-profile setup, mobile access (61KB) | | `openz_runbook_for_zoe.md` | Zoe's kid-persona runbook — restricted permissions, guardrail prompt, bank isolation | | `openg_runbook.md` | Guest runbook — full access, no restrictions | | `openj_runbook_for_jennifer.md` | Jennifer's runbook — full access, Family group | | `openwebui_build_checklist.md` | Build/verification checklist with Phase A/B/C work order | | `AGENTS.md` | open1 workspace context — architecture diagram, port table, conventions | ## Pitfalls - **Don't leave placeholder values in runbooks.** Fill in concrete credentials before considering the runbook complete. The openg runbook has `` placeholders because guests are ephemeral; family members get concrete values. - **Check url_idx carefully.** Each new connection increments the index. open1=0, openz=1, openg=2, openj=3. The next will be 4. Getting this wrong means the wrong model appears in the wrong persona's dropdown. - **Cross-grants break memory isolation.** Never grant one profile's base model to another persona's group. The peer Hermes explicitly caught this in Phase A validation. - **The peer may find bugs in ALL runbooks, not just the new one.** When the peer flags an API issue, check the sibling runbooks too — they likely share the same bug. The GET→POST bug existed in openz, openg, and the original openj draft. - **Open WebUI version matters.** These runbooks target 0.10.2. If the instance is upgraded, re-validate API endpoints against the new version's source. - **The Hermes API server is an agent runtime, not a pure LLM proxy.** Tool calls execute on the Hermes host (10.0.0.42), not the Open WebUI host (10.0.0.204).