Buchhaltungsbutler-Agent: autonome Kontierung & Verbuchung mit Schwellenwerten
  • Python 82.8%
  • Shell 17.2%
Find a file
2026-04-27 00:35:00 +02:00
.claude feat: BB-Controller (Opus) als Supervisor — eigene tmux, /bb-control für Health/Plausibilität; Worker (start.sh) defaultet auf Sonnet 2026-04-27 00:35:00 +02:00
bb_mcp feat(validators): max_posting_age_days konfigurierbar via config.yml (Default 90, vorher hardcoded) 2026-04-27 00:24:16 +02:00
knowledge init: BB-Agent skeleton (MCP server, sync, watchdog, knowledge base) 2026-04-26 23:09:28 +02:00
scripts feat: BB-Controller (Opus) als Supervisor — eigene tmux, /bb-control für Health/Plausibilität; Worker (start.sh) defaultet auf Sonnet 2026-04-27 00:35:00 +02:00
.env.example feat: BB-Controller (Opus) als Supervisor — eigene tmux, /bb-control für Health/Plausibilität; Worker (start.sh) defaultet auf Sonnet 2026-04-27 00:35:00 +02:00
.gitignore feat: structured file logging (rotating); README ohne 1Password, mit Logging-Anleitung 2026-04-26 23:39:18 +02:00
.mcp.json fix(mcp): MCP-Server-Config in .mcp.json (kanonisch); cwd-Variable raus; bb_search_similar in allow-Liste 2026-04-27 00:18:09 +02:00
CLAUDE.md feat: RAG with 3 swappable embedding backends (Voyage/OpenAI/local Gemma) + bb_search_similar tool 2026-04-26 23:54:58 +02:00
config.yml feat(validators): max_posting_age_days konfigurierbar via config.yml (Default 90, vorher hardcoded) 2026-04-27 00:24:16 +02:00
CONTROLLER.md feat: BB-Controller (Opus) als Supervisor — eigene tmux, /bb-control für Health/Plausibilität; Worker (start.sh) defaultet auf Sonnet 2026-04-27 00:35:00 +02:00
LICENSE license: AGPL-3.0; README: Troubleshooting-Zeilen entfernt 2026-04-27 00:08:20 +02:00
pyproject.toml license: AGPL-3.0; README: Troubleshooting-Zeilen entfernt 2026-04-27 00:08:20 +02:00
README.md feat: BB-Controller (Opus) als Supervisor — eigene tmux, /bb-control für Health/Plausibilität; Worker (start.sh) defaultet auf Sonnet 2026-04-27 00:35:00 +02:00
uv.lock feat: RAG with 3 swappable embedding backends (Voyage/OpenAI/local Gemma) + bb_search_similar tool 2026-04-26 23:54:58 +02:00

BB-Agent — Buchhaltungsbutler Auto-Kontierung

Ein lokal laufender Agent, der offene Bankumsätze und Belege in Buchhaltungsbutler (BB) autonom kontiert und verbucht. Mitarbeiter pflegen Belege/Umsätze weiterhin manuell ein — der Agent übernimmt nur die Buchungslogik.

Sicherheitsmodell: Vollautonom mit Schwellenwerten — sichere Fälle direkt verbuchen, unklare in eine lokale Review-Queue, niedrige Konfidenz wird eskaliert. Erste 1-2 Wochen läuft alles im DRY_RUN-Modus (keine BB-Schreibvorgänge), damit du die Vorschläge vor der Aktivierung kalibrieren kannst.

Wie es funktioniert

Cron (alle 15min) ─→ Trigger-Datei  ──┐
                                      ▼
                       tmux-Session mit Claude Code (im /loop)
                                      │
                       ┌──────────────┴──────────────┐
                       ▼                             ▼
                 bb_mcp Tools                Wissensbasis
                 ├─ list/get/search          ├─ SKR03/04
                 ├─ propose (review-queue)   ├─ Änderungen 2026
                 └─ commit (BB-API)          └─ Eigene Regeln
                       │
                       ▼
                BuchhaltungsButler API
                (HTTPS Basic + api_key)

