Skip to content

Deep research ​

Deep research answers a question with a cited report instead of a chat reply. A user picks a model such as "Deep Research · Recht" in Bebbi Bot, answers at most two clarifying questions, approves a research plan, and gets a German report with numbered sources back in the same chat. Most runs happen at night, because one report takes minutes of model time and the GPUs are busy during office hours.

The agent lives in its own repository, DCC-BS/bebbi-deep-research. Open WebUI reaches it through a pipe. This page first explains what a pipe is, then how the agent works.

What is a pipe? ​

In Open WebUI a model is normally an endpoint behind an OpenAI-compatible API. A pipe is a Python function that Open WebUI shows in the model picker like any other model, but whose answer comes from code you wrote. Open WebUI calls the pipe with the chat request, and whatever the pipe returns or streams becomes the assistant's message. The pipe can call an LLM, a different API, or run a whole program.

The official documentation describes the full interface. The parts that matter here:

  • Class and method. A pipe is a class Pipe with a pipe(self, body, ...) method. body holds the messages and parameters of the request.
  • Manifold. If the class also defines pipes(), it returns a list of models and Open WebUI lists each one separately. One file can then provide many models. Open WebUI names them <function id>.<model id>.
  • Injected arguments. The method may ask for __user__ (the caller), __event_emitter__ (send status lines, source citations or replacement text to the chat), __event_call__ (ask the user something and wait for the answer), __request__ and __task__. Open WebUI fills in whatever the signature names.
  • Valves. A Valves class defines settings that an admin edits in the UI, such as a service URL or a token.
  • Admin only. A pipe runs arbitrary code on the server, so only admins can install one. Ours is installed by the seeder.

Pipes are one of three function types, next to filters and actions. See Tools and workspace content for the difference between those and tools.

Why a pipe and not a tool? A tool is something the model chooses to call in the middle of an answer. Deep research is a different product: it has its own conversation flow, can take hours, and must not be steered by a chat model's guesses. The pipe takes over the whole turn.

How a research run goes ​

  1. Clarify. The service asks at most two questions, and only when the task is unclear.
  2. Plan. The service writes a plan of sub-questions. The user sees it in Open WebUI's ask-user card with three buttons: approve, change, discard. "Change" opens an input box, and the plan is rewritten and shown again, up to three times. Closing the card or letting it time out counts as discard, and nothing runs.
  3. Queue. After approval the job goes into a queue in PostgreSQL. It starts inside the night window, 20:00 to 05:00 in Europe/Zurich. The one exception is a quick run of a focus preset (below), which may start during the day.
  4. Research. The service searches the web, reads pages and calls MCP servers, collects evidence with verbatim quotes, and writes the report.
  5. Delivery. The finished report replaces the "queued" text in the user's chat, with sources as numbered badges and a source list. A button under the message adds a Word file.

The user can say "schnell" or "gründlich" in the question to choose a quick or deep run. Quick, standard and deep differ in rounds, number of sub-questions and a hard token cap per run (200k, 450k, 900k tokens).

Presets ​

Each preset is a research profile and appears as its own model.

ModelPresetSources
Deep Research · RechtrechtsrechercheFederal and cantonal legislation and court decisions through OpenCaseLaw, plus the web
Deep Research · Grosser RatgrossratAll business of the Grosser Rat since 1973 through its MCP server
Deep Research · StatistikstatistikOpen data portal data.bs.ch and official statistics
Deep Research · Verwaltungverwaltung_webStrategies and web offers of Confederation, cantons and cities, with the Grosser Rat, data.bs.ch and OpenCaseLaw servers as helpers
Deep Research · Webweb_surveyBroad web research on international topics
Deep Research · Eigene DokumentedokumenteOnly files and knowledge bases of the user, no web

Presets live in config/presets.yaml, mounted as a ConfigMap. They set the engine, the preferred domains, the MCP tools the model may use, the budgets and the report style. Adding a topic needs no code. German reports follow the house style of the canton (Swiss spelling, short sentences, gender-neutral wording).

