Logbuch#control-center#agents#architektur#security
Ein AI-Team fürs Control Center — und warum der Wert außerhalb des Modells liegt
Von Niclas Hennrich · veröffentlicht · geschehen am
Selbst gebaut und in Betrieb genommen. Gehört zum Vorhaben HomeOS — Control Center mit drei Säulen.
- Tests grün (davon 179 neu)
- 720
- Tabellen fürs Agentensystem
- 14
- Echte Modell-Aufrufe bisher
- 0
Kurz zur Einordnung: HomeOS ist mein selbst gebautes Control Center fürs Homelab — aus dem Infrastruktur-NOC erwachsen, inzwischen mit drei Säulen: Infrastruktur, Haus (Smart Home) und Family/Haushalt. Bis zu diesem Eintrag war es fast vollständig eine Leseanwendung: genau ein schreibender API-Pfad, und der stellt die Wetter-Einstellung.
Was ich wollte: Eine „virtuelle Entwicklungsabteilung" im Control Center. Ein Lead, der seinen Bereich kennt und Arbeit zuschneidet; Worker, die genau einen Task umsetzen; ein unabhängiger Reviewer, der ihre Arbeit prüft. Und zwar nicht als Chat zwischen Agenten, sondern mit einem Zustand, der die Agenten überlebt.
Was ich verworfen habe, bevor eine Zeile Code entstand: den naheliegenden Bauplan — mehrere Coding-Agenten, die einander Texte schicken. Der hat drei Fehler, die man nachträglich nicht mehr repariert: Nach einem Neustart ist der Zustand weg. Niemand kann belegen, warum eine Aufgabe überhaupt entstand. Und ein überzeugend formulierter Absatz reicht, damit „fertig" behauptet wird.
Was ich stattdessen gebaut habe: sechs Bausteine, alle im vorhandenen Stack, keine Parallelarchitektur. 14 Tabellen für Domäne, Agent, Ziel, Idee, Finding, Task, Lauf, Review, Änderung, Entscheidung und so weiter. Eine State Machine mit elf Task-Zuständen, die ohne Datenbank und ohne Sprachmodell auskommt und für jeden Übergang zwei Fragen beantwortet: Ist er vorgesehen — und darf dieser Handelnde ihn auslösen? Eine Freigabegrenze mit Rollenrechten, Schreibbereichen, geschützten Pfaden und einer Kommando-Allowlist; die verbotenen Aktionen stehen einmal im Code und werden von dort in jeden System-Prompt eingesetzt. Eine Provider-Abstraktion mit einem Mock (deterministisch, ohne Netz, ohne Kosten) und einem echten Anbieter. Der Ablauf: Lead-Analyse, Worker im eigenen git-Worktree, Review gegen den echten Diff, Nacharbeitsschleife mit Obergrenze, Freigabe durch mich. Dazu eine Oberfläche mit Idea Inbox, Backlog, Review-Queue und Aktivitätsspur.
Die Voreinstellungen sind bewusst die harmlosen:
AGENT_PROVIDER=mock # echte Läufe nur nach ausdrücklichem Umschalten
AGENT_REPO_ROOT= # leer = Agenten fassen keine Datei an
AGENT_DRY_RUN=true # Zyklus entscheidet, führt aber nichts ausWo es geknirscht hat: dreimal, und alle drei sind lehrreich. Ein
Reparaturskript für deutsche Anführungszeichen sollte über die neuen Dateien
laufen und lief über das ganze Verzeichnis — 19 Bestandsdateien verändert,
per git checkout zurückgeholt. Ein Skript über einen Glob braucht dieselbe
Pfadprüfung wie ein Agent. Dann naive Zeitstempel: Unter PostgreSQL sind
Start und Ende zeitzonenbehaftet, unter SQLite in den Tests kommt der
Startwert naiv zurück, und die Subtraktion wirft. Und der Budget-Abbruch lief
ins Leere: Der Lauf fing die Budget-Ausnahme selbst ab, um sauber als
gescheitert gespeichert zu werden — und der Zyklus danach lief munter
weiter. Wer nach einer erreichten Grenze weitermacht, hat keine Grenze.
Wo es steht: umgesetzt und getestet, aber noch nicht ausgerollt. 720 Backend-Tests grün (541 Bestand, 179 neu), darunter der komplette Ablauf von der Idee bis zum Abschluss über die API. Das Frontend baut sauber, die Migration hinterlässt keinen Restdiff. Was es nicht gab: einen Live-Test gegen die laufende Installation auf optimus, eine Migration auf der produktiven Datenbank, einen einzigen echten Anthropic-Aufruf. Die API-Parameter sind nur statisch gegen das SDK geprüft. Ob die Modelle mit meinen Schemata praktisch zurechtkommen, zeigt erst der erste echte Lauf — den trage ich hier nach.
Was ich mitnehme:
- Der Wert liegt außerhalb des Modells. Persistenter Zustand, explizite Tasks, State Machine, isolierte Ausführung, unabhängiges Review, Tests, Freigabegrenzen — das ist die Substanz. Nimmt man sie weg, bleibt ein teurer Chat.
- Rechte gehören in Code, nicht in den Prompt. Ein Prompt ist eine Bitte, eine Assertion ist eine Bedingung. Die Werkzeuge laufen deshalb im eigenen Prozess: Der Anbieter erfährt, dass es ein Werkzeug gibt, und bekommt dessen Ergebnis — nie Dateisystemzugriff.
- Der Diff schlägt den Bericht. Was die Oberfläche als „Änderungen"
zeigt, kommt aus
git status, nicht aus dem Abschlussbericht des Agenten. Weichen beide voneinander ab, ist genau das der interessanteste Befund — und er wird dem Reviewer ausdrücklich vorgelegt. - Ein ehrlicher Mock ist zurückhaltend. Mein Mock meldet im Standard, dass er nichts geändert hat, und das Review endet mit „nicht prüfbar" statt mit einem erfundenen Bestanden. Ein Mock, der Erfolg simuliert, bringt einem bei, den Zahlen zu glauben.
- Worktrees statt Branch-Wechsel. Ein
git checkoutverändert das Arbeitsverzeichnis; zwei gleichzeitige Worker zögen einander den Boden weg. Ein Worktree je Task kostet ein Verzeichnis und löst das Problem, bevor es entsteht.