Pro Tick (Verarbeitungsrunde):

  1. Offene Posten holen (Umsätze + Belege ohne Verbuchung)
  2. Vendor-Historie und Wissensbasis konsultieren
  3. Kontierung vorschlagen (Konten, USt, Buchungstexte, ggf. Splits)
  4. Konfidenz schätzen + validieren (Konto existiert, Periode offen, Idempotenz, Caps)
  5. Verzweigung: ≥0.90 commit · 0.60-0.90 review-queue · <0.60 escalate
  6. Audit-Log + Heartbeat

Voraussetzungen

OS macOS (Apple Silicon getestet); Linux mit minimalen Anpassungen
Tools Homebrew, uv, tmux, Claude Code
Account Claude.ai-Subscription mit Claude Code
BB-Zugang Buchhaltungsbutler ab Plan Buchhaltung Pro (API verfügbar). API-Credentials: API Client, API Secret, API Key — zu finden in BB → Einstellungen → API

Installation

# 1) Voraussetzungen (macOS)
brew install uv tmux

# 2) Repo klonen
git clone https://git.mngd.io/patrick/bb-agent.git ~/projects/bb-agent
cd ~/projects/bb-agent

# 3) Abhängigkeiten
uv sync

Konfiguration

.env mit BB-Credentials

cp .env.example .env
# .env in einem Editor öffnen und ausfüllen:
#   BB_API_CLIENT=...
#   BB_API_SECRET=...
#   BB_API_KEY=...
#   MANDANT_NAME=meine_gmbh    # nur fürs Logging

.env ist in .gitignore — wird nie committet.

config.yml: Schwellenwerte und Sicherheitsgeländer

thresholds:
  auto_post_confidence: 0.90       # ≥ → direkt verbuchen
  review_confidence: 0.60          # < → eskalieren
guards:
  max_amount_auto_post: 5000       # Cap deckelt Konfidenz auf 0.85
  blocked_accounts: ["1200","1210","1800"]  # Bank/Kasse — nie hier buchen
  require_receipt_for_expenses: true        # keine Aufwandsbuchung ohne Beleg
  hard_max_postings_per_hour: 50            # Notbremse
  max_posting_age_days: 90                  # ältere Buchungen → abgelehnt
dry_run: true                               # solange true: keine BB-Writes

Konfidenz-Bänder

Konfidenz Verhalten
auto_post_confidence direkt verbuchen (nur wenn dry_run: false)
zwischen den Schwellen Vorschlag in review_queue — manuell via /bb-review
< review_confidence Eskalation in errors, kein Vorschlag

Konfidenz-Berechnung

LLM-Selbsteinschätzung + Validator-Anpassungen:

Bedingung Δ
Vendor bekannt (count > 5) und Betrag in ±2σ +0.10
Vendor unbekannt 0.20
Betrag > 2σ vom Vendor-Mittel 0.20
Belegtext widerspricht historischem Konto 0.30
Betrag > max_amount_auto_post Cap auf 0.85 (erzwingt Review)

Tuning-Hinweise

Setting Default Wann anders setzen
auto_post_confidence 0.90 Pilot mit 0.95 starten, später Richtung 0.85 wenn High-Confidence-Vorschläge sauber sind
review_confidence 0.60 auf 0.50 wenn viele Vorschläge bei 0.500.65 hängen
max_amount_auto_post 5000 im Pilot bei ~500 starten, schrittweise hochziehen
blocked_accounts siehe oben Pflicht anzupassen an dein SKR (siehe bb_mcp.skr_detect-Output): SKR03 → 1200/1210 Bank, 1000 Kasse, 1800 Privatentnahmen — SKR04 → 1800 Bank, 1600 Kasse
require_receipt_for_expenses true nur auf false wenn du bewusst auf den Belegzwang verzichten willst (steuerlich riskant)
hard_max_postings_per_hour 50 bei sehr hohem Buchungsvolumen hochziehen
max_posting_age_days 90 730 bei aktiven Vorjahres-Korrekturen, 35 bei strenger Monats-Schließung

