Skip to content

Three-Service Model

q15 is not a monolith. It is three services, each with a clear ownership boundary, that run together as one stack.

Service Owns Listens
q15-agent Prompt assembly, tool wiring, Telegram I/O, memory, file operations Telegram (long-poll)
q15-exec Command execution, session lifecycle, Nix package management :50051 (gRPC)
q15-proxy Credential injection, request mutation, TLS interception :50052 (proxy), :18080 (PAC)

q15-agent connects to q15-exec at q15-exec:50051. q15-exec connects to q15-proxy at q15-proxy:50052. The agent never talks to the proxy directly — the exec service routes outbound traffic through it.

A fourth service, q15-qdrant, stores embedding vectors when the embeddings tool is configured.

One stack = one q15-agent + one q15-exec + one q15-proxy, running together in Compose or Kubernetes. Optionally a q15-qdrant sidecar for embeddings.

In Kubernetes, the supported topology is one namespace per q15 stack. Each stack contains its own ConfigMaps, Secrets, and persistent volumes. The namespace is the isolation boundary.

Every stack has persistent volumes for:

Path Purpose
/workspace Durable project tree and working files
/memory Agent identity, semantic knowledge, working state, history
/skills Installed skill artifacts
/nix Nix store and fetched packages (keeps builds warm across sessions)
/var/lib/q15/proxy Proxy-owned durable state

/workspace may start empty on first deploy. That is a valid initial state. It is expected to persist long-term and survive restarts and upgrades.

  1. User sends a Telegram message — The message arrives at q15-agent via long-polling.
  2. Prompt assembly — The agent assembles context from core memory files, working memory, and conversation history.
  3. Model selection — Capabilities are inferred from the request. Models that cannot satisfy the requirements are filtered out. The remaining models are tried in configured preference order.
  4. Tool execution — Tool calls from the model are executed by the agent. Shell commands go through q15-exec, which routes egress through q15-proxy.
  5. Persistence — The completed turn is written to /memory/history/ as a JSON file. Working memory may be updated.
  6. Response — The agent sends the final response back to Telegram.

Interactive auth is handled separately by q15-auth, an operator tool that runs on your machine, not inside the runtime containers. It produces auth.json, which gets mounted into the agent container.