# finance-agent XMPP-erreichbarer Codex-Agent für Finanzen (`finance@bot.0ff.space`), nach demselben Muster wie `agent@`/`builder@bot.0ff.space` auf blunix (`hosts/blunix/localServices/agent-codex/`), aber nur eine Rolle, nur für den Owner erreichbar, mit Schreibrecht auf ihr eigenes Arbeitsverzeichnis statt eines Git-Commit-Workflows. ## Architektur ``` XMPP-Nachricht (Text oder ein von Monal hochgeladener Anhangs-Link) an finance@bot.0ff.space → finance-xmpp-listener.service (go-sendxmpp --listen | listener.py) → Queue: /var/lib/finance-agent/inbox/*.json → systemd.path löst finance-agent-worker.service aus → codex exec --sandbox workspace-write -C /home/drone/finance-agent --add-dir /home/drone/finance-agent ... → Antwort per go-sendxmpp zurück an lukas@0ff.space ``` `listener.py` ist eine unveränderte Kopie von `hosts/blunix/localServices/agent-codex/listener.py` (rein umgebungsvariablengetrieben, keine Codex-Spezifika). `worker.py` ist eine abgespeckte Variante von `agent-codex/worker.py`: gleiche Queue-/Sitzungs-/Debounce-Mechanik, aber `--sandbox workspace-write` statt `read-only` und ohne Builder-Handoff/Git-Logik -- dieser Agent committet nichts, er pflegt einfach Dateien in seinem eigenen Arbeitsverzeichnis. ## Was hier fehlt und noch von Hand ergänzt werden muss Dieses Modul bereitet nur die Plattform-Seite vor (XMPP-Konto, Secret, Listener/Queue/Worker-Verdrahtung, Verzeichnis). Damit der Agent tatsächlich antwortet, fehlen noch zwei Dinge, die nicht deklarativ in diesem Repo passieren: 1. **`codex login` als `drone` auf pinix**, einmalig, interaktiv -- erzeugt `/home/drone/.codex/auth.json`, von dort kopiert `prepareCodexHome` in `../finance-agent.nix` es bei jedem Worker-Lauf in den isolierten `CODEX_HOME` der Rolle. 2. **`/home/drone/finance-agent/finance-agent.md`** (plus alles sonst, was die Rolle braucht -- Rechnungen, CSVs, Vorlagen). Dieses Verzeichnis wird von der Nix-Aktivierung leer angelegt (`systemd.tmpfiles.rules`, `0700 drone`); der eigentliche Inhalt ist Lukas' eigenes, lokal gebautes Repo, hierher kopiert (erledigt am 31.07.2026, per `rsync` von tnix). `worker.py`s `FIXED_PROMPT` weist Codex an, zuerst vollständig `finance-agent.md` in diesem Verzeichnis zu lesen -- das definiert Rolle, Aufgabenbereich und Grenzen des Agenten vollständig; hier wird nichts Fachliches vorausgesetzt oder dupliziert. Bis beides erledigt ist, schlägt `finance-agent-worker.service` beim ersten Trigger fehl (fehlendes `auth.json` bzw. fehlendes `finance-agent.md`) -- erwartet, kein Fehler in diesem Modul. Der Listener funktioniert davon unabhängig schon vorher: Nachrichten landen zuverlässig in `/var/lib/finance-agent/inbox/`, auch wenn der Worker sie noch nicht verarbeiten kann. ## Anhänge (Rechnungsscans) Kein Sonderfall nötig: Monal lädt Dateien über Prosodys `httpFileShare` (`upload.0ff.space`) hoch und schickt den Link als normalen Nachrichtentext -- landet unverändert im `body`-Feld des Queue-Eintrags (mit einem `.HEIC`-Upload verifiziert). `finance-agent.md` kann Codex anweisen, in `body` enthaltene `upload.0ff.space`-Links herunterzuladen (`curl` steht im PATH des Workers) und auszuwerten. ## Zugriff `AGENT_ALLOWED_SENDERS` ist fest auf `lukas@${domain}` beschränkt (kein `@domain`-Wildcard wie bei `agent@`) -- bewusst, da es um private Finanzdaten geht. Keine MUC-Anbindung. ## State-Verzeichnisse (`/var/lib/finance-agent/`) Gleiches Muster wie `agent-codex`: `inbox/`, `processing/`, `failed/`, `sessions/`, `senders/`, `codex-home/`, `home/`. Kein `builder-*`-Äquivalent -- es gibt nur eine Rolle.