dry_run und Aktivierungspfad

dry_run: true ist der sichere Default — alle Vorschläge gehen in review_queue, keine BB-Writes. Der PreToolUse-Hook in Claude Code blockt bb_commit_*-Aufrufe direkt.

Pfad zur Aktivierung:

  1. Pilot mit dry_run: true, Vorschläge täglich via /bb-review durchsehen
  2. Konfidenzen aus audit_log kalibrieren
  3. max_amount_auto_post klein setzen (z.B. 500)
  4. dry_run: false
  5. Cap schrittweise hochziehen, sobald committete Buchungen seit ≥1 Woche fehlerfrei laufen

Erster Lauf

Empfohlen: ein einziger Befehl macht alles — Voraussetzungen prüfen, beim Erst-Run SKR detecten + Historie syncen + (falls konfiguriert) Embeddings indexieren, tmux-Session aufmachen, Claude Code starten:

bash scripts/start.sh

Optionen:

Flag Wirkung
--bypass-permissions Claude Code mit --dangerously-skip-permissions — Tools ohne Approval-Prompts. Alternativ via BB_BYPASS_PERMISSIONS=true in .env persistieren.
--attach Nur an bestehende tmux-Session attachen (kein Neustart).
--session NAME tmux-Session-Name überschreiben (default bb-agent).
--skip-first-run Initialisierungsschritte überspringen, falls die DB neu angelegt wurde aber bewusst leer bleiben soll.

Manuell (wenn du nicht das Start-Skript nutzen willst):

uv run python -m bb_mcp.skr_detect              # SKR-Profil + Kontenrahmen-Cache
uv run python scripts/sync_history.py --full    # Historie (24 Monate)
tmux new -s bb-agent
claude --model claude-sonnet-4-6                # Worker im Projektverzeichnis

BB-Controller — optionaler Supervisor

Zwei-Modell-Setup: der Worker (scripts/start.sh) macht die Kontierungs-Arbeit mit Sonnet (schnell, günstig, ausreichend für Routinefälle). Der Controller (scripts/controller.sh) ist ein paralleler Supervisor mit Opus 4.7, der den Worker beobachtet, Vorschläge auf Plausibilität prüft und bei Bedarf den Worker wiederbelebt oder steuert.

bash scripts/controller.sh                       # eigene tmux-Session "bb-controller"
bash scripts/controller.sh --bypass-permissions  # für autonome Kontroll-Loops

Der Controller liest beim Start CONTROLLER.md und wartet dann auf Anweisungen oder /bb-control.

Was /bb-control macht (eine Kontroll-Runde):

  1. Health-Check: tmux-Session bb-agent aktiv? data/status.json aktuell? claude-Prozess am Leben?
  2. Plausibilität: Top-10 pending Vorschläge gegen historical_postings und chart_of_accounts_cache cross-checken — passt das Konto zum Vendor/Belegtext? Halluzinierte Konten?
  3. Diagnose: Muster-Erkennung (immer derselbe Fehler? knowledge/regeln.md erweitern?)
  4. Empfehlung (max. 6 Zeilen) + Vorschlag für eine nächste Aktion. Aktionen werden erst nach User-OK ausgeführt:
    • Worker-Restart: tmux kill-session -t bb-agent && bash scripts/start.sh
    • Tick erzwingen: tmux send-keys -t bb-agent '/bb-tick' Enter
    • Klärfrage in den Worker tippen
    • oder: nichts tun

Hard rules für den Controller (in CONTROLLER.md festgeschrieben):

  • bucht nicht selbst (keine bb_commit_*)
  • ändert keine Daten in bookings.db (nur SELECT)
  • führt Aktionen nur mit User-Bestätigung aus

Modell-Override:

