Skip to content

Overview

KRONOS orchestrator mark

KRONOS — agentic orchestrator · time · agents · control

A local-first, full-stack platform for building, running, evaluating, and fine-tuning multi-agent AI systems
a visual canvas, production RAG, per-agent fine-tuning, and an agent that reviews and patches codebases, all wired end-to-end.

Documentation site Source: private License: Apache-2.0 Python 3.12+ Backend Frontend Local-first

[!IMPORTANT] This repository is a case study, not the source. KRONOS's implementation lives in a private repository. What you'll find here is the architecture, the decisions and their reasoning, the data contracts, the screenshots, and a handful of verbatim code excerpts — everything needed to evaluate the engineering without publishing the codebase. See Source access if you need to read it properly.

Every screenshot below is from a live local instance — not mockups. The backend runs on Ollama by default (no keys, no cost, no data egress); OpenAI, Anthropic, Gemini, Mistral, and OpenRouter are one opt-in key away. See docs/adr for the reasoning behind that and every other major decision.

New here? Read the Guidebook — setup plus a hands-on tour of every feature.

134 backend source files, mypy --strict clean · 96 offline tests green (pytest -m "not live") plus a live suite against a real Ollama daemon · 9 ADRs · 12 ingestible source types · 5 agent reasoning strategies · 6 LLM providers · 8 frontend routes

Those first two numbers are the ones worth checking, so the raw output of the type-check, lint, and test runs behind them is reproduced in docs/evidence rather than asserted with a badge you can't click through to.

Contents

Why this exists

Most agent frameworks assume a cloud API key and hide their machinery behind an SDK. KRONOS was built to do the opposite on both counts: default to running entirely on your machine (ADR-0003), and own the full stack rather than wrap one — a native multi-provider LLM adapter instead of a LangChain dependency (ADR-0002), a hand-rolled hybrid retriever instead of a vector-DB SaaS, a workflow engine you can read top to bottom.

An adapter with no API key never silently falls back or mocks a response — it reports itself unconfigured and tells you exactly what to set. That "no mocks" rule extends to the test suite: the live-marked tests hit a real Ollama daemon, not a stub.

Architecture

flowchart LR
    Browser(["Browser"]) <--> FE

    subgraph FE["Frontend — Next.js 15 · React 19 · TypeScript"]
        direction TB
        Canvas["Canvas / Orchestrator<br/>React Flow, live WS state"]
        Screens["Fine-tune · Data · Import<br/>Run History · Router"]
    end

    FE <-->|"REST + WebSocket"| API["aop.api — FastAPI"]

    API --> Supervisor["Supervisor<br/>capability routing"]
    Supervisor --> Agents["5 agent strategies<br/>ReAct · Plan-Execute · Reflexion<br/>CRITIC · Tool-calling"]
    Agents --> Tools["MCP tool registry"]
    API --> Workflow["Workflow DAG engine<br/>native asyncio + LangGraph"]

    Tools --> RAG["Hybrid RAG<br/>Qdrant + BM25 → RRF → re-rank"]
    Tools --> Mem["Conversation memory"]
    Tools --> WH["DuckDB warehouse"]

    API --> FT["Fine-tuning<br/>LoRA · QLoRA · DPO · RLHF"]
    API --> Eval["Eval harness<br/>golden suites, CI gate"]
    API --> Import["Project import<br/>static + AST + LLM review → apply"]

    Agents --> LLM["Unified LLM adapter"]
    FT --> LLM
    LLM --> Ollama["Ollama (local, default)"]
    LLM --> Cloud["OpenAI · Anthropic · Gemini<br/>Mistral · OpenRouter"]
    LLM --> Tuned["Fine-tuned registry models"]

    RAG --> Qdrant[("Qdrant")]
    WH --> DuckDB[("DuckDB")]
    Mem --> PG[("Postgres")]

