20 KiB
Buying Agent – Source & Discovery Specification v0.1
Status: implementierungsbereit
Spezifikationsversion: 0.1
Stand: 2026-10-04
Ergänzt: buying-agent-v0.1-spec-v1.1.md und buying-agent-architecture-addendum-v1.md
1. Zweck
Diese Spezifikation definiert den ersten real nutzbaren Discovery-Slice des Buying Agents.
Ziel ist, externe Produktsuchen automatisiert aus den Kriterien eines BuyingProjects abzuleiten, regelmäßig auszuführen, Ergebnisse dauerhaft zu verwalten, Veränderungen zu erkennen und die Treffer anschließend durch die eigene Buying-Engine zu bewerten.
Der erste Pilot erfolgt mit Geizhals, Kategorie Notebooks. Die Architektur darf jedoch nicht notebook-spezifisch sein.
BuyingProject
↓
Canonical Criteria
↓
Source Taxonomy + Mapping
↓
generierte Geizhals-Suche
↓
periodischer SearchRun
↓
persistierte Produkte + Beobachtungen
↓
Diff zum vorherigen Lauf
↓
NEW / CHANGED / MISSING / DISAPPEARED
↓
interne Constraints + Ranking
↓
Shortlist
↓
später Deep Enrichment
↓
später Decision
2. Fachliche Leitprinzipien
- Geizhals ist Discovery-Quelle, nicht Decision Engine.
- Die eigenen BuyingProject-Kriterien bleiben die fachliche Quelle der Wahrheit.
- Geizhals wird als möglichst starker Vorfilter genutzt.
- Nicht auf Geizhals abbildbare Kriterien bleiben interne Kriterien.
- Discovery, Ranking und Decision bleiben getrennte fachliche Stufen.
- Externe Filtertaxonomien werden on demand gelernt, nicht vollständig vorab katalogisiert.
- URL-Encoding und Filtersyntax dürfen nicht vom LLM erfunden werden.
- Produktidentität wird zunächst konservativ und pragmatisch behandelt.
- Bei Unsicherheit erfolgt keine automatische Zusammenführung.
- Suchläufe speichern strukturierte Zustände, keine HTML-Archive.
3. Scope v0.1
Enthalten
- Geizhals als erste Discovery-Quelle
- Pilotkategorie Notebooks
- On-Demand-Erfassung der Geizhals-Filtertaxonomie
- Speicherung von Source-Kategorien, Filterdefinitionen, Optionen und Wertebereichen
- Mapping zwischen Canonical Criteria und Source-Filtern
- reproduzierbare Generierung von Geizhals-Such-URLs
- periodische SearchRuns
- vollständige Ergebnisaufnahme einer aktiven Suche
- persistierte SourceProductReferences
- Historisierung sichtbarer Attribute und Preise
- Diffing zwischen Suchläufen
- Status
NEW,CHANGED,UNCHANGED,MISSING,DISAPPEARED - interne Bewertung der Kandidaten
- konfigurierbare Shortlist, Default 5
- defensives Fehler-/Backoff-Verhalten
- Tests
Nicht enthalten
- Frontend-Implementierung
- Keepa
- Idealo
- LLM-Automation
- automatische Kaufentscheidung
- Kaufautomatisierung
- Warenkorbmanagement
- Authentifizierung / RBAC
- Multi-User-UI
- automatische Deep-Enrichment-Quellen
- Umgehung von Schutzmechanismen externer Websites
4. Source Taxonomy
4.1 SourceCategory
Repräsentiert eine Kategorie einer externen Quelle.
{
"source": "geizhals",
"external_category_key": "nb",
"name": "Notebooks",
"source_url": "https://geizhals.de/?cat=nb",
"status": "ACTIVE",
"last_verified_at": "2026-10-04T10:00:00Z"
}
4.2 SourceFilterDefinition
Beschreibt einen von Geizhals angebotenen Filter.
{
"source": "geizhals",
"category_key": "nb",
"external_filter_key": "17023",
"label": "Arbeitsspeicher",
"filter_type": "NUMERIC_THRESHOLD",
"canonical_unit": "GB",
"status": "VERIFIED"
}
Mögliche filter_type-Werte:
BOOLEAN
ENUM
MULTI_ENUM
NUMERIC_RANGE
NUMERIC_THRESHOLD
TEXT
UNKNOWN
4.3 SourceFilterOption
Für diskrete Filterwerte:
{
"filter_key": "17023",
"source_value": "ab 24GB",
"normalized_value": 24,
"operator": ">=",
"unit": "GB"
}
4.4 SourceFilterRange
Für Bereiche bzw. frei parametrisierbare Werte:
{
"filter_key": "price",
"minimum": 0,
"maximum": null,
"step": 1,
"unit": "EUR"
}
5. On-Demand Taxonomy Learning
Die Taxonomie wird nur für tatsächlich verwendete Kategorien gelernt.
Initial:
Geizhals → Notebooks
Später z. B.:
Monitore
Fernseher
Kameras
Rasenmäher
...
Ablauf
Kategorie öffnen
↓
verfügbare Filter erkennen
↓
Filterdefinitionen speichern
↓
Optionen / Bereiche erfassen
↓
URL-Verhalten beobachten
↓
Mapping erzeugen
↓
technisch verifizieren
Mapping-Status
DISCOVERED
LEARNED_UNVERIFIED
VERIFIED
BROKEN
DISABLED
Nur VERIFIED darf für automatische produktive Suchläufe verwendet werden.
Änderbarkeit
Die gelernten Mappings sollen später im Frontend administrierbar sein.
v0.1 benötigt dafür noch keine UI, aber die Persistenz muss Änderungen ermöglichen, ohne Source-Code anzupassen.
6. Canonical Criteria
Canonical Criteria sind die interne fachliche Darstellung eines Suchkriteriums.
Sie sollen sich stark an der Source-Taxonomie orientieren, aber nicht fest an Geizhals gekoppelt sein.
{
"key": "ram_gb",
"value_type": "number",
"unit": "GB",
"semantic": "working_memory"
}
Ein BuyingProject verwendet daraus konkrete Anforderungen:
{
"criterion": "ram_gb",
"operator": ">=",
"value": 24,
"mandatory": true
}
Source Mapping
Canonical Criterion
ram_gb >= 24
↓
Geizhals Mapping
filter_key = 17023
source_value = "ab 24GB"
↓
URL fragment
xf=17023_ab+24GB
Nicht jedes Canonical Criterion muss ein Source Mapping besitzen.
Fehlt ein Mapping:
Criterion → INTERNAL_ONLY
Das Kriterium wird dann erst nach Discovery intern bewertet.
7. DiscoverySearch
Eine DiscoverySearch gehört zu einem BuyingProject und einer Source.
Sie enthält mindestens:
id
buying_project_id
source_id
source_category_id
criteria_version
mapping_version
generated_url
status
schedule_interval_minutes
broad_result_threshold
created_at
updated_at
last_successful_run_at
Defaults:
schedule_interval_minutes = 180
shortlist_size = 5
broad_result_threshold = 300
8. Search URL Generation
Die URL wird ausschließlich aus:
BuyingProject Criteria
+
VERIFIED CriterionMappings
+
SourceCategory
+
konfigurierbaren Source-Optionen
generiert.
Die URL ist abgeleitet, nicht die fachliche Quelle der Wahrheit.
Eine Änderung der BuyingProject-Kriterien erzeugt eine neue criteria_version.
Wenn die gespeicherte DiscoverySearch nicht mehr zur aktuellen Criteria-/Mapping-Version passt:
status = OUT_OF_SYNC
Danach muss die URL neu generiert werden.
9. Ergebnisumfang
Aktive Suchläufe werden grundsätzlich vollständig eingelesen.
Keine stille Begrenzung auf Top-N.
Nur vollständige Ergebnismengen erlauben belastbare Erkennung von:
NEW
CHANGED
MISSING
DISAPPEARED
TOO_BROAD
Überschreitet die Treffermenge den konfigurierten Schwellwert:
result_count > broad_result_threshold
wird die Suche markiert:
TOO_BROAD
Die Suche darf technisch weiter ausgeführt werden, erzeugt aber einen Hinweis, dass die Source-Kriterien geschärft werden sollten.
Spätere Versionen dürfen breite Suchen differenziert behandeln, etwa seltenere Full-Reconciliation.
10. SearchRun
Jeder Abruf erzeugt einen unveränderlichen SearchRun.
Felder:
id
discovery_search_id
criteria_version
mapping_version
generated_url
started_at
finished_at
status
result_count
page_count
http_status_summary
error_code
Status:
RUNNING
SUCCESS
PARTIAL
FAILED
BLOCKED
Es wird kein HTML-Snapshot gespeichert.
11. SourceProductReference
Ein Treffer einer externen Quelle wird als SourceProductReference dauerhaft angelegt.
Mindestens verfügbare Felder:
id
source_id
source_category_id
source_url
source_title
manufacturer
model
manufacturer_sku
gtin_ean
normalized_spec_fingerprint
first_seen_at
last_seen_at
status
Keines dieser Felder außer der internen UUID wird pauschal als garantiert stabil betrachtet.
12. Produktidentität – Pilotansatz
v0.1 implementiert bewusst keine komplexe globale Identity Engine.
Für den Notebook-Pilot werden folgende Signale verwendet:
- vorhandene stabile Source-ID, falls entdeckt
- GTIN/EAN, falls vorhanden
- Hersteller-SKU, falls vorhanden
- kanonische Source-URL
- normalisierter Titel
- Hersteller + Modell
- differenzierende technische Specs
Für Notebooks kann der initiale Fingerprint beispielsweise enthalten:
manufacturer
model
cpu
ram
storage
display_size
gpu
Matching-Regeln
- Hohe Sicherheit → existierende SourceProductReference verwenden
- Unsicherheit →
MATCH_UNCERTAIN - Keine sichere Übereinstimmung → neue SourceProductReference
- niemals zwei Produkte allein aufgrund ähnlicher Namen automatisch verschmelzen
Die tatsächliche Stabilität der Identitätsmerkmale wird im Notebook-Pilot beobachtet und danach verfeinert.
13. Produktbeobachtungen und Historie
Technische Eigenschaften und Preise werden nicht einfach überschrieben.
Jeder SearchRun kann neue Beobachtungen erzeugen.
ProductObservation
source_product_reference_id
search_run_id
observed_at
raw_title
best_price
currency
raw_attributes
normalized_attributes
availability
seller_count
Veränderte Werte bleiben historisch nachvollziehbar.
Beispiele:
Preis: 1499 → 1299
RAM: 16 → 32
Anbieterzahl: 8 → 12
Verfügbarkeit geändert
Bei technischen Attributänderungen muss das System berücksichtigen, dass auch fehlerhaftes Matching vorliegen könnte.
14. Diffing
Jeder erfolgreiche Full SearchRun wird mit dem vorherigen erfolgreichen Full SearchRun derselben DiscoverySearch verglichen.
Status
NEW
CHANGED
UNCHANGED
MISSING
DISAPPEARED
Regeln
NEW
Produkt war im vorherigen vollständigen Lauf nicht vorhanden.
CHANGED
Produkt vorhanden, aber mindestens ein relevantes beobachtetes Feld hat sich verändert.
UNCHANGED
Produkt vorhanden und relevante Felder unverändert.
MISSING
Produkt fehlt in einem vollständigen Lauf.
DISAPPEARED
Produkt fehlt in drei aufeinanderfolgenden vollständigen Läufen.
Produkte werden nicht gelöscht.
Historie bleibt erhalten.
Ein später erneut auftauchendes Produkt wird reaktiviert und nicht als neues Produkt dupliziert, sofern das Matching ausreichend sicher ist.
15. Lifecycle eines BuyingProjects
Während ein BuyingProject aktiv ist:
ACTIVE
↓
DiscoverySearches laufen
↓
Produkte + Historie wachsen
↓
Ranking + Shortlist
Nach finalem Kauf:
PURCHASED
↓
BuyingProject archivieren
↓
Discovery stoppen
Produkte, Beobachtungen und Evaluationen können mit dem Projekt archiviert bzw. aus aktiven Ansichten entfernt werden.
Keine physische Löschung historischer Daten als Standardverhalten.
16. Ranking
Nach Discovery übernimmt ausschließlich die interne Buying Engine.
Source Results
↓
interne Hard Constraints
↓
ProductScore
↓
Ranking
Geizhals-Sortierung darf für die technische Ausgabe genutzt werden, ist aber keine fachliche Ranking-Entscheidung.
17. Shortlist
Nach internem Ranking wird eine Shortlist gebildet.
Default:
shortlist_size = 5
Der Wert ist pro BuyingProject konfigurierbar.
Shortlist-Kandidaten erhalten:
SHORTLISTED
Andere gültige Kandidaten:
CANDIDATE
Die spätere Deep-Enrichment-Stufe arbeitet primär auf der Shortlist.
18. Deep Enrichment
Nicht Bestandteil dieses Implementierungsslices.
Zielbild:
Shortlist
↓
Herstellerdaten
Tests
Benchmarks
Reviews
weitere Händler
Preisportale
Qualitätsinformationen
↓
erneute Bewertung
Discovery darf daher nicht voraussetzen, dass Geizhals alle für die finale Kaufentscheidung notwendigen Daten liefert.
19. Discovery, Ranking und Decision
Die drei fachlichen Stufen müssen getrennt bleiben.
Discovery
Welche Produkte kommen potenziell infrage?
Ranking
Welche dieser Produkte passen am besten zum BuyingProject?
Decision
Ist jetzt der richtige Zeitpunkt, Kandidat X zu kaufen?
Decision wird später u. a. berücksichtigen können:
- Zielpreis
- Deadline
- historische Preisentwicklung
- aktuelle Verfügbarkeit
- Product Fit
- Offer Fit
- Alternativen
- Beschaffungsdringlichkeit
Decision ist nicht Bestandteil dieses Slices.
20. Scheduling und defensiver Abruf
Default:
alle 180 Minuten
pro DiscoverySearch konfigurierbar.
Anforderungen
- keine parallelen Massenabrufe
- Pagination sequenziell oder stark begrenzt parallel
- Caching, wo sinnvoll
- Timeout
- Retry mit exponentiellem Backoff
- Jitter
- Stop bei wiederholten Fehlern
- keine Umgehung von Captchas oder Bot-Schutz
Reaktion
HTTP 429
BACKOFF
HTTP 403
BLOCKED
Captcha / Challenge erkannt
BLOCKED
Automatische weitere Abrufe der betroffenen DiscoverySearch werden pausiert.
Keine Schutzmechanismen umgehen.
21. Source Adapter Contract
Ein Discovery-Adapter soll mindestens folgende Fähigkeiten kapseln:
class DiscoverySourceAdapter(Protocol):
def discover_taxonomy(category_ref): ...
def build_query(criteria, mappings): ...
def fetch_results(query, pagination): ...
def parse_results(response): ...
def normalize_result(result): ...
Taxonomy Learning und Result Retrieval dürfen intern getrennte Services sein.
Der Rest des Systems darf keine Geizhals-spezifische URL- oder HTML-Logik kennen.
22. Services
Mindestens:
TaxonomyService
CriterionMappingService
DiscoverySearchService
SearchExecutionService
SourceProductIdentityService
SearchDiffService
CandidateRankingService
ShortlistService
Keine Businesslogik in n8n.
n8n kann später den Scheduler bzw. externe Events orchestrieren.
23. Persistenz
Neue bzw. ergänzende Tabellen können sein:
source_categories
source_filter_definitions
source_filter_options
source_filter_ranges
criterion_definitions
criterion_mappings
discovery_searches
search_runs
source_product_references
product_observations
project_candidates
candidate_status_history
Bestehende globale Entitäten aus der Hauptspezifikation bleiben bestehen:
Product
ProductVariant
Offer
PriceObservation
Diese dürfen nicht unnötig dupliziert werden.
Der Discovery-Slice kann zunächst mit SourceProductReference arbeiten und erst bei ausreichender Identität eine Verknüpfung zu canonical Product/ProductVariant herstellen.
24. API – minimaler Vertrag
Taxonomie
POST /api/v1/sources/geizhals/categories/{category}/discover-taxonomy
GET /api/v1/sources/geizhals/categories/{category}/filters
Mapping
GET /api/v1/criterion-mappings
POST /api/v1/criterion-mappings
PATCH /api/v1/criterion-mappings/{id}
DiscoverySearch
POST /api/v1/discovery-searches
GET /api/v1/discovery-searches/{id}
POST /api/v1/discovery-searches/{id}/generate-query
POST /api/v1/discovery-searches/{id}/run
SearchRuns
GET /api/v1/discovery-searches/{id}/runs
GET /api/v1/search-runs/{id}
Candidates
GET /api/v1/buying-projects/{id}/candidates
GET /api/v1/buying-projects/{id}/shortlist
Falls BuyingProject im aktuellen Code noch nicht existiert, muss die Integration mit der im Architecture Addendum vorgesehenen nächsten Domain-Erweiterung abgestimmt werden.
25. Tests
Taxonomy
- Notebook-Kategorie kann on demand eingelesen werden
- Filterdefinitionen werden reproduzierbar gespeichert
- Optionen werden nicht dupliziert
- Filteränderungen werden erkannt
- BROKEN-Mapping wird nicht produktiv verwendet
Query Generation
- identische Criteria + Mapping-Version erzeugen identische URL
- RAM >= 24 erzeugt erwartetes Geizhals-Fragment
- Preisbereich korrekt
- mehrere Filter kombinierbar
- INTERNAL_ONLY-Kriterien verändern die Source-URL nicht
- veraltete Mapping-Version markiert Search als OUT_OF_SYNC
Search Execution
- Pagination vollständig
- Ergebniszahl korrekt
- TOO_BROAD bei Überschreitung
- kein stilles Top-N-Abschneiden
- 429 → Backoff
- 403/Captcha → BLOCKED
Identity
- identische SKU wird wiedererkannt
- identische EAN wird wiedererkannt
- gleiche URL wird wiedererkannt
- leicht geänderter Titel bei stabilen Specs wird erkannt
- unsicheres Match erzeugt MATCH_UNCERTAIN
- ähnliche Produktnamen werden nicht automatisch verschmolzen
Diffing
- neuer Treffer → NEW
- geänderter Preis → CHANGED
- unverändert → UNCHANGED
- einmal fehlend → MISSING
- dreimal fehlend → DISAPPEARED
- Wiederauftauchen reaktiviert bestehende Referenz
Historie
- Preisänderungen bleiben historisiert
- technische Änderungen bleiben historisiert
- alte SearchRuns bleiben unverändert
- Projektarchivierung löscht keine History
Ranking
- nur interne Engine bestimmt Ranking
- Source-Sortierung beeinflusst ProductScore nicht
- Shortlistgröße Default 5
- Shortlistgröße konfigurierbar
26. Implementierungsreihenfolge
- Bestehende Implementierung gegen diese Spec und das Architecture Addendum prüfen.
- Notwendige BuyingProject-/ProjectCandidate-Minimalstruktur ergänzen, falls für Discovery erforderlich.
- Source Taxonomy + Mapping persistieren.
- Geizhals-Taxonomie-Pilot für Notebooks implementieren.
- reproduzierbare Query Generation implementieren.
- SearchRun + Pagination implementieren.
- SourceProductReference + ProductObservation implementieren.
- Identity Pilot implementieren.
- Diffing implementieren.
- interne Ranking-Engine anbinden.
- Shortlist bilden.
- Scheduling-Schnittstelle vorbereiten bzw. internen Scheduler minimal anbinden.
- Tests vollständig ausführen.
- Notebook-Pilot mit realer Suche validieren.
27. Definition of Done
- Geizhals-Notebook-Taxonomie wird on demand eingelesen und gespeichert.
- Source-Filter und Optionen werden persistiert.
- Filter-Mappings besitzen Lifecycle-Status.
- BuyingProject-Kriterien erzeugen reproduzierbar eine Geizhals-URL.
- Nicht abbildbare Kriterien bleiben INTERNAL_ONLY.
- Aktive Suche kann vollständig ausgeführt werden.
- Pagination wird vollständig verarbeitet.
- TOO_BROAD wird erkannt.
- SearchRuns werden gespeichert.
- Produkte werden dauerhaft als SourceProductReference angelegt.
- Preise und relevante Attribute werden historisiert.
- NEW / CHANGED / UNCHANGED / MISSING / DISAPPEARED funktionieren.
- DISAPPEARED erst nach drei aufeinanderfolgenden fehlenden Full Runs.
- Unsichere Produktidentität wird nicht automatisch verschmolzen.
- interne Engine bewertet Kandidaten.
- Shortlist Default 5 funktioniert.
- Suchfrequenz ist konfigurierbar, Default 180 Minuten.
- 403/429/Captcha führen zu defensivem Stop/Backoff.
- keine HTML-Archive.
- keine Notebook-spezifische Businesslogik außerhalb des Geizhals-Pilotmappings.
- Tests grün.
- Ergebnisse des Notebook-Piloten dokumentiert.
Coding-Agent-Arbeitsauftrag
Verwende als verbindliche Anforderungen:
buying-agent-v0.1-spec-v1.1.mdbuying-agent-architecture-addendum-v1.mdbuying-agent-source-discovery-spec-v0.1.md
Die neue Source-/Discovery-Spec ergänzt die bestehenden Dokumente. Bei Konflikten in ihrem Fachbereich hat sie Vorrang.
Vorgehen
1. Zuerst analysieren
Prüfe den aktuellen Repository-Stand gegen alle drei Dokumente.
Berichte vor größeren Änderungen:
- welche Teile bereits kompatibel sind,
- welche Domain-/DB-/API-Erweiterungen erforderlich sind,
- ob bestehende Implementierung refaktoriert werden muss,
- welche Änderungen rein additiv möglich sind.
2. Minimal integrieren
Implementiere nur den beschriebenen Source-/Discovery-Slice.
Nicht implementieren:
- Frontend
- Keepa
- Idealo
- LLM-Automation
- Auth/RBAC
- Kaufautomatisierung
- Warenkorb
3. Besonders beachten
- nicht notebook-spezifisch modellieren
- Geizhals-spezifische Logik ausschließlich im Source Adapter / Mapping Layer
- URL-Encoding nur aus verifizierten Source-Mappings
- vollständige SearchRuns, kein stilles Top-N-Limit
- konservatives Product Matching
- keine automatische Zusammenführung bei Unsicherheit
- alle Änderungen historisieren
- Discovery, Ranking und Decision getrennt halten
4. Tests
Führe Unit-, Integration- und End-to-End-Tests aus.
Mindestens:
- Taxonomy Discovery
- Query Generation
- Pagination
- Identity Matching
- Diffing
- History
- Ranking
- Shortlist
- Backoff / BLOCKED
5. Abschlussbericht
Dokumentiere:
- geänderte Dateien
- neue Migrationen
- neue API-Endpunkte
- Testergebnisse
- real durchgeführten Notebook-Pilot
- erkannte Geizhals-Eigenheiten
- verbleibende Risiken
- insbesondere Beobachtungen zur Stabilität der Produktidentität