# Worker mit anderem Modell
BB_MODEL=claude-haiku-4-5-20251001 bash scripts/start.sh
# Controller mit anderem Modell
BB_CONTROLLER_MODEL=claude-sonnet-4-6 bash scripts/controller.sh

In Claude Code:

/bb-tick      # einen Tick manuell auslösen
/bb-status    # Heartbeat + Queue-Status
/bb-review    # Vorschläge interaktiv durchsehen + freigeben
/bb-sync      # Historie aktualisieren

Im DRY_RUN-Modus landen alle Vorschläge in data/bookings.db → Tabelle review_queue. Nichts wird in BB geschrieben.

Cron einrichten (Automatik)

bash scripts/install_cron.sh

Installiert drei Einträge in deiner User-Crontab:

  • */15 * * * * → Tick-Trigger
  • 0 */6 * * * → History-Sync
  • * * * * * → Watchdog (lokales Monitoring + macOS-Notification bei Stillstand)

Die tmux-Session muss laufen, damit der Agent die Tick-Dateien abarbeitet.

Logging und Audit

Der Agent loggt auf drei Ebenen — alles lokal, alles in data/:

1. data/logs/agent.log — Python-Anwendungs-Log

Was du hier findest: jeder BB-API-Call (Pfad, Status, Dauer; niemals Bodies/Secrets), jedes bb_propose_posting/bb_commit_*/bb_escalate mit Konto, Betrag und Konfidenz. Rotierend (5 × 5 MB).

tail -f data/logs/agent.log              # live mitlesen
grep ERROR data/logs/agent.log           # nur Fehler
grep COMMIT data/logs/agent.log          # nur echte Verbuchungen

Log-Level steuern: BB_LOG_LEVEL=DEBUG uv run python … für mehr Details.

2. data/logs/{tick,sync,watchdog}.log — Cron-Logs

Stdout/stderr der Cron-Jobs:

  • tick.log — Trigger-Generierung (jede 15min eine Zeile)
  • sync.log — Historie-Sync (alle 6h)
  • watchdog.log — Watchdog-Output

3. SQLite — data/bookings.db

Strukturierte Aufzeichnung der Agent-Entscheidungen:

# Alle Aktionen heute
sqlite3 data/bookings.db "SELECT ts, action, ref_type, ref_id, account, amount, confidence
  FROM audit_log WHERE ts > datetime('now','start of day') ORDER BY ts DESC"

# Eskalierte Fälle der letzten 7 Tage
sqlite3 data/bookings.db "SELECT ts, ref_id, message FROM errors
  WHERE ts > datetime('now','-7 days')"

# Pending Review-Queue mit Konfidenz absteigend
sqlite3 data/bookings.db "SELECT id, ref_type, ref_id, confidence, reason
  FROM review_queue WHERE status='pending' ORDER BY confidence DESC"

Schneller Status-Überblick:

uv run python scripts/status_cli.py

Was wird nicht geloggt

  • .env-Werte, API-Keys, HTTP-Bodies
  • Belegrohdaten (die bleiben in BB)
  • Inhalte der Markdown-Wissensbasis

Pilot-Phase und Aktivierung

  1. Woche 1-2: dry_run: true, alle Vorschläge täglich via /bb-review durchsehen. Konfidenzen tunen.
  2. Aktivierung: dry_run: false setzen, max_amount_auto_post: 500 als Anfangs-Cap.
  3. Schrittweise hochziehen: Cap erhöhen, sobald die committeten Buchungen seit 1 Woche fehlerfrei laufen.

Sicherheit

  • Belege bleiben in BB — werden nie ins lokale Repo gespiegelt.
  • GoBD-Trail: jede Buchung trägt eine justification (1-3 Sätze), die zusätzlich via /comments/add an die BB-Buchung gehängt wird.
  • Idempotenz: SHA-256-Hash aus (ref_id, account, amount, date) verhindert Doppelbuchungen.
  • Notbremse: hard_max_postings_per_hour stoppt den Agenten, falls er amok läuft.
  • PreToolUse-Hook: blockt schreibende Tools im DRY_RUN-Modus auf Claude-Code-Ebene.
  • Tool-Scope: Agent darf nur bb_mcp__*-Tools nutzen — andere globale MCP-Server (n8n, Gmail, Drive etc.) sind in .claude/settings.json deny-gelistet.

