---
title: Web chat
description: The browser chat app every hub serves on port 3080, with sign-in, the Hub's agent and tools, uploads, file downloads, branding and chat history.
canonical_url: https://hubzoid.com/docs/chat/web-chat
last_updated: 2026-09-27
---

# Web chat

The browser chat app every hub serves on port 3080, with sign-in, the Hub's agent and tools, uploads, file downloads, branding and chat history.

Every hub ships with a browser chat app. Hubzoid bundles [Open WebUI](https://github.com/open-webui/open-webui) and starts it for you, wired to the hub's agent, so teammates can use the Hub without installing anything.

## When to use this

Use the web chat when people should talk to the Hub from a browser: to ask questions, attach files, download reports the agent writes, and keep a searchable history of their own conversations. When the hub serves MCP, it is also where each person creates the API key they use to [connect an existing assistant](https://hubzoid.com/docs/guides/connect-an-assistant).

## Start the chat app

```bash
hubzoid run my-hub
```

Open `http://localhost:3080`. The model picker shows the hub's main agent. Pick a suggested prompt or type a question.

`hubzoid run` starts three processes and keeps them together:

| Process | Where it listens | What it does |
| --- | --- | --- |
| Edge | `127.0.0.1:3080` (the public port) | The single front door. Sends `/artifacts`, `/portal` and, when enabled, `/mcp` to the bridge. Everything else goes to the chat app. |
| Open WebUI | `127.0.0.1:43080` (loopback only) | The chat app itself. Moves to the public port plus 40000 so the edge can take the public port. |
| Bridge | `127.0.0.1:8000` (loopback only) | Runs the Hub's agent and serves the [OpenAI-compatible API](https://hubzoid.com/docs/chat/openai-compatible-api) that the chat app calls. |

Browser → Edge on :3080 → Open WebUI → Bridge /v1 → Hub agent

A chat message travels from the browser through the edge and the chat app to the bridge, which runs the agent.

The edge drops any `X-Hubzoid-*` and `X-OpenWebUI-*` headers a browser sends, so identity can only be asserted by the chat app on loopback.

### Ports and binding

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `--port` | `integer` | `3080` | Public port for the chat app. Also read from PORT in the hub .env. |
| `--bridge-port` | `integer` | `8000` | Loopback port for the bridge. Also read from BRIDGE\_PORT. |
| `--host` | `string` | `"127.0.0.1"` | Interface the public port binds to. Also read from HUBZOID\_HOST. Use 0.0.0.0 to reach the chat app from your local network. The bridge always stays on 127.0.0.1. |
| `--no-ui` | `flag` |  | Start the bridge only, without the chat app or the edge. |
| `HUBZOID_OWUI_PORT` | `integer` |  | Pins the internal Open WebUI port instead of the public port plus 40000. |
| `HUBZOID_DISABLE_EDGE` | `boolean` |  | Skips the edge. Open WebUI then binds the public port itself. |

The chat app keeps its own data per hub in `<hub>/.openwebui-data/`, including its database `webui.db` and a log at `openwebui.log`. Under a [gateway](https://hubzoid.com/docs/deploy/gateway), one shared chat app fronts many hubs and keeps its data in the gateway's data folder.

## Sign-in

A hub starts with sign-in off (`WEBUI_AUTH` defaults to `False`). Anyone who can reach the port is in, which suits a single person on a laptop. Before anyone else can reach the port, turn sign-in on in the hub's `.env`:

```bash title="my-hub/.env"
WEBUI_AUTH=true
ENABLE_SIGNUP=false
DEFAULT_USER_ROLE=user
WEBUI_SECRET_KEY=<output of: openssl rand -hex 32>
WEBUI_URL=https://hub.example.com
WEBUI_ADMIN_EMAIL=you@example.com
WEBUI_ADMIN_PASSWORD=<temporary password>
```

On a fresh database the `WEBUI_ADMIN_*` pair creates the first admin. Delete both lines after the first boot and restart. Google, Microsoft, GitHub, OIDC, LDAP and trusted-header sign-in are covered in [Authentication](https://hubzoid.com/docs/deploy/authentication).

Hubzoid refuses to start the chat app in two unsafe configurations:

- `WEBUI_AUTH=true` without a `WEBUI_SECRET_KEY`, or with Open WebUI's public default key.
- An OAuth client ID (`GOOGLE_CLIENT_ID`, `MICROSOFT_CLIENT_ID`, `GITHUB_CLIENT_ID` or `OAUTH_CLIENT_ID`) without `WEBUI_URL`, because sign-in callbacks are built from it.

The chat app forwards the signed-in person's email to the bridge on every message. The bridge uses it to decide which restricted tools that person may use and, when the hub's access is managed in [the Console](https://hubzoid.com/docs/console/agents-and-access), whether they may use the agent at all. The bridge refuses a message from a person without the **Use this agent** grant.

## How the Hub appears in chat

The chat app does not hold the agent's instructions or tools. It sends each conversation to the bridge, and the bridge runs the Hub's agent with everything the hub defines.

| What the person sees | Where it comes from |
| --- | --- |
| The agent in the model picker | One model per hub, named by `MODEL_LABEL` or the `name:` in `AGENTS.md`. In a single hub every signed-in person sees it. Under a gateway each person sees the agents they have access to. |
| Answers that follow the Hub's rules | The `AGENTS.md` body, knowledge, skills and sub-agents, applied by the bridge on every turn. |
| Suggested prompts on an empty chat | The `suggestions:` list in the main `AGENTS.md` frontmatter. |
| Tool activity | Each tool call as a collapsible dropdown. Set `SHOW_TOOLS=full` for inline notes or `off` to hide them. |
| A "Thinking" panel | Hubs on `MODEL=claude-local` only, controlled by `SHOW_THINKING` (`indicator` by default, `full` to stream a summary, `off`). |
| Thumbs up and down, chat titles | Open WebUI features that stay on. |

Tools guarded by a `restricted/` file are hidden from a person who may not use them and refused if reached anyway. See [Restrict tools](https://hubzoid.com/docs/guides/restrict-tools).

```markdown title="my-hub/AGENTS.md"
---
name: Stock desk
description: Answers stock and reorder questions for four store locations.
suggestions:
  - Which items are below reorder point at the harbor store?
  - Summarize yesterday's stock movements
  - Draft this week's reorder list
---

You help store managers with stock questions. Use read_knowledge for policy
and grep_data for the stock exports in raw_data/.
```

### Features Hubzoid turns off

Hubzoid starts Open WebUI with features that would bypass the Hub switched off. Each one is an environment variable, so a value in the hub's `.env` always wins.

| Setting | Default | Why |
| --- | --- | --- |
| `ENABLE_CODE_INTERPRETER` | `False` | Runs code outside the Hub's tool model, with no access checks or audit. Add a `tools_local/` tool instead. |
| `ENABLE_DIRECT_CONNECTIONS` | `False` | Would let people plug in their own model keys and bypass the Hub. |
| `ENABLE_RAG_WEB_SEARCH` | `False` | The Hub has its own `web_search` tool. |
| `ENABLE_MEMORY` | `False` | Open WebUI memory is separate from the Hub's context. |
| `ENABLE_NOTES`, `ENABLE_CHANNELS` | `False` | Parallel products inside the chat app. |
| `ENABLE_COMMUNITY_SHARING` | `False` | Removes the share-to-community button. |
| `ENABLE_FOLLOW_UP_GENERATION`, `ENABLE_TAGS_GENERATION`, `ENABLE_AUTOCOMPLETE_GENERATION` | `False` | Each adds an extra model call. |
| `ENABLE_VERSION_UPDATE_CHECK` | `False` | No update checks from your server. |
| `ENABLE_PERSISTENT_CONFIG` | `False` | Keeps the `.env` authoritative on every restart. |

Non-admin users also lose the Workspace tabs for models, tools, functions, knowledge and prompts. A baseline stylesheet hides the Workspace link and the voice mode and microphone buttons. Put your own `custom.css` in `<hub>/branding/` to replace it.

## Uploads

People attach files in the chat as usual. The bridge copies each attached file into the chat's own uploads folder, `<hub>/.hubzoid/chats/<chat_id>/uploads/`, and tells the agent what arrived.

- **Images** are shown to the model directly. Up to 4 images per turn are sent as images (`HUBZOID_VISION_MAX_IMAGES`), with the long edge scaled to 1568 pixels (`HUBZOID_VISION_MAX_EDGE`). Set `HUBZOID_VISION=false` for a text-only hub.
- **Other files** are read on demand with `read_upload`, which returns a preview that fits the file: the first 200 lines of text, a CSV header with 20 rows and a row count, or the first 5 pages of a PDF. `read_upload_full` returns the whole text when the agent needs it.

If a file the person attached cannot be read from storage, the agent is told to say so and ask for it again rather than guess its contents. Open WebUI's own document indexing is bypassed: files are text-extracted, never embedded.

## Files the agent writes

When the agent calls `write_artifact`, the file is saved to `<hub>/.hubzoid/chats/<chat_id>/artifacts/` and the reply carries a download link, even if the model forgets to repeat it.

- Links are signed with a per-hub secret stored in `<hub>/.hubzoid/artifact_secret`. Set `HUBZOID_ARTIFACT_SECRET` only to share one secret across hosts serving the same hub. Changing or deleting the secret revokes every issued link.
- Links never expire by default. Set `HUBZOID_ARTIFACT_LINK_TTL` to a number of seconds to limit them.
- Behind a reverse proxy, set `HUBZOID_PUBLIC_URL=https://hub.example.com` so links use your public address. Without it, links fall back to `WEBUI_URL`, then to the local bridge address.
- Files open in a sandbox with a separate origin, so a script inside an HTML report cannot read the chat app's session.

## Branding

With nothing in `<hub>/branding/`, the chat app shows Open WebUI's own logo and names itself after your agent with an "(Open WebUI)" suffix. Add at least one image and the hub is branded.

```text
my-hub/
  AGENTS.md
  .env
  branding/
    logo.svg
    favicon.png
    splash.png
```

| Item | Source | Default |
| --- | --- | --- |
| Name in the app | `WEBUI_NAME` in `.env` | The main agent's `name:` from `AGENTS.md`, then `Hubzoid` |
| Logo and tab icon | `logo.svg`, `logo.png`, `favicon.svg`, `favicon.png` or `favicon.ico` | Open WebUI's mark |
| Splash screen | `splash.png` | Open WebUI's splash |
| Watermark on copied replies | `RESPONSE_WATERMARK` in `.env` | The hub folder name |

A single `favicon.png` (or `logo.png`) fills every raster icon slot, light and dark. With branding in place, Hubzoid also rewrites the static tab title, link-preview tags and app manifest name on each `hubzoid run`. Branding files are picked up on the next start.

> **Warning: Open WebUI license**
>
> Open WebUI's license allows removing its branding for deployments with 50 or fewer end users in any rolling 30 days, or with an Open WebUI enterprise license. Above that, set `HUBZOID_KEEP_OWUI_SUFFIX=true`, which keeps Open WebUI's branding even when your files are present.

## Admins and other people's chats

An Open WebUI admin cannot open, list or export another person's chats. Set `ENABLE_ADMIN_CHAT_ACCESS=true` (viewing) or `ENABLE_ADMIN_EXPORT=true` (export) in the hub's `.env` and restart to allow it. Both are environment-only, so nobody can switch them on from the admin panel.

## History on each surface

Each surface keeps its own conversations. They share the Hub's instructions, knowledge and tools, not their histories.

| Surface | Where the conversation lives |
| --- | --- |
| Web chat | The chat app's database, per person. The whole conversation is sent to the bridge each turn. |
| [Slack](https://hubzoid.com/docs/chat/slack) | Slack itself. The adapter reads the thread back on every message. |
| [WhatsApp and Telegram](https://hubzoid.com/docs/chat/whatsapp-and-telegram) | The hub database, the last 40 messages per chat by default. |
| [OpenAI-compatible API](https://hubzoid.com/docs/chat/openai-compatible-api) | The caller sends the conversation with each request. |
| [MCP](https://hubzoid.com/docs/guides/connect-an-assistant) | The connected assistant. Each MCP call is independent. |

Files attached and written in a chat stay in that chat's folder under `<hub>/.hubzoid/chats/`. For how the Hub's durable context differs from conversation history, see [Memory and history](https://hubzoid.com/docs/concepts/memory-and-history).

## Next steps

- [Authentication](https://hubzoid.com/docs/deploy/authentication): Turn on sign-in with email, SSO, OIDC or LDAP before sharing the chat app.
- [Agents and access](https://hubzoid.com/docs/console/agents-and-access): Decide who may use each agent and which restricted tools they get.
- [Slack](https://hubzoid.com/docs/chat/slack): Offer the same Hub in Slack threads, DMs and the assistant sidebar.
- [Connect an assistant](https://hubzoid.com/docs/guides/connect-an-assistant): Use the Hub from Claude Code, Codex or Hermes with a personal API key.
