Files
zk-data-agent/docs/architecture.md
T

7.6 KiB

Architecture

Design objective

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.

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.

System context

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"]

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.

Responsibility boundaries

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

This separation lets the Web UI be upgraded on its own schedule while the Agent loop can iterate frequently.

Request lifecycle

Agent request

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

    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

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

browser with Open WebUI session
  -> /api/v1/k1412/workspace/*
  -> 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 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.

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.