Semantische Suche (RAG, optional)

Die statistische Vendor-Map (vendor_account_mapping) reicht für wiederkehrende Lieferanten. Für Schreibvarianten, neue Vendors mit ähnlichem Pattern, Splits und Kostenstellen macht ein semantisches Retrieval mehr Sinn — der Agent ruft dafür das Tool bb_search_similar(query, k=5) auf, das die Top-k ähnlichsten historischen Buchungen via Cosine-Similarity über Embeddings liefert.

Drei Backends, alle optional, alle in .env umschaltbar:

Backend Setup Modell (Default) Dim Setup-Größe Pro Anfrage Privatsphäre
voyage API-Key voyage-3-lite 512 API-Roundtrip ~150 ms Texte verlassen den Host
openai API-Key text-embedding-3-small 1536 API-Roundtrip ~200 ms Texte verlassen den Host
local uv sync --group local google/embeddinggemma-300m 768 ~600 MB (einmalig) ~30 ms (CPU/M1) komplett offline

Anthropic hat keine eigene Embeddings-API. Die offiziell empfohlene Option für die "Anthropic-Welt" ist Voyage AI (Anthropic-Partner) → Backend voyage.

Aktivierung

# In .env eines wählen:
BB_EMBEDDING_BACKEND=local       # oder: voyage / openai
# bei voyage: VOYAGE_API_KEY=...
# bei openai: OPENAI_API_KEY=...
# Modell-Override optional via BB_EMBEDDING_MODEL=...

# Bei local einmalig:
uv sync --group local

# Index aufbauen:
uv run python scripts/reindex_embeddings.py            # nur neue/geänderte
uv run python scripts/reindex_embeddings.py --force    # alles neu (z.B. nach Backend-Wechsel)

Beim regulären scripts/sync_history.py werden neue Postings automatisch mit-indexiert.

Was wird embedded? Pro Buchung der Text "{vendor} | {posting_text} | D:{debit} C:{credit}". Wenn du später Belegtext-OCR oder Kostenstellen-Hinweise einbeziehen willst, anpassen in bb_mcp/embeddings.py:posting_embed_text.

Wann hilft RAG? Erst ab ~100+ historischen Buchungen mit unterschiedlichen Pattern. Bei deinem Demo (13 AfA-Buchungen) merkst du keinen Unterschied — sinnvoll wird es im Echtbetrieb.

Wissensbasis pflegen

In knowledge/regeln.md kommen deine eigenen Buchungsregeln rein, z.B.:

- Notion, Linear, GitHub → SKR04 6815 (Bürobedarf), VAT 19% (deutsche Anbieter) bzw. RC (USA)
- Bewirtung: 70/30-Split nach knowledge/bewirtungen.md

Je besser dein Agent die Konventionen kennt, desto präziser werden seine Vorschläge.

Troubleshooting

Symptom Ursache Fix
tmux: command not found brew shellenv nicht im PATH source ~/.zprofile oder neues Terminal
400 Bad Request von BB API-Endpoint braucht zusätzliche Pflichtfelder bb_mcp/server.py und scripts/sync_history.py prüfen
dry_run is true — refusing to commit richtig so erst nach Pilot dry_run: false setzen

Lizenz

Lizenziert unter der GNU Affero General Public License v3.0 (AGPL-3.0) — siehe LICENSE.

Kurz: du darfst den Code frei nutzen, modifizieren und weitergeben. Wenn du modifizierte Versionen über ein Netzwerk anbietest (z.B. als gehosteten Service), musst du den Quellcode deiner Modifikationen unter derselben Lizenz veröffentlichen.

Beitragen

Pull Requests willkommen — das Repo lebt unter https://git.mngd.io/patrick/bb-agent.