Bau dein eigenes Tiny-Agents-System
Concierge und Runner selbst gebaut: ein Router ohne LLM-Call, ein Agent mit frischem Kontext, eine harte Kompressionsgrenze. In acht Schritten, gegen einen beliebigen OpenAI-kompatiblen Endpunkt.
Ein Agent mit fünf Werkzeugen funktioniert. Ein Agent mit zweihundert nicht mehr
- und zwar aus zwei völlig verschiedenen Gründen, die dauernd in einen Topf geworfen werden. Der Baustein Tiny Agents erklärt diese beiden Gründe und die Architektur, die sie trennt. Dieser Kurs baut sie.
Am Ende hast du ein Verzeichnis tiny-agents/, in dem ein Concierge ohne
einen einzigen LLM-Aufruf entscheidet, wer eine Anfrage bearbeitet, und ein
Runner, der den gewählten Agenten mit frischem Kontext, seinen eigenen ein
bis fünf Werkzeugen und einem Budget startet, das nicht verhandelbar ist. Dazu
ein Artefakt-Speicher, der aus 38.000 Token gescraptem Text einen Digest von
800 macht, ohne den Rest wegzuwerfen.
Die Regel: kein Framework
Eine Regel hält den Kurs zusammen, und sie ist dieselbe wie in Bau dein eigenes PyTorch: Don't import it, build it.
Erlaubt sind ein HTTP-Client, ein YAML-Parser und NumPy. Also httpx (oder
requests), pyyaml, numpy. Wer will, nimmt zusätzlich tiktoken zum Zählen
- das ist Buchhaltung, nicht Architektur.
Verboten sind Agenten-Frameworks jeder Art: LangChain, LlamaIndex, CrewAI, AutoGen, smolagents, das Agents SDK. Sie würden dir genau die drei Bauteile abnehmen, um die es hier geht: Routing, Kontextverwaltung, Budget-Durchsetzung.
Ausdrücklich nicht verboten, aber nicht nötig: eine Vektordatenbank. Der Router dieses Kurses hält seine Beispiele in einer Python-Liste und rechnet Kosinus-Ähnlichkeit mit einem NumPy-Einzeiler. Bei ein paar hundert Beispielen ist das nicht die Sparversion, sondern die ehrliche: Du siehst dabei, dass Qdrant an dieser Stelle eine Optimierung ist und kein Baustein. Wann sie sich lohnt, steht am Ende von Kapitel 03.
Was du brauchst
Python 3.11 oder neuer. Alles andere ist eine pip install-Zeile.
Einen OpenAI-kompatiblen Endpunkt. Das ist die einzige externe Abhängigkeit
des Kurses, und es ist bewusst die schwächste mögliche: Alles, was
/v1/chat/completions und /v1/embeddings spricht, genügt. Lokal über
Ollama, gemietet über
OpenRouter, selbst gehostet über vLLM
oder LiteLLM. Der Kurs redet nie mit einem Anbieter-SDK, nur mit zwei URLs.
export TINY_BASE_URL="http://localhost:11434/v1" # Ollama lokal
export TINY_API_KEY="ollama" # Ollama ignoriert ihn, andere nicht
export TINY_CHAT_MODEL="qwen3:8b"
export TINY_EMBED_MODEL="bge-m3"
Ein Chat-Modell, das Werkzeugaufrufe beherrscht. Ab Kapitel 05 brauchst du
tools im Request. Kleine Modelle können das oft schlechter, als ihre
Modellkarte behauptet - wenn dein Runner reihenweise Geisteraufrufe zählt, ist
das erst mal ein Modellbefund und kein Bug in deinem Code. Genau deshalb zählt
Kapitel 05 sie überhaupt.
Ein mehrsprachiges Embedding-Modell. Das ist die eine Stelle, an der eine
falsche Wahl den ganzen Kurs kaputtmacht: Ein englischlastiges Modell wie
all-MiniLM-L6-v2 bricht beim Routing deutscher Anfragen ein, und du suchst den
Fehler stundenlang in deinem Schwellwert. Empfohlen ist bge-m3 - läuft
lokal in Ollama (ollama pull bge-m3) und liegt bei den meisten Anbietern
ebenfalls. Alternative: multilingual-e5-large, das aber Präfixe erwartet
(query: vor der Anfrage, passage: vor dem Beispiel). Wer die vergisst,
verliert Trefferqualität, ohne dass irgendetwas kaputtgeht - eine der
unangenehmeren Fehlerklassen.
Der Aufbau
Am Ende von Kapitel 08 sieht dein Repo so aus. Es wächst Kapitel für Kapitel
dorthin, du legst also jetzt nur tiny-agents/ und tiny/ an:
tiny-agents/ ← dein Repo
├── registry/ ← die Cards, ab Kapitel 02
│ ├── web-reader.card.yaml
│ ├── crm-writer.card.yaml
│ └── docs-finder.card.yaml
├── tiny/ ← das Paket
│ ├── __init__.py (leer)
│ ├── llm.py (03) OpenAI-kompatibler Client
│ ├── cards.py (02) Format und Validator
│ ├── index.py (03) Embeddings und Kosinus
│ ├── concierge.py (03, 04) der Router
│ ├── tools.py (05) die Werkzeug-Registry
│ ├── runner.py (05, 06) Invocation-Schleife
│ └── artifacts.py (07) Handle und expand()
└── scripts/
├── 01_token_vergleich.py
├── 03_router_eval.py
└── 08_abc.py
Jedes Kapitel endet mit einem lauffähigen Stand. Nicht mit einem grünen Test, sondern mit einem Befehl, den du eingibst, und einer Ausgabe, die du liest: eine Zahl, eine Rangliste, eine Ablehnung. Das ist Absicht - dieser Kurs baut ein System, dessen ganzer Wert an Zahlen hängt, die man vorher nicht kennt.
Was dieser Kurs bewusst nicht baut
Der Prototyp, nicht das Produktionssystem. Drei Dinge, die ein echtes Tiny-Agents-System braucht, kommen hier nicht vor, und das steht am Ende von Kapitel 08 noch einmal ausführlich:
- Traces in einer Datenbank. Der Kurs loggt nach stdout und in eine JSONL-Datei. Wer Routing-Entscheidungen über Wochen auswerten will, braucht Postgres.
- Learned Routing. Bestätigte Routings zurück in den Index zu schreiben, ist Phase 2 - und ohne Traces ohnehin nicht möglich.
- Gap-Clustering. Dass jeder Abstain die Roadmap für den nächsten Agenten ist, baust du in Kapitel 04 als Logzeile. Diese Logzeilen automatisch zu gruppieren, ist ein eigenes kleines Projekt.
Der Fachstoff hinter all dem steht in den sieben Kapiteln des Bausteins Tiny Agents, von „Zwei Probleme, zwei Größenordnungen“ bis „Was das kostet“. Du kannst den Kurs ohne sie fahren. Wer wissen will, warum eine Entscheidung so und nicht anders fällt, findet die Begründung dort.
Der Fahrplan
8 Schritte, je eine Einsicht und ein lauffähiger Stand. Jeder Schritt steht auf dem vorigen.
- 01Das Problem messen20 min
Werkzeugliste und Werkzeugausgabe sind zwei Probleme mit zwei Größenordnungen.
Meilenstein Ein Skript stellt die Token einer Werkzeugliste und einer einzigen gescrapten Seite nebeneinander, der Faktor steht als Zahl da.
- 02Die Capability Card25 min
Ein Artefakt ist gleichzeitig Registrierung, Doku, Routing-Index und Testfall.
Meilenstein Drei handgeschriebene Cards laufen durch den Validator, eine absichtlich kaputte wird mit lesbarer Meldung abgewiesen.
- 03Der Positiv-Index30 min
Geroutet wird Anfrage gegen Anfrage, nicht Anfrage gegen Beschreibung.
Meilenstein Für zwölf Testanfragen steht der richtige Agent auf Platz 1, Recall@1 wird als Zahl ausgegeben.
- 04Veto und Abstain20 min
Ein Router ohne Schwellwert routet auch Unsinn, die Ablehnung ist ein Feature.
Meilenstein „mach mir ein butterbrot“ wird ehrlich abgelehnt statt geroutet, und ein Counter-Example zieht seinen Agenten aus der Liste.
- 05Der Runner35 min
Die Isolation kommt vom frischen Kontext, nicht vom eigenen Prozess.
Meilenstein Ein Runner-Prozess bedient drei Cards mit je eigenem Kontext, ein Geisteraufruf wird erkannt und gezählt.
- 06Brief, Digest, Budget30 min
Ein Budget, das im Systemprompt steht, ist keins.
Meilenstein Eine Seite mit 38.000 Token kommt als Digest unter 800 Token zurück, mit genau einem Reparaturversuch am Schema.
- 07Der Artefakt-Speicher25 min
Kompression ist erst dann vertretbar, wenn sie rückholbar ist.
Meilenstein Eine Information, die im Digest fehlte, wird per expand() nachgeholt, ohne dass die 38.000 Token den Hauptkontext berühren.
- 08Messen, ob es was bringt25 min
Eine These, die nicht scheitern kann, ist keine.
Meilenstein Die eigene A/B/C-Kurve über wachsendes N steht als Tabelle da, auch „bringt hier nichts“ ist ein gültiges Ergebnis.