Live agent state reaches the browser over Redis Streams, not raw pub/sub — deliberately, so a WebSocket client that connects after a run starts still replays every step from the beginning instead of missing the early ones (ADR-0007).

See it running

Canvas — build an agent, watch it run live

Canvas with a tool-calling agent node added from the palette Canvas showing a completed live run with trace, tool call, and grounded answer

Click an agent onto the canvas, give it a task, hit Run. The run above is real: a tool_calling agent invoking the native rag_answer tool against a Qdrant collection ingested from this repo's own docs, with token counts, the tool call, and the grounded answer streaming into the Inspector live over the WebSocket.

Orchestrator — multi-agent workflows as a DAG

Orchestrator canvas showing a 4-node research-team workflow

Agents become nodes in a directed graph. This research-team workflow fans out to a react researcher and a critic reviewer, then converges through a reflexion writer and editor — each node's output addressable in the next via {node_id} templating. It runs level-parallel on a native asyncio engine or an interchangeable LangGraph StateGraph backend.

Agents — a library of reasoning strategies, and a wizard to add your own

Agent Library showing the five built-in agent strategies New agent wizard, strategy selection step

Five agent strategies ship out of the box. The New Agent wizard persists a custom agent — provider, model, temperature, system prompt, tool allowlist — that becomes a droppable, independently-tunable node everywhere in the app, immediately.

Fine-tune — LoRA/DPO training, for real, on your machine

Fine-tune control panel showing dataset split, training config, and eval metrics

Build a train/val split from any dataset, configure LoRA / QLoRA / DPO / RLHF, and launch a real training subprocess that streams its log live. The model registry versions every run and serves it as a chat model (name@vN) — indistinguishable, to the rest of the platform, from any other provider.

Data Infrastructure — 12 source types, one pipeline

Data Infrastructure page showing all six systems green and two live Qdrant collections

CSV, JSON, Parquet, SQL, Mongo, PDF, HTML, transcripts, BigQuery, and Snowflake all funnel through the same Source → Chunk → Embed → Index pipeline into a dual dense+sparse index and a DuckDB warehouse.

Project Import & Auto-Improvement — an agent that reviews (and patches) code

Project Import report showing ruff findings and LLM-generated code review findings

Point it at a path or a git URL; it runs ruff + mypy, AST complexity metrics, a dependency audit, ML-data-leakage heuristics, and an LLM code review — on an isolated copy, never the original. The run above is genuine: KRONOS analyzing one of its own modules, catching a real hash-collision bug in a Dedupe transform and missing exception handling in an HtmlStrip parser.

Run History — every run persisted, replayable, exportable to a dataset

Run History showing a list of past runs and a replayed trace

Every run is persisted with its full trace and its resolved provider/model/temperature, for reproducibility. Select a batch of successful runs and export them straight into a fine-tuning dataset — the platform's own usage becomes its own training data.

LLM Router — one interface, six providers

LLM Router showing provider reachability and routing fallback order

Ollama is the default and needs no key. Cloud providers are opt-in — paste a key in the UI and it's live immediately via a runtime keystore, no restart. Fine-tuned registry models are just another provider in the list.

What this demonstrates

