docs: publish architecture and experiment portal

This commit is contained in:
wuyang
2026-07-26 21:03:23 +08:00
parent 4eb915283d
commit 688ddec1fe
17 changed files with 3582 additions and 56 deletions
+164 -53
View File
@@ -1,74 +1,185 @@
# Architecture
## Single Agent path
## Design objective
Open WebUI owns authenticated users, conversation history, and rendering.
Every normal model request is delegated to the K1412 Runtime. There is no
second Chat loop and no per-conversation mode state.
K1412 Agent is a multi-user web coding Agent whose loop can be changed
independently of its account system and user interface. The architecture keeps
the high-cost experimental surface small: researchers should be able to change
context, memory, scheduling, tools, delegation, or completion policy without
forking authentication, chat history, Docker lifecycle, or the whole frontend.
## Agent loop
The system deliberately has one Agent path. The earlier idea of a lightweight
Chat loop beside a custom Work loop was removed because it duplicated product
behavior, confused model selection, and increased the amount of frontend and
backend code that had to remain compatible.
The first strategy is intentionally modular:
## System context
- `ModelProvider` owns provider transport.
- `ContextPolicy` owns visible-message cleanup and compaction.
- `ToolRegistry` owns tool schemas and dispatch.
- `AgentLoop` owns iteration, safe parallel scheduling, and delegation.
- `RuntimeStore` owns events, plans, and durable Agent memory.
- `ExecutionProvider` owns local or SSH Docker execution.
```mermaid
flowchart LR
U["Browser user"] --> P["DNS, TLS and Nginx Proxy Manager"]
P --> W["Open WebUI<br/>auth, RBAC, history, UI"]
W --> R["Agent Runtime<br/>loop, context, memory, model routing"]
R --> M["Model providers<br/>K1412 API or DeepSeek"]
R --> G["Workspace Gateway<br/>identity and execution policy"]
G -->|Tailscale + SSH Docker| X["Per-user workspace container<br/>home-node-itx"]
W --> DB["PostgreSQL<br/>users and chats"]
R --> DB
W --> Q["Redis<br/>coordination"]
```
Every run records its model ID, strategy version, scheduler version, context
policy, model/tool events, failures, and completion. This event stream is the
foundation for replay, evaluation, and future experiment assignment.
Only Web is publicly reachable. Runtime, Gateway, PostgreSQL, and Redis live on
private Compose networks. Workspace containers run on a separate physical
Docker host, receive no application secrets, and expose no host ports.
Luna, Terra, and Sol are three independent Ollama models. Each advertises
boolean thinking support, but none advertises adjustable reasoning effort.
DeepSeek V4 Pro is a fourth model configured with thinking enabled and maximum
reasoning effort. Provider selection and credentials remain server-side.
Thinking state is preserved across tool turns when the provider requires the
assistant's `reasoning_content` to be returned with following tool results.
The Agent never publishes hidden reasoning as its own user-facing output.
## Responsibility boundaries
Completion is evidence-gated. Requests for scripts, reports, code, or
other concrete artifacts are not accepted as complete until a file mutation
has succeeded and a later read, diff, or command has verified the latest
mutation. Bare interactive shell commands are rejected. If the iteration
budget is exhausted without evidence, Runtime returns an explicit incomplete
checkpoint instead of repeating an unverified model claim.
| Layer | Owns | Must not own |
| --- | --- | --- |
| Open WebUI | Registration, login, sessions, admin approval, RBAC, chat persistence, rendering | Agent scheduling, provider secrets, Docker access |
| Agent Runtime | Model catalog, context policy, Agent loop, tools, scheduling, delegation, memory, plans, run events, evidence gates | Browser sessions, Docker socket |
| Workspace Gateway | Signed identity enforcement, workspace path policy, per-user locks, Docker lifecycle, file delivery | Model calls, public authentication UI |
| Workspace container | User code, dependencies, generated files, command execution | Other users' data, service credentials, Docker socket |
| PostgreSQL | Open WebUI durable state plus Runtime events, plans, and memories | Execution |
| Shared infrastructure | TLS, registry, source hosting, private routing, model serving | Agent behavior |
Read-only tools and read-only child Agents may run concurrently. Workspace
mutations are serialized. A child Agent cannot delegate again, and read-only
children receive only read-only tools.
This separation lets the Web UI be upgraded on its own schedule while the
Agent loop can iterate frequently.
## Execution providers
## Request lifecycle
`local-docker` connects the Workspace Gateway to the local Docker daemon.
`ssh-docker` connects the same Docker SDK operations to a remote physical
machine through SSH. Both create the same workspace image, persistent per-user
volume, and dedicated per-user bridge network, so moving execution off the web
host changes configuration rather than Agent behavior.
### Agent request
For SSH mode, layer `compose.ssh.yaml` over the development Compose file, or
`deploy/docker-compose.ssh.yml` over the two production Compose files. The
override removes the local Docker socket and mounts only the selected SSH
configuration directory read-only.
```mermaid
sequenceDiagram
participant B as Browser
participant W as Open WebUI
participant R as Runtime
participant M as Model provider
participant G as Gateway
participant X as User workspace
Only Open WebUI publishes a host port. Runtime, Gateway, Postgres, and Redis
remain unpublishing services. Runtime and Gateway also join an egress-only
bridge so the model API and a future SSH Docker host are reachable without
exposing either service on the host.
B->>W: Authenticated chat request
W->>R: OpenAI-compatible request + service key + signed user identity
R->>R: Verify identity, build context, record run.created
loop Until evidence-backed completion or budget exhausted
R->>M: Recent context + tools + provider policy
M-->>R: Assistant content and/or tool calls
R->>R: Normalize, validate, limit, and schedule calls
R->>G: Tool request + service key + freshly signed identity
G->>G: Verify identity and bind user workspace
G->>X: Execute with resource and path constraints
X-->>G: Exit code, output, or file result
G-->>R: Structured tool result
R->>R: Persist events and evaluate completion evidence
end
R-->>W: SSE answer and completed tool detail blocks
W-->>B: Rendered Agent response
```
## Workspace file path
The identity sent by Open WebUI is verified once when Runtime accepts the
request. Runtime then signs the already verified identity again for every
Gateway call. This prevents a long Agent run from reusing an identity token
that expired while the model or a tool was working.
### Workspace file request
```text
browser with Open WebUI session
-> /api/v1/k1412/workspace/*
-> Open WebUI backend verifies the user
-> backend mints a short-lived signed identity JWT
-> Workspace Gateway verifies service key + user JWT
-> provider selects only that user's hashed container and volume
-> Open WebUI verifies the logged-in user
-> Web signs a short-lived user identity
-> Gateway verifies service key + signed identity
-> Gateway selects only the hashed container and volume for that user
-> browse, download, or streamed archive response
```
The file API exposes read-only browse, file download, and streamed directory
archive operations. Paths pass through the same `/workspace` normalization as
Agent tools. The browser never talks to Gateway or Docker directly.
The browser never receives a Gateway service key and never connects to Docker.
## Runtime internals
Runtime is an OpenAI-compatible provider from Open WebUI's point of view, but
normal chat completions are implemented by the K1412 loop:
- `ModelProvider` translates the internal model spec to a provider request and
normalizes streamed completion responses.
- `ContextPolicy` removes rendered tool-detail markup, prepends the system
contract and durable memories, and keeps the newest visible messages within
a per-model character budget.
- `ToolRegistry` declares tool schemas and routes workspace tools to Gateway or
state tools to `RuntimeStore`.
- `AgentLoop` owns iteration, tool normalization, validation, scheduling,
recovery, delegation, and evidence-gated completion.
- `RuntimeStore` persists run events, per-chat plans, and user memories.
More detail is in [agent-loop.md](agent-loop.md).
## Workspace architecture
`local-docker` and `ssh-docker` implement the same `ExecutionProvider`
contract. Production uses `ssh-docker`: Gateway talks to Docker on
`home-node-itx` through a dedicated SSH configuration mounted read-only.
Each immutable Open WebUI user ID maps to a SHA-256-derived workspace ID and
therefore to exactly one:
- container named `k1412-ws-<workspace-id>`;
- named volume `k1412-ws-data-<workspace-id>`;
- bridge network `k1412-ws-net-<workspace-id>`.
Containers run as UID/GID 1000 with a read-only root filesystem, all Linux
capabilities dropped, `no-new-privileges`, PID/CPU/memory limits, no Docker
socket, and no published ports. `/workspace` is the only persistent writable
filesystem. `/tmp` is writable but mounted `noexec`.
Python environments live at `/workspace/.venv`. User-level home and package
caches live below `/workspace/.agent`. The image puts the virtual environment
and user binary directories first on `PATH`. Commands run under Bash with
`pipefail`, so a failed install cannot be hidden by a successful `tail` or
similar pipeline stage.
When `WORKSPACE_IMAGE` changes to a new immutable tag, Gateway replaces a stale
container on its next access but reattaches the existing named volume. Image
upgrades therefore change the execution environment without deleting user
files.
## Networks and deployment
Production runs as one Unraid Compose Manager project:
- `public`: Web ingress;
- `internal`: private service-to-service traffic;
- `egress`: Runtime provider access and Gateway SSH access.
Only Web publishes NAS port `12004`. Nginx Proxy Manager on the VPS terminates
TLS for `agent.k1412.top` and forwards over Tailscale. Images are built for
`linux/amd64`, pushed to `docker.k1412.top/wuyang/*` with immutable
timestamp-and-commit tags, and deployed by updating only the relevant service.
The documentation portal is packaged inside the Web image at `/doc/`. It does
not add a public service, port, database, or proxy rule.
## Stable and experimental surfaces
Stable platform contracts:
- authenticated Web-to-Runtime request;
- signed Runtime/Web-to-Gateway identity;
- `ExecutionProvider` workspace semantics;
- per-user volume isolation;
- run-event persistence;
- public model IDs;
- workspace file API.
Expected experiment surfaces:
- prompt and context policy;
- memory selection;
- tool catalog and intent routing;
- scheduler and parallelism;
- delegation;
- recovery and evidence rules;
- model budgets and routing.
Version experiment-sensitive behavior in `run.created` so results remain
comparable after the implementation changes.