Skip to work
All work
Flagship2026Capstone · All 8 milestones built and measured

Self-Improving Agent PlatformThe Closed Retraining Loop

A multi-tenant RAG-agent platform that measurably improves itself with no human in the retrain loop. Every trace is scored, failures are mined into eval cases, a router is retrained on-device, shadow-tested, and promoted only on measured lift.

Headline results

Cost per query
2.6¢ → 1.1¢
Quality held
92% → 92%
Unattended weeks
6 · $1.77
Tests
245

System architecture

System architecture diagram for self-improving-agent-platform
Fig. 1 — Self-Improving Agent Platform — system architectureFull size

Problem

Every LLM agent in production degrades or overspends, and the fix is always a human: someone reads the traces, notices the pattern, rewrites the prompt, swaps the model. That human is the bottleneck and the reason most agent projects stall. Nobody ships the loop that does it without them, because closing it means solving the hard half first, an objective quality signal you can promote on.

Approach

A multi-tenant platform in three planes. Serve is a grounded plan, retrieve, tool, critic agent on real AWS Bedrock whose inline citations are checked against what retrieval actually returned, with a sandboxed DuckDB tool it uses to run its own SQL before answering. Observe traces every request to SQLite and scores it two ways: an execution oracle that checks SQL answers by running them, and an LLM judge calibrated against that oracle rather than trusted on its own. Self-improve mines low-scoring traces into training data, retrains the router on-device, replays it in shadow for free, gates it behind an execution-oracle canary, and promotes only on measured dominance. A promotion log records every rejection, and rollback is one command.

Impact

Six unattended simulated weeks of support traffic on real Bedrock for $1.77 total: quality held at 92% while cost fell from 2.6¢ to 1.1¢ per query, a 54% reduction with no human in the retrain loop. The flywheel rejected its candidate twice for insufficient evidence before promoting at week 3, and the second rejection is the interesting one, because it triggered the bounded shadow sample that produced the missing evidence. Then it declined to churn when nothing further could be gained. 245 offline tests, a FastAPI backend, a Next.js chat and admin console, and a docker compose stack.

Decisions & tradeoffs

Pick a corpus whose answers are executable

DuckDB documentation won over SEC filings and FastAPI docs for one reason: SQL answers can be verified by running them. A well-memorized corpus lets the model answer from parametric memory and mask retrieval failure, and a judge-only signal is exactly what a self-improving loop learns to game.

Log the rejections, not just the promotions

Cycle 1 was rejected for insufficient evidence and that rejection ships in the promotion log. A flywheel that only records its wins is marketing. Keeping the rejections is what makes the promotion at week 3 mean something.

Call the first promotion what it is, a demotion

The policy that won was always-cheap, a declared-degenerate router that kills the waste the agent milestone had measured by hand. Dressing that up as learned intelligence would be dishonest; the honest read is that the loop found the cheapest correct answer and the escalation net still catches the rest.

Build spec

Corpus
DuckDB docs, 411 pages, pinned by commit sha
Retrieval
Dense + link graph, R@1 0.371 · R@10 0.843 · MRR 0.573 at ~11ms
Models
Claude Haiku 4.5 cheap tier · Sonnet 4.6 strong tier, on Bedrock
The curve
6 weeks · quality 92% → 92% · cost 2.6¢ → 1.1¢ · $1.77
Tests
245 offline · FastAPI + Next.js + docker compose

System notes

  • Execution-based oracle: SQL answers are scored by running them, not by asking another model, which is what stops the loop reward-hacking its own judge
  • The CI gate flips 92% green to 67% red on a deliberately worse prompt, and it caught a citation collapse an execution-only gate would have missed
  • The on-device reranker fine-tune was rejected correctly: it lifted recall@3, recall@10 and nDCG but regressed rank 1 from 0.357 to 0.314, so the dominance gate declined it
  • Every guardrail fired on a live run, including an injection blocked at $0.00 before it reached the model

What this does not show

  • Traffic is authored: 12 queries a week at ±8% granularity, so the curve demonstrates the loop rather than a trend.
  • One promotion event is not a trend, and the policy that won is honestly degenerate (always-cheap).
  • The golden eval is 12 cases with a starting-guess threshold; post-promotion grounding was 87.5% against 93.8% pre, which n=24 cannot resolve from noise.

Stack

AWS Bedrock · FAISS + BM25 · FastAPI · Next.js · MLX / torch on-device · SQLite tracing

View source on GitHub
Next project
Clinical LLM Bias Audit · The Geographic Disparity Index