AI/ML Engineering - A multi-provider LLM adapter (Ollama, OpenAI, Anthropic, Gemini, Mistral, OpenRouter) behind one typed interface — chat, streaming, embeddings, native function calling, model listing, health — all real HTTP, with a typed error hierarchy, no SDK wrapper. - Five agent reasoning strategies — ReAct, Plan-and-Execute, Reflexion, CRITIC, and native tool-calling — each emitting the same structured trace contract, so a Supervisor can route between them by capability. - Hybrid RAG: Qdrant dense vectors and a BM25 sparse index fused with weighted Reciprocal Rank Fusion, Cohere/cross-encoder re-ranking, and a RAPTOR hierarchical-summary tree built with deterministic numpy KMeans instead of the paper's UMAP+GMM stack. - Fine-tuning that actually runs: LoRA and DPO complete on CPU; QLoRA and RLHF are implemented and GPU-gated, not stubbed. - An eval harness with deterministic graders (`contains`, `regex`, `tool_called`, `min_words`) that gates on a minimum pass rate — "did this change help" answered mechanically, not by vibes.
Data Engineering - 12 ingestible source types — CSV, JSON, JSONL, Parquet, SQL, MongoDB, PDF, HTML, transcripts, plain text, BigQuery, Snowflake — across 5 connector modules feeding one ingestion pipeline. - DuckDB does double duty as both the file-reading engine (native `read_csv_auto`/`read_json_auto`/`read_parquet`, no `pyarrow` dependency) and the analytical warehouse — one engine, two jobs. - Dual indexing (Qdrant dense + file-persisted BM25 sparse) behind 4 chunking strategies, including true late chunking via local token-level embeddings, not a pooled-vector approximation. - Kafka/Redpanda streaming ingestion; schema-evolving batched warehouse writes (`ALTER TABLE` on new columns) with incremental quality-metric accumulation, so memory stays bounded regardless of dataset size.
Software Engineering - `mypy --strict` clean across 134 backend source files; `ruff` (pyflakes, isort, pyupgrade, bugbear, comprehensions, simplify, async-lint, pydocstyle) as linter and formatter. - 96 offline unit/integration tests, plus a separate `-m live` suite that exercises a real Ollama daemon — no mocks anywhere, including the tests. - CI matrix on Python 3.12 + 3.14: backend (lint, format-check, strict type-check, test) and frontend (lint, typecheck, production build) as independently gated jobs. - Typed contracts end-to-end: Pydantic models generate the JSON-Schema contracts under [`docs/schemas`](schemas/README.md), mirrored by hand-written TypeScript types on the frontend. - 9 ADRs recording the reasoning behind each architectural decision, not just the result — e.g. why Redis *Streams* and not pub/sub for the run event bus ([ADR-0007](adr/0007-canvas-ui.md)).
R&D - **Project Import & Auto-Improvement**: an agent that statically analyzes, LLM-reviews, and patches arbitrary codebases on an isolated copy — including, as shown above, its own. - **Run-history → dataset flywheel**: successful runs export straight into an SFT dataset, train, register, and come back as a servable agent — a closed loop from inference to training data to a new model. - A structured, JSON-first router for agent dispatch (LLM proposes JSON → parse → regex/substring fallback → deterministic default) with every routing decision logged — an inspectable policy, not an LLM black box.

Code excerpts

The source is private, so three files are reproduced in snippets/ verbatim and unedited — enough to judge how the code is actually written, without publishing the codebase.

Excerpt What it shows
fusion.py Weighted Reciprocal Rank Fusion — how dense (Qdrant) and sparse (BM25) results merge into one ranking without comparable score scales. Pure, 57 lines, no I/O.
graders.py The deterministic eval graders. No LLM judging, so a given agent output always scores identically.
llm_adapter_base.py The abstract LLMAdapter every provider subclasses — the seam that makes swapping Ollama for Anthropic a config change rather than a code change (ADR-0002).

They're representative rather than flattering: typed throughout, docstrings that state contracts instead of restating parameter names, and typed errors that surface an unconfigured provider as UNCONFIGURED with a fix path rather than silently mocking a response.

Tech stack

Layer Stack
Backend Python 3.12+, FastAPI, Pydantic v2, Typer CLI, structlog, httpx
Frontend Next.js 15 (App Router), React 19, TypeScript 5, React Flow (@xyflow/react), zustand
LLM providers Ollama (default) · OpenAI · Anthropic · Gemini · Mistral · OpenRouter
Retrieval Qdrant (dense) · rank_bm25 (sparse) · Cohere / cross-encoder re-ranking
Data DuckDB (warehouse) · Postgres (metadata + memory) · Redpanda/Kafka (streaming) · MongoDB
Orchestration Redis Streams (run bus) · native asyncio DAG engine · LangGraph backend
Fine-tuning PEFT · TRL · transformers · torch
Observability Langfuse v2 (self-hosted) · structlog
Quality ruff · mypy --strict · pytest · ESLint · tsc · GitHub Actions