Two engines ​

  • Focus engine. Used by every preset except the web survey. The model plans a checklist, then runs a bounded loop of tool calls over web search, page fetches and the preset's MCP tools. Each source becomes a record with URL, title, date and a verbatim quote. The model cites [S3] style references and code resolves them into the numbered source list, so a citation cannot point at a source that does not exist. Numbers and identifiers are checked against the evidence. A report takes about 60k tokens and three minutes.
  • Pipeline engine. Used for the web survey. It plans, researches each sub-question in rounds, writes the report section by section, and verifies quotes. About 190k tokens and five minutes.

The model behind both is Gemma 4 31B on the KDKP, in a thinking role for planning and writing and a fast role for routing, plus a Qwen embedding model for passage selection.

Own sources ​

Files uploaded in the chat and knowledge bases attached to the chat or the model count as sources next to the web. The pipe checks, as the chat user, what that user may read, and sends the extracted texts and knowledge base ids along with the job. The night run therefore needs no user session. Citations show "Hochgeladene Datei" or the knowledge base name. The limits are 10 files, two million characters per file and five knowledge bases per run. A preset can be set to only, which removes web search and MCP tools. The "Eigene Dokumente" model works that way.

What sits in Open WebUI ​

PartWhereRole
bebbi_deep_research pipeseeded functionThe manifold. One model per preset, talks to the service with a bearer token
bebbi_deep_research_download actionseeded functionButton that adds the Word file to a report delivered at night
Model entriesseeded modelsName, description, public read grant, citations capability
Delivery routecustom imageLets the service write into a chat at night

The pipe keeps its chat state in an invisible marker inside the assistant message, written as a Markdown link reference definition that Open WebUI never renders. The marker records whether the chat is waiting for answers, for a decision, or for a delivered report, and a later message in the same chat continues from it. The pipe also answers Open WebUI's background tasks (title, tags, follow-ups) itself, so they do not start a research turn.

The pipe depends on httpx and pydantic only, both already in the Open WebUI image. Its valves:

ValveMeaning
SERVICE_URLIn-cluster URL of the research service
SERVICE_TOKENBearer token, equal to the service's RA_TOKEN
DEFAULT_DEPTHquick, standard or deep when the user says nothing
DECISION_MINUTESHow long the approve card waits, default 30
PRESETSList of preset:label pairs, one model each
OWN_SOURCESUse uploaded files and knowledge bases

Delivering the report ​

At night no user is logged in, yet the service must write into a user's chat. Since Open WebUI 0.12, an admin API key can no longer write into another user's chat when ENABLE_ADMIN_CHAT_ACCESS is off. The custom image therefore adds one narrow route, POST /api/v1/dcc/deep-research/deliver:

  • Off unless DCC_DEEP_RESEARCH_DELIVERY_SECRET is set to a secret of at least 32 characters.
  • The secret is separate from every Open WebUI API key and is checked in constant time before the body is read. The body is capped at 4 MB.
  • The route writes only into an assistant message of a deep research model whose state marker says a job is queued, in a chat that belongs to the given user. After delivery the marker is gone, so the message is closed.
  • Block /api/v1/dcc/ for external clients at the gateway. Only the in-cluster service needs it.

Service ​

The job service is a FastAPI app on dcc-backend-common, with PostgreSQL for drafts, jobs, events and reports. It is stateless apart from the database, so a restart re-queues running jobs. It exposes health probes and Prometheus metrics (research_jobs, research_in_night_window). Configuration is by environment variables, listed in docs/operations.md of the repository.

SettingDefault
RA_NIGHT_WINDOW20:00-05:00
RA_TIMEZONEEurope/Zurich
RA_WORKERS1 concurrent job inside the window
RA_DAY_WORKERS1 concurrent job outside the window

More ​

The repository has the details: docs/integration.md (install, valves, upgrade checklist), docs/presets.md (adding presets and MCP servers), docs/evaluation.md (benchmarks and tuning history behind the engines) and docs/mcp-servers.md.

Developed with ❤️ by the DCC. Documentation released under the MIT License.