How it runs

There's no git clone for this repository — it holds no application code. The steps below are the real setup from the private repo, included because how a system is operated is part of its design: one bootstrap script, a local model, and no cloud account anywhere in the critical path.

# 0. Prerequisites: Ollama running with the default models
ollama pull llama3.2:3b
ollama pull nomic-embed-text

# 1. One-shot bootstrap: venv + install + .env + diagnostics
.\scripts\bootstrap.ps1

# 2. Validate the environment
.\.venv\Scripts\aop.exe diagnose

# 3. Talk to the local model through the unified adapter
.\.venv\Scripts\aop.exe chat "Explain RAG in one sentence."

# 4. Bring up the data stack, backend, and canvas
docker compose up -d
.\.venv\Scripts\aop.exe serve          # http://127.0.0.1:8000
cd frontend; pnpm install; pnpm dev    # http://localhost:3000

POSIX users: ./scripts/bootstrap.sh (set PYTHON=python3.12 if needed). The Guidebook walks the same path in full, including what each service is for and how to verify it came up correctly.

Source access

KRONOS is a personal R&D project kept in a private repository. It isn't a product and isn't accepting contributions, but the source is available for review on request — for hiring processes, technical due diligence, or a collaboration that warrants it.

Reach me at github.com/YousefHlaly and say what you'd like to look at. Read access to the private repository is straightforward to arrange; a guided walkthrough of a specific subsystem is usually more useful and I'm happy to do that instead.

In the meantime, the material here is the honest version of the same thing: the ADRs record why each decision went the way it did (including the ones that didn't work out), docs/evidence has the raw quality-gate output, and snippets/ has real, unedited code.

Capability map

Phase Scope Status
0 Environment bootstrap — unified LLM adapter, diagnostics, project scaffold Done
1 Data infrastructure — 12 source types, 4 chunkers, Qdrant + BM25, DuckDB, streaming Done
2 RAG + memory — hybrid retrieval with RRF, re-ranking, scoped + episodic memory Done
3 Orchestrator engine — MCP tools, agent strategies, supervisor, Langfuse, FastAPI Done
4 Canvas UI — React Flow, live run state via Redis Streams + WebSockets Done
5 Fine-tuning control panel — LoRA/DPO real, QLoRA/RLHF GPU-gated, eval, registry Done
6 Project import & auto-improvement — static + AST + leakage + LLM review/apply Done

Beyond Phase 6, shipped and verified: native function calling and a tool_calling agent strategy; a multi-agent workflow DAG engine with a native and a LangGraph execution backend; custom agents with per-node/per-run config overrides; an OpenRouter provider with a runtime API-key store and a searchable model browser; run cancellation, reproducibility stamping (resolved provider/model/temperature), and enforced-read-only warehouse access; per-run token budgets; a structured JSON-first router with logged decisions; and the golden-suite eval harness described above. See the per-phase ADRs in docs/adr and runbooks in docs/runbooks for the phased history.

Documentation

Everything below is also published as a searchable site at yousefhlaly.github.io/kronos-showcase.

Guidebook Setup plus a hands-on tour of every feature. Start here.
Architecture decisions 9 ADRs — the reasoning behind each choice, not just the result.
Operational runbooks How each phase is actually run and verified.
Data contracts 34 JSON Schemas generated from the Pydantic models.
API reference The FastAPI surface.
Code excerpts Three real source files, verbatim.
Evidence Raw type-check, lint, and test output behind the quality claims.

Backend and frontend implementation notes live with the source, in the private repository — see Source access.

License

The KRONOS source is licensed Apache-2.0. This repository carries the same licence, covering the documentation and the code excerpts reproduced here.

Screenshots are of a local instance and contain no third-party or user data.