Die Gridbert-Schnittstelle
Diese Seite dokumentiert dieselbe Schnittstelle, mit der auch app.gridbert.at rechnet. Keine zweite, abgespeckte Variante. Sie ist erzeugt, nicht getippt: Werkzeuge, Endpunkte und Grenzen kommen direkt aus dem Gateway-Code.
Was die Schnittstelle ist
Gridbert bietet zwei Wege zu denselben Werkzeugen: einen MCP-Server (unten) für Chatbots und eigene Agenten, und HTTP-Endpunkte, über die app.gridbert.at und die Kontoseiten selbst laufen. Für wen das relevant ist: alle, die einen eigenen Client, ein Skript oder einen Agenten gegen Gridbert bauen wollen. Für den fertigen Chat-Einstieg gibt es die Anleitungen je Agent.
Verbinden über MCP
Die Adresse für jeden MCP-fähigen Client:
https://mcp.gridbert.at/mcp
Verbindungsaufbau läuft über OAuth 2.1 mit Dynamic Client Registration, die Einrichtung je Agent beschreibt den Klickweg, hier die technischen Eckdaten:
| AS-Discovery | https://mcp.gridbert.at/.well-known/oauth-authorization-server |
|---|---|
| Resource-Discovery | https://mcp.gridbert.at/.well-known/oauth-protected-resource |
| JWKS | https://mcp.gridbert.at/jwks.json |
| Client-Registrierung (DCR) | https://mcp.gridbert.at/register |
| Scopes | mcp-tools offline_access |
| Grant-Typen | authorization_code, refresh_token, client_credentials |
| PKCE | S256, Pflicht |
| Token-Endpunkt-Auth | none, client_secret_post (öffentlicher Client) |
| Zugangs-Token gültig | 30 Minuten |
| Refresh-Token gültig | 30 Tage |
| Autorisierungs-Code gültig | 1 Minute |
| Protokollversion | 2025-06-18 |
Unter POST /mcp stehen vier JSON-RPC-Methoden bereit:
initialize, notifications/initialized, tools/list, tools/call. Jede Werkzeug-Antwort trägt ihr Ergebnis doppelt: als Text-Block
(content) und, wo ein Werkzeug ein Ausgabe-Schema deklariert, zusätzlich
strukturiert als structuredContent. Beide sind byte-gleich derselbe
Rechenweg, nur einmal als Text und einmal als Objekt.
Werkzeuge
27 Werkzeuge stehen jedem verbundenen Haushaltskonto zur Verfügung. Die Familie zeigt, woher ein Ergebnis kommt:
Gedächtnis liest oder schreibt dein persönliches Profil · Rechenwerk rechnet deterministisch mit energietools · Gridbert-Domäne ist Gateway-eigene Logik (Fakten, Bereitschaft, Rückfragen).
Die Beschreibung je Werkzeug ist wörtlich zitiert, so bekommt sie der Agent.
-
analyze_load_profileRechenwerk (energietools) nur lesendLastprofil-Metriken (Grundlast, Spitzen, Anomalien, Sparpotenziale) + Ursachen-Signale (E-Heizung, PV-Eigenverbrauch, Dauerläufer) + signal-getriebene Rückfragen-Kandidaten aus einer Lastgang-Serie (lastganganalyse-Prozess, Schritte 'lastprofil_metriken' + 'ursachen_signale'). IMMER als erster Analyse-Schritt nach list_load_series. lastprofil läuft auch auf Tageswerten weiter (Granularitäts-Caveat statt Verweigerung); signale verweigert bei Tageswerten (interval_minutes >= 60) — dann signale=null + signale_grund (Q15-Opt-in-Empfehlung), lastprofil bleibt trotzdem verfügbar. Bei PV-Haushalten greifen automatisch Netzbezug-Guards (basis_label='Netzbezug'). Fakt-vor-Heuristik: jeder Signal-Wert trägt eine quelle + profil_abgleich: quelle='profil'/'rechnung'/'messung' ist ein gespeicherter FAKT und IST die Antwort (z.B. aus submit_lastgang_facts) — quelle='heuristik' ist NUR eine Schätzung aus dem Lastprofil. Bei profil_abgleich.status='widerspruch' den Widerspruch dem User BENENNEN, nie stillschweigend zugunsten der Heuristik auflösen. mit_chartdaten=true liefert zusätzlich verdichtete Chart-Reihen (Stunden-Tagesprofil, Nachtlast je Tag) für Anzeige-Oberflächen — im Chat NICHT nötig, dort das Feld weglassen.
Eingabe
is_pvbooleantrue, falls der Haushalt eine PV-Anlage hat (aktiviert die Netzbezug-Guards). mit_chartdatenbooleanoptional, Default false — für Anzeige-Oberflächen (z.B. die Gridbert-App), NICHT für den Chat. true liefert zusätzlich data.chartdaten: ein Stunden-Tagesprofil (gesamt + Werktag/Wochenende, je 24 Werte) und eine Nachtlastreihe je Tag (max. ~120 Tage) — verdichtete Anzeige-Aggregate, keine Rohserie. Ohne dieses Flag bleibt das Ergebnis unverändert. price_per_kwhnumberoptional, brutto EUR/kWh — für Kosten-Kontext (lastprofil) pv_feedin_kwhnumberoptional — Summe aus dem Einspeise-serie_ref, falls vorhanden. Ohne Angabe versucht der Gateway automatisch einen zweiten aktiven Einspeise-Consent desselben Accounts zu finden. serie_ref*stringaus list_load_series/request_data_release Ausgabe (oberste Ebene)
dataobjectZusammengeführtes Ergebnis (lastgang_analysis.run_analyze_load_profile). hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. metaobject | nullHerkunft der Rechnung/Daten aus energietools (quelle, stand, snapshot_version) — Inhalt variiert je Capability. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
answer_lastgang_questionGridbert-DomäneSpeichert die Antwort auf eine offene Lastgang-Rückfrage (ereignis_id aus list_open_lastgang_questions) — entweder label (EXAKT eines der optionen[].label dieser Frage) ODER freitext (frei formuliert, höchstens 200 Zeichen), NIE beides gleichzeitig erfinden: nur übernehmen, was der User wirklich gesagt hat. Liefert danach dieselbe Rückschau wie die Web-Antwortseite — was diese Auffälligkeit seit Beginn der Messwerte gemacht hat, längstens über die letzten zwölf Monate (Tage, kWh, wenn auflösbar Euro) —, damit die Antwort für den User einen sofortigen Gegenwert hat, nicht nur einen 'danke, notiert'. Eine leere rueckschau ist kein Fehler (z.B. ohne Datenfreigabe oder zu wenig Messwerte) — die Antwort ist trotzdem gespeichert. Im Berater-Workspace ist das der Weg, die telefonisch aufgenommene Antwort des Kunden einzupflegen; sie wird als Berater-Angabe vermerkt und dem Haushalt später nicht als seine eigene zurückzitiert. Auch dort gilt: nur übernehmen, was der Kunde wirklich gesagt hat.
Eingabe
ereignis_id*integeraus list_open_lastgang_questions, NICHT raten oder selbst vergeben. freitextstringFrei formulierte Antwort, falls keine Option passt. labelstringExakt eines der optionen[].label der Frage. Weglassen, wenn stattdessen freitext gesetzt wird. Ausgabe (oberste Ebene)
gespeichertbooleanimmer true — bei Ablehnung wird NICHTS gespeichert. hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). rueckschauarraySätze der Rückschau in Alltagssprache (Tage, kWh, wenn auflösbar Euro). Kann LEER sein — kein Fehler, nur zu wenig Daten/keine Freigabe/kein Preis; die Antwort bleibt trotzdem gespeichert. workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
capability_gapGridbert-DomäneMelde einen fehlenden Bedarf, wenn ein Werkzeug für eine Energie-Frage fehlt (Unmet-Demand-Signal).
Eingabe
kategorie*stringBereich des fehlenden Bedarfs. kurzbeschreibung*stringWas hat konkret gefehlt? Zwei bis vier Sätze — welche Frage offen blieb, welche Zahl gebraucht wurde, ob sie extern beschafft werden musste. Keine Zählpunkte, Beträge oder Kontaktdaten. Ausgabe (oberste Ebene)
aufgenommenbooleanimmer true, wenn das Signal angenommen wurde. hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. inhaltstragendbooleanimmer true — der Freitext wird gespeichert (markierte F12-Ausnahme zur Telemetrie-Regel, redigiert im EventEmitter). kategoriestringEingeordnete Kategorie. Eine unbekannte Kategorie fällt bewusst auf 'sonstiges' zurück, statt das Signal zu verwerfen. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
compile_doneGedächtnis (engram)Schließt einen geclaimten Compile-Job ab (nach compile_next + upsert_page). keys = die Ziel-Seiten, in die das Artefakt gemergt wurde (jede muss einen [quelle: <item_id>]-Anker tragen, dessen Werte wörtlich in der Quelle stehen — der Server prüft deterministisch); keys=[] = explizites Noise-Signal. Für jede noch untypisierte Ziel-Seite typing[key] = { type, status, relations, confidence } AUSSCHLIESSLICH mit dem T-Box-Vokabular aus dem tbox-Feld der letzten compile_next-Antwort (tbox.types/tbox.relations/tbox.statuses) mitgeben. claim_token aus compile_next.item.claim_token UNVERÄNDERT zurückgeben — er beweist die Lease (sonst lease_lost).
Eingabe
claim_tokenstringFencing-Token aus compile_next.item.claim_token — unverändert zurückgeben. item_id*stringDas geclaimte Inbox-Item (aus compile_next). keys*arrayZiel-Seiten-Keys des Merges; [] = Noise. typingobjectTyping je noch untypisierter Ziel-Seite: { "<key>": { "type": "<T-Box-Typ|null>", "status": "<status|null>", "relations": { "<prädikat>": ["<key>"] }, "confidence": 0..1 } }. Ausgabe (oberste Ebene)
hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). proxiedbooleanimmer true — die Nutzlast kommt aus der engram-Instanz, nicht aus dem Gateway. resultobject | nullRohes MCP-Tool-Result der Instanz: {content: [...], isError: bool}. Der eigentliche Inhalt steckt als JSON-Text in content[0].text. toolstringName des proxierten Vault-Tools. workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
compile_nextGedächtnis (engram)Claimt genau EIN pending Item + Routing-Index + Zielblätter + Compile-Regeln + Union-T-Box (tbox.types/tbox.relations/tbox.statuses — das VOLLSTÄNDIGE Typ-Vokabular für compile_done.typing steht direkt in diesem Result, kein separater Tool-Call nötig). Leer = nichts zu tun.
Ausgabe (oberste Ebene)
hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). proxiedbooleanimmer true — die Nutzlast kommt aus der engram-Instanz, nicht aus dem Gateway. resultobject | nullRohes MCP-Tool-Result der Instanz: {content: [...], isError: bool}. Der eigentliche Inhalt steckt als JSON-Text in content[0].text. toolstringName des proxierten Vault-Tools. workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
energieberatung_infoRechenwerk (energietools) nur lesendKostenlose, produktneutrale Energieberatungsstelle(n) für ein Bundesland (Träger, Kontakt-URL, Quelle). Braucht 'bundesland' ODER 'plz' — die PLZ wird intern aufgelöst; bei mehrdeutiger/unbekannter PLZ kommt eine strukturierte Rückfrage nach 'bundesland'. Reine Informationsauskunft — Gridbert führt keine Beratung durch und vermittelt nicht.
Eingabe
bundeslandstringBundesland, für das die Beratungsstelle(n) gesucht werden. plzstringPLZ, aus der das Bundesland aufgelöst wird (Alternative zu bundesland). Ausgabe (oberste Ebene)
beratungsstellenarrayJe Eintrag: Träger, Kontakt-URL, Quelle. bundeslandstringAufgelöstes Bundesland. ergebnissearrayImmer [] — Platzhalter des Leer-Vertrags. grundstringWarum leer — z.B. 'keine Lastgang-Serien am Account'. hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. leerbooleantrue = Leer-Vertrag (errors.empty_result): kein Fehler, aber auch keine Ergebnisse. Die Nutzdatenfelder dieses Tools fehlen dann. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). standanyDatenstand der Einträge. workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
energiegemeinschaften_infoRechenwerk (energietools) nur lesendFakten zu Energiegemeinschaften (GEA, EEG lokal, EEG regional, BEG): Netzentgelt-Vorteile je Rechtsform mit Rechtsquelle und Gültigkeit, die ElWG-Änderung zur Netzentgelt-Reduktion für BEG greift erst ab 31.12.2026 — NICHT schon ab 1.10.2026 (das frühere Datum betrifft nur Begriffs-Definitionen, nicht die Netzentgelt-Bestimmung selbst — diesen Unterschied beim Beantworten nicht verwischen), außerdem Marktstand und die sechs Beitrittsschritte. Optionales 'bundesland' liefert zusätzlich bekannte Verzeichnis-Einträge aus der amtlichen Landkarte — das Verzeichnis ist NICHT vollständig (freiwillig befüllt, deckt nur einen Teil der Bürgerenergiegemeinschaften ab, keine Erneuerbare-Energie-Gemeinschaften); ohne Treffer liefert das Tool einen ehrlichen Hinweis statt einer leeren Behauptung. Sag dem User das Datenstand-Datum dazu. Keine Rechtsberatung.
Eingabe
bundeslandstringOptional — liefert zusätzlich bekannte Verzeichnis-Einträge des Bundeslands. Ausgabe (oberste Ebene)
beitrittsschrittearrayDie sechs Schritte zum Beitritt. bundeslandstringNur, wenn eines übergeben wurde. elwg_aenderungobject | nullStrukturiertes Objekt mit den Inkrafttreten-Terminen + Quellen (Netzentgelt-Reduktion für BEG erst ab 31.12.2026). ergebnissearrayImmer [] — Platzhalter des Leer-Vertrags. fazit_haushaltanyKuratiertes 'was muss ich als Haushalt tun'. grundstringWarum leer — z.B. 'keine Lastgang-Serien am Account'. hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. leerbooleantrue = Leer-Vertrag (errors.empty_result): kein Fehler, aber auch keine Ergebnisse. Die Nutzdatenfelder dieses Tools fehlen dann. marktstandanyMarktstand in Österreich. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). rechtsformenarrayGEA / EEG lokal / EEG regional / BEG mit Rechtsquelle und Gültigkeit. standanyDatenstand — dem User nennen. verzeichnisarrayBekannte Verzeichnis-Einträge des Bundeslands — NICHT vollständig. verzeichnis_hinweisstringStatt einer leeren Liste: warum es keinen Treffer gibt. workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
foerderungen_checkRechenwerk (energietools) nur lesendOffene, verifizierte Förderungen für PV, Speicher, Heizungstausch, Sanierung, Balkonkraftwerk, Geräte-Reparatur und Wallbox — Bund + das gewählte Bundesland, je mit Fördersatz, Bedingungen, Antrags-Link, Zeitfenster (falls terminiert) und Quelle+Stand. Geschlossene oder unsicher markierte Einträge werden NIE ausgespielt. Braucht 'bundesland' ODER 'plz' — die PLZ wird intern aufgelöst; bei mehrdeutiger/unbekannter PLZ (z.B. eine PLZ, die zwei Bundesländer überspannt) kommt eine strukturierte Rückfrage nach 'bundesland' statt eines geratenen Ergebnisses. Optional 'kategorien' filtert auf einzelne Kategorien, z.B. ['pv','speicher']. Sag dem User das Datenstand-Datum ('stand') dazu — das ist KEINE Rechtsberatung, vor jeder Antragstellung immer die verlinkte Primärquelle prüfen. Am besten NACH einem Tarifvergleich anbieten, nicht davor.
Eingabe
bundeslandstringBundesland, für das Förderungen gefiltert werden. kategorienarrayFilter, z.B. ['pv','speicher']. Leer/weggelassen = alle Kategorien. plzstringPLZ, aus der das Bundesland aufgelöst wird (Alternative zu bundesland). Ausgabe (oberste Ebene)
anzahlintegerAnzahl ausgelieferter Förderungen. bundeslandstringAufgelöstes Bundesland. ergebnissearrayImmer [] — Platzhalter des Leer-Vertrags. foerderungenarrayJe Eintrag: Fördersatz, Bedingungen, Antrags-Link, Zeitfenster, Quelle. grundstringWarum leer — z.B. 'keine Lastgang-Serien am Account'. hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. leerbooleantrue = Leer-Vertrag (errors.empty_result): kein Fehler, aber auch keine Ergebnisse. Die Nutzdatenfelder dieses Tools fehlen dann. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). standanyDatenstand — dem User nennen. Keine Rechtsberatung. workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
get_data_release_statusGridbert-Domäne nur lesendFragt den Status einer Datenfreigabe ab (pending/active/revoked/…) + den aktuellen Datenstand der Serie (lastganganalyse-Prozess, Schritt 'datenfreigabe_status'). WARTE-UX ist PFLICHT: nach jeder Bestätigung im Netzbetreiber-Portal meldet der Netzbetreiber die Freigabe zurück — gemessen war die Hälfte nach rund fünf Stunden durch, einzelne brauchten mehrere Tage (Markt-Latenz, nicht dein Fehler). Sag das dem User ehrlich, versprich KEINE Minutenangabe und poll nicht endlos: Gridbert prüft stündlich und mailt von selbst, sobald sie da ist — und meldet sich auch, wenn eine Anfrage ungewöhnlich lange steht. Erinnere bei 'pending' an die ZWEITE, spätere Freigabe-Anfrage für Stammdaten (Doc §2) — kein Fehler, wenn sie erst Stunden nach der ersten erscheint. Ohne zaehlpunkt liefert es den Status ALLER Freigaben des Accounts. GRANULARITÄT: sobald Daten fließen, sagen 'aufloesung_minuten' und 'q15_aktiv', wie fein sie ankommen. Ist 'q15_empfehlung' gesetzt, liefert der Zähler nur grobe Werte (z. B. Tagessummen) — sprich die Empfehlung dann AKTIV aus: die Viertelstundenauslesung ist ein Opt-in, das der User bei seinem Netzbetreiber anfordern kann, und ohne sie sind Lastgang-Tools (analyze_load_profile, spot_backtest) nicht möglich. Bei 'q15_aktiv': null ist die Auflösung UNBEKANNT (noch keine Daten) — dann nichts über die Granularität behaupten.
Eingabe
zaehlpunktstringOptional — ohne Angabe: alle Freigaben des Accounts Ausgabe (oberste Ebene)
ergebnissearrayImmer [] — Platzhalter des Leer-Vertrags. freigabenarrayEine Zeile je Freigabe. grundstringWarum leer — z.B. 'keine Lastgang-Serien am Account'. hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. leerbooleantrue = Leer-Vertrag (errors.empty_result): kein Fehler, aber auch keine Ergebnisse. Die Nutzdatenfelder dieses Tools fehlen dann. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
get_knowledgeRechenwerk (energietools) nur lesendDeterministische Auslieferung der Wissensschicht (wie sich AT-Stromkosten zusammensetzen o. ä.). Reine Text-Auslieferung, kein Rechen-Result. 'thema' ist ein fester Wiki-Slug — Kern-Themen: 'stromkosten-zusammensetzung', 'netz-netzentgelte', 'tarife', 'steuern', 'foerderung', 'glossar'. Bei unbekanntem Thema listet die Fehlermeldung die gültigen Slugs auf.
Eingabe
thema*stringWiki-Slug, z.B. 'stromkosten-zusammensetzung' (mit Bindestrich, nicht Unterstrich) Ausgabe (oberste Ebene)
dataobjectWissens-Artikel der Capability 'get_knowledge'. hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. metaobject | nullHerkunft der Rechnung/Daten aus energietools (quelle, stand, snapshot_version) — Inhalt variiert je Capability. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
get_pageGedächtnis (engram) nur lesendLiefert eine Seite der Instanz per Key.
Eingabe
key*stringSeiten-Key (Slug). Ausgabe (oberste Ebene)
hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). proxiedbooleanimmer true — die Nutzlast kommt aus der engram-Instanz, nicht aus dem Gateway. resultobject | nullRohes MCP-Tool-Result der Instanz: {content: [...], isError: bool}. Der eigentliche Inhalt steckt als JSON-Text in content[0].text. toolstringName des proxierten Vault-Tools. workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
get_switch_infoGridbert-Domäne nur lesendWechsel-Infos (Schritte, Fristen, Kontaktweg) aus Katalogdaten. Reine Information — KEIN Vollmacht-Flow, keine Durchführung.
Eingabe
lieferantstringName des Ziel-Lieferanten, optional. Ausgabe (oberste Ebene)
fristenobjectRücktrittsrecht, Kündigungsfrist, übliche Wechseldauer. hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. hinweis_vollmachtstringKlarstellung: Gridbert wechselt NICHT selbst. kontakt_hinweisstringNur mit Lieferant: wo der Kontaktweg steht. lieferantstringNur, wenn ein Lieferant übergeben wurde. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). schrittearrayDie generischen AT-Wechselschritte. workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
ingestGedächtnis (engram)Schreibt ein RAW-Artefakt (JSON/Text-Fakten-Submission) in den append-only Raw-Store der Instanz (SSOT). Wird später über compile_next kompiliert.
Eingabe
content*stringDer zu speichernde Inhalt (JSON oder Text). content_typestringMIME-Type des Inhalts, Default 'application/json'. sourcestringHerkunft des Artefakts (frei wählbare Kennung). Ausgabe (oberste Ebene)
hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). proxiedbooleanimmer true — die Nutzlast kommt aus der engram-Instanz, nicht aus dem Gateway. resultobject | nullRohes MCP-Tool-Result der Instanz: {content: [...], isError: bool}. Der eigentliche Inhalt steckt als JSON-Text in content[0].text. toolstringName des proxierten Vault-Tools. workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
list_load_seriesGridbert-Domäne nur lesendListet alle Lastgang-Serien am Account (Zählpunkt MASKIERT, Richtung, Zeitraum, Coverage, Granularität, Datenstand — lastganganalyse-Prozess, Schritt 'serien_uebersicht'). IMMER als ERSTER Schritt aufrufen: bevor eine neue Datenfreigabe angefordert wird (kein doppelter Consent-Flow) und bevor ein Analyse-Tool (analyze_load_profile/load_trend/spot_backtest) aufgerufen wird — liefert den serie_ref, den die Analyse-Tools brauchen.
Ausgabe (oberste Ebene)
ergebnissearrayImmer [] — Platzhalter des Leer-Vertrags. grundstringWarum leer — z.B. 'keine Lastgang-Serien am Account'. hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. leerbooleantrue = Leer-Vertrag (errors.empty_result): kein Fehler, aber auch keine Ergebnisse. Die Nutzdatenfelder dieses Tools fehlen dann. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). serienarrayEine Zeile je Serie. workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
list_open_lastgang_questionsGridbert-Domäne nur lesendListet die offenen Rückfragen dieses Kontos zu Lastgang-Auffälligkeiten (z.B. 'was lief da nachts?') — Frage, Optionen und Zeitraum je Ereignis, damit du die Frage im Chat stellen kannst. 'Offen' heißt HIER: noch nicht beantwortet, egal ob schon per Mail verschickt — ein Konto, das im Chat von einem Gerät erzählt, muss dieselbe Frage nicht nochmal per Mail bekommen. Kein Input: das Konto kommt immer aus der Anmeldung, nie als Parameter. Rufe danach answer_lastgang_question mit der ereignis_id auf, sobald der User geantwortet hat.
Ausgabe (oberste Ebene)
ergebnissearrayImmer [] — Platzhalter des Leer-Vertrags. fragenarrayEine Zeile je offener Frage. grundstringWarum leer — z.B. 'keine Lastgang-Serien am Account'. hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. leerbooleantrue = Leer-Vertrag (errors.empty_result): kein Fehler, aber auch keine Ergebnisse. Die Nutzdatenfelder dieses Tools fehlen dann. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
load_trendRechenwerk (energietools) nur lesendMehrjahres-Trend (YoY) + Treiber-Zerlegung nach Leistungsband x Tageszeit x Werktag/Wochenende aus einer Lastgang-Serie (lastganganalyse-Prozess, Schritte 'mehrjahres_trend' + 'treiber_zerlegung'). trend: Kalender-YoY nur bei >=2 vollen Kalenderjahren (Coverage-Guard) — sonst Fenster-YoY über deckungsgleiche (Monat,Tag,Std,Min)-Slots; NIE ein Teiljahr gegen ein Volljahr stellen; läuft auch auf Tageswerten weiter (Granularitäts-Caveat). attribution benennt je Treiber eine Geräte-KLASSE als Hypothese — NIE einen Gerätenamen (15-min-Grenze, Abnahme-Kriterium 15) — nur mit >=2 Jahren Q15-Historie verfügbar, sonst attribution=null + attribution_grund (trend bleibt trotzdem verfügbar).
Eingabe
jahr_aintegerattribution-Basisjahr, leer = zweitjüngstes Jahr der Serie jahr_bintegerattribution-Vergleichsjahr, leer = jüngstes Jahr der Serie serie_ref*stringaus list_load_series/request_data_release Ausgabe (oberste Ebene)
dataobjectZusammengeführtes Ergebnis (lastgang_analysis.run_load_trend). hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. metaobject | nullHerkunft der Rechnung/Daten aus energietools (quelle, stand, snapshot_version) — Inhalt variiert je Capability. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
pv_potenzialRechenwerk (energietools) nur lesendNUR bei vorhandener Lastgang-Serie (serie_ref aus list_load_series) mit Viertelstundenwerten. Beantwortet 'Was würde mir eine PV-Anlage bringen?' auf dem ECHTEN Verbrauchsverlauf statt auf einem Standardprofil: je Anlagengröße Ertrag, Eigenverbrauch, Eigenverbrauchsquote, Autarkie, Einspeisung, vermiedene Netzkosten und Amortisation. Das Sonnenertragsprofil des Standorts holt der Gateway (PVGIS) — NIE vom User-LLM. Verweigert bei Tageswerten mit Begründung, weil sich daraus die Tageszeit des Verbrauchs nicht ablesen lässt. Liefert zwei getrennte Ergebnisse: 'gemessen' (nichts modelliert) und 'jahr_modelliert' (Tagessummen + gemessene Tagesform, als Modell gekennzeichnet). Euro-Beträge gibt es nur auf Jahresbasis — ein Teiljahr wird NICHT hochgerechnet. Die Einspeisevergütung ist eine Annahme und wird als Szenario-Band gerechnet.
Eingabe
arbeitspreis_netto_ct_kwhnumberArbeitspreis netto in ct/kWh (Alternative zu energiepreis_brutto_ct_kwh). ausrichtungstringSüd, Südost, Südwest, Ost, West (Default Süd) diskontratenumberDiskontrate für die Kapitalwertrechnung (z.B. 0.04 = 4%). einspeise_szenarien_ct_kwharrayAnnahme-Band, Default [3, 5, 8] netto ct/kWh energiepreis_brutto_ct_kwhnumberArbeitspreis von der Rechnung (brutto) gemeindestringGemeinde des Anschlusses. Nur nötig, wenn die Antwort danach fragt: bei geteilten PLZ (z.B. 1140, 1210) liegen zwei Netzgebiete nebeneinander. gemessene_anlage_kwpnumberInstallierte Leistung der BESTEHENDEN Anlage in kWp, zu der gemessener_jahresertrag_kwh gehört. Gridbert rechnet daraus den Ertrag je kWp. Nicht mit kwp_varianten verwechseln — das sind die durchzurechnenden Größen, das hier ist die reale. gemessener_jahresertrag_kwhnumberNUR bei einer BESTEHENDEN Anlage: tatsächlich gemessener Jahresertrag in kWh (vom Wechselrichter/Zähler). Ersetzt den PVGIS-Modellertrag — sinnvoll bei Verschattung, Mischausrichtung oder Balkonkraftwerken, wo das Modell weit danebenliegt. Nur zusammen mit gemessene_anlage_kwp verwenden; beide Zahlen erfragen, nie schätzen. investition_eur_pro_kwpobjectInvestition brutto EUR/kWp je Größe, z.B. {"10": 1400} kwp_variantenarrayAnlagengrößen in kWp, Default [5, 10] neigung_gradintegerDefault 35 nutzungsdauer_jahreintegerNutzungsdauer der Anlage in Jahren für die Amortisationsrechnung. plz*stringPLZ des Standorts, für das Sonnenertragsprofil (PVGIS). serie_ref*stringaus list_load_series/request_data_release speicher_kwhnumberZusatzvariante mit Speicher (0 = ohne) Ausgabe (oberste Ebene)
dataobjectErgebnis der Capability 'pv_potenzial' (+ gateway-seitiger Standort). hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. metaobject | nullHerkunft der Rechnung/Daten aus energietools (quelle, stand, snapshot_version) — Inhalt variiert je Capability. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
read_invoice_factsGridbert-Domäne nur lesendLiest aus einer hochgeladenen Rechnung (rechnung_ref aus POST /accounts/rechnung) die Felder, die submit_invoice_facts braucht — je Feld mit wörtlichem Zitat von der Rechnung und einer Konfidenz (hoch|mittel|niedrig|fehlt). Rechnet NICHTS und speichert NICHTS: die gelesenen Werte gehören dem User vorgelegt und erst nach seiner Bestätigung an submit_invoice_facts übergeben. Ein Feld mit konfidenz='niedrig' oder 'mittel' ist zu bestätigen, eines mit 'fehlt' zu erfragen — nie selbst ergänzen und nie aus dem Gesprächsverlauf raten. 'mittel' heisst zusätzlich: der Wert stammt aus einer gescannten Seite. Wer nur drei Stufen kennt, darf den vierten Wert NICHT wegwerfen — er ist da und er ist vorzulegen. Beträge und Mengen kommen SYSTEMATISCH als 'niedrig' zurück; das ist kein Mangel, sondern die gemessene Erkennungsgüte (Verbrauch 86 %, Rechnungsbetrag 90 %) — sie sind ausnahmslos vorzulegen. pruefbar=false heisst, die Rechnung ist keine prüfbare Jahres-, Zwischen- oder Monatsrechnung (Teilbetragsvorschreibung, Einspeisung, Energiegemeinschaft, Grosskunde über 100.000 kWh, ausländische Rechnung, keine Energierechnung): dann 'ablehnungsgrund' dem User im Klartext sagen und KEINE Prüfung anbieten. 'quellen_anker' ist fertig für die Übergabe an submit_invoice_facts aufgebaut, nicht neu bauen. Fotos, Scans und PDFs ohne Textebene werden mit not_configured abgelehnt statt geraten — dafür ist der Modell-Pfad noch nicht gebaut.
Eingabe
rechnung_ref*stringKennung aus POST /accounts/rechnung. Nicht raten und nicht aus dem Gespräch rekonstruieren — sie ist eine Stunde gültig. Ausgabe (oberste Ebene)
ablehnungsgrundstring | nullteilbetrag | einspeisung | energiegemeinschaft | grosskunde | ausland | keine_energierechnung — oder null, wenn prüfbar. energieartstringstrom | gas | kombi | unbekannt. felderarrayEin Eintrag je gelesenem Feld. gelesen_mitstringtextebene = exakt aus dem PDF gelesen, ohne Modell. Der einzige heute gebaute Weg; Fotos und Scans werden abgelehnt statt geraten. hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). pruefbarbooleanfalse = keine prüfbare Jahres-, Zwischen- oder Monatsrechnung. Dann steht der Grund in 'ablehnungsgrund' und es gibt keine Prüfung. quellen_ankerarrayFertig für die Übergabe an submit_invoice_facts: Objekte {feld, zitat}. NICHT neu bauen — dort wird geprüft, ob der übergebene Zahlenwert im Zitat wirklich vorkommt. rechnungstypstringjahresrechnung | zwischenrechnung | monatsrechnung | unbekannt. workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
request_data_releaseGridbert-DomäneFordert die Datenfreigabe für einen Zählpunkt an (EDA-Consent, CM_REQ_ONL — lastganganalyse-Prozess, Schritt 'datenfreigabe_anfordern'). Der Zählpunkt MUSS aus den Invoice-Fakten der Instanz stammen (get_page/search_pages) — nicht vom User abtippen lassen. Nur aufrufen, wenn list_load_series noch keine aktive Freigabe für diesen Zählpunkt zeigt (kein doppelter Consent-Flow). energy_direction ist PFLICHT (consumption|generation) — bewusst setzen, NICHT raten: eine falsche Richtung wedged den Zählpunkt beim Netzbetreiber (langes 'pending', dann Fehler bei jedem Retry). Ist die Richtung nicht klar aus den Invoice-Fakten ableitbar, den User zuerst fragen: 'Hast du eine PV-Anlage mit Einspeisung an diesem Zählpunkt?' Kündige dem User EXAKT an: 'Du bekommst zwei Freigabe-Anfragen im Netzbetreiber-Portal unter Freigaben→Offen (Provider EP100505) — zuerst die Energiedaten, wenige Stunden später eine zweite für Stammdaten (Adresse/Zählerdaten).' Beide sind eigene Consents mit eigenem Lifecycle — die zweite (ST/MasterData) feuert der Netzbetreiber automatisch, du musst sie nicht selbst auslösen, aber im Portal ebenfalls bestätigen. Nach jeder Bestätigung meldet der Netzbetreiber die Freigabe zurück; wie lange das dauert, ist sehr verschieden — gemessen war die Hälfte nach rund fünf Stunden durch, einzelne brauchten mehrere Tage (ehrlich sagen, kein Live-Spinner, keine Minutenangabe versprechen). Gridbert prüft stündlich und mailt von selbst, sobald sie da ist. Bei bestätigter PV-Einspeisung: ZWEITER Aufruf mit energy_direction='generation' und dem Einspeise-Zählpunkt (eigene Nummer, i.d.R. Suffix …9901).
Eingabe
energy_direction*stringPFLICHT, bewusst setzen: 'consumption' für Bezug, 'generation' NUR für den separaten Einspeise-Zählpunkt bei PV. Nicht ableitbar? Erst den User fragen, nicht raten. plz*stringPLZ des Zählpunkts (4-stellig). zaehlpunkt*string33-stelliger AT-Zählpunkt aus den Invoice-Fakten (kein Abtippen durch den User) Ausgabe (oberste Ebene)
bereits_freigegebenbooleanNur im Bestandsfall: true = es lief schon eine Freigabe, kein zweiter CM_REQ_ONL. energy_directionstringNur bei frischer Anforderung: 'consumption' oder 'generation'. esp_providerstringNur bei frischer Anforderung: Provider-Kennung im Portal. hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). portal_pfadstringNur bei frischer Anforderung: 'Freigaben → Offen'. serie_refstringReferenz auf die Serie — der Schlüssel für alle Lastgang-Tools. statusstringConsent-Status: 'pending' nach frischer Anforderung, sonst der Stand der bestehenden Freigabe ('pending'|'active'). workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. zaehlpunkt_maskedstringZählpunkt MASKIERT. Der Klartext verlässt den Gateway nie. -
search_pagesGedächtnis (engram) nur lesendDeterministische FTS-Suche über die kompilierten Seiten der Instanz (LLM-frei) — das GEDÄCHTNIS des Haushalts. Hier liegen aus Rechnungen gemerkte Fakten (Jahresverbrauch, Arbeits-/Grundpreis, Lieferant, Zeitraum) UND selbst genannte Haushalts-Fakten (Heizart, Geräte, PV, …). ZUERST aufrufen bei JEDER Frage zu dem, was der User schon eingebracht hat — Verbrauch, Kosten, Tarif, Lieferant, WIE er heizt —, BEVOR du aus einem Lastprofil-Signal/einer Heuristik schätzt, nach manuellen Daten fragst oder 'weiß ich nicht' sagst. Ein gespeicherter Fakt schlägt immer die Heuristik. Suchtext als 'query'; 'limit' optional (Default 10).
Eingabe
limitintegermax. Treffer (Default 10) query*stringSuchtext (Freitext) Ausgabe (oberste Ebene)
hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). proxiedbooleanimmer true — die Nutzlast kommt aus der engram-Instanz, nicht aus dem Gateway. resultobject | nullRohes MCP-Tool-Result der Instanz: {content: [...], isError: bool}. Der eigentliche Inhalt steckt als JSON-Text in content[0].text. toolstringName des proxierten Vault-Tools. workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
speicher_dimensionierungRechenwerk (energietools) nur lesendNUR bei vorhandener Q15-Lastgang-Serie. Beantwortet 'Wie groß soll der Batteriespeicher sein?': je Größe Eigenverbrauchsquote, Autarkie, Vollzyklen, Amortisation, Kapitalwert — und den Grenznutzen, also ab welcher Größe die nächste Kilowattstunde fast nichts mehr bringt. Sagt auch ehrlich Nein, wenn keine Größe einen positiven Kapitalwert erreicht. Speicher-Alterung ist NICHT eingepreist; die Vollzyklen je Größe stehen im Ergebnis. Braucht die Anlagengröße (kwp).
Eingabe
arbeitspreis_netto_ct_kwhnumberArbeitspreis netto in ct/kWh (Alternative zu energiepreis_brutto_ct_kwh). ausrichtungstringSüd, Südost, Südwest, Ost, West (Default Süd). diskontratenumberDefault 0.04 einspeise_netto_ct_kwhnumberDefault 5 energiepreis_brutto_ct_kwhnumberArbeitspreis brutto in ct/kWh. gemeindestringGemeinde des Anschlusses. Nur nötig, wenn die Antwort danach fragt: bei geteilten PLZ (z.B. 1140, 1210) liegen zwei Netzgebiete nebeneinander. gemessene_anlage_kwpnumberInstallierte Leistung in kWp, zu der der gemessene Jahresertrag gehört. Meist dieselbe Zahl wie kwp. gemessener_jahresertrag_kwhnumberNUR bei einer BESTEHENDEN Anlage: tatsächlich gemessener Jahresertrag in kWh. Ersetzt den PVGIS-Modellertrag — bei Verschattung oder Mischausrichtung liegt das Modell weit daneben, und die Speichergröße hängt daran. Nur zusammen mit gemessene_anlage_kwp; beide erfragen, nie schätzen. groessen_kwharraySpeichergrößen, Default [2.5, 5, 7.5, 10, 15] kwp*numberAnlagengröße in kWp neigung_gradintegerDachneigung in Grad (Default 35). nutzungsdauer_jahreintegerDefault 15 plz*stringPLZ des Lieferorts (4-stellig). serie_ref*stringaus list_load_series/request_data_release speicher_kosten_eur_pro_kwhnumberDefault 600 Ausgabe (oberste Ebene)
dataobjectErgebnis der Capability 'speicher_dimensionierung' (+ Standort). hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. metaobject | nullHerkunft der Rechnung/Daten aus energietools (quelle, stand, snapshot_version) — Inhalt variiert je Capability. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
spot_backtestRechenwerk (energietools) nur lesendNUR bei vorhandener Lastgang-Serie (serie_ref aus list_load_series). Für den normalen Tarifvergleich aus einer Rechnung ist dieses Tool NICHT nötig — dafür tariff_compare, das ganz ohne Lastgang rechnet. Profilgewichteter Spot-Backtest (echter Verbrauchs-Shape x EPEX-Stundenpreise, aus dem Box-Postgres — NIE vom User-LLM übergeben) vs. aktueller Fixpreis, plus Tarifwechsel-Ersparnis (lastganganalyse-Prozess, Schritt 'spot_und_tarifvergleich'). tarif_ersparnis ist nur verfügbar, wenn plz/energiepreis_brutto_ct_kwh/aktuelle_grundgebuehr_brutto_eur_monat/aktueller_lieferant/jahresverbrauch_kwh vollständig sind — sonst verfuegbar=false + grund (nie eine stille 0). Hebel-Reihenfolge: Tarif zuerst prüfen. Verweigert bei Tageswerten mit Begründung.
Eingabe
aktuelle_grundgebuehr_brutto_eur_monatnumberGrundgebühr brutto in €/Monat. aktueller_lieferantstringName des aktuellen Stromlieferanten. aufschlag_ctnumberAnnahme (Lieferanten-Aufschlag), Default aus energietools energiepreis_brutto_ct_kwhnumberArbeitspreis brutto in ct/kWh. jahresverbrauch_kwhnumberJahresverbrauch in kWh. plzstringPLZ des Lieferorts (4-stellig). serie_ref*stringaus list_load_series/request_data_release Ausgabe (oberste Ebene)
dataobjectErgebnis der Capability 'spot_backtest'. hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. metaobject | nullHerkunft der Rechnung/Daten aus energietools (quelle, stand, snapshot_version) — Inhalt variiert je Capability. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
submit_invoice_factsGridbert-DomäneÜbergibt EXAKT abgelesene Rechnungswerte + wörtliche Zitate. Validiert deterministisch (energieart muss strom|gas|kombi sein — Nicht-Energie-Rechnungen z.B. Restaurant werden mit error_class=validation_rejected und benanntem Grund abgelehnt, nichts wird gespeichert), rechnet finalize, schreibt die Fakten-Submission in den Raw-Store. PFLICHT: energieart, lieferant, plz, verbrauch_kwh, zeitraum_von, zeitraum_bis (ISO YYYY-MM-DD oder DE TT.MM.JJJJ) und quellen_anker. Zusätzlich muss arbeitspreis (ct/kWh) ODER summe_energieentgelte vorliegen. quellen_anker sind Objekte {feld, zitat} — je ein wörtliches Zitat für den Verbrauch und einen Betrag, z.B. quellen_anker=[{"feld":"verbrauch_kwh","zitat":"Jahresverbrauch 2562,3 kWh"},{"feld":"arbeitspreis","zitat":"Arbeitspreis 16,02 ct/kWh"}]. Lehnt bei Unplausibilität feld-genau mit Rückfrage ab (nichts wird gespeichert). Dieses Tool speichert nur — die Frage 'zahle ich zu viel?' beantwortet erst tariff_compare, das danach im selben Zug zu rechnen ist.
Eingabe
arbeitspreisobjectArbeitspreis: {wert_ct_kwh, ist_netto}. Erforderlich, falls keine summe_energieentgelte. energieart*stringEnergieart der Rechnung: 'strom', 'gas' oder 'kombi'. grundgebuehrobjectGrundgebühr: {wert_eur, zeitraum(monat|jahr), ist_netto}. lieferant*stringName des Lieferanten auf der Rechnung. plz*stringPLZ des Lieferorts (4-stellig). quellen_anker*arrayWörtliche Belegstellen je Feld — mindestens ein Zitat für Verbrauch und einen Betrag. summe_energieentgelteobjectSumme des Energieentgelt-Blocks in € (Zeile 'Energiekosten'/'Summe Energieentgelte'): {wert_eur, ist_netto}. Erforderlich, falls kein arbeitspreis — z.B. wenn nur eine Blocksumme auf der Rechnung steht, kein ct/kWh-Wert. verbrauch_kwh*numberVerbrauch im Abrechnungszeitraum in kWh. zaehlpunktstringZählpunkt von der Rechnung (33 Zeichen, AT + 31 Ziffern; Punkte und Leerzeichen egal). Optional — aber wenn er auf der Rechnung steht, mitgeben: er benennt das Netzgebiet, das sonst aus der PLZ erschlossen wird, und die liegt falsch, wo ein Netzbetreiber über die Bundeslandgrenze versorgt. Liegt eine Datenfreigabe vor, ergänzt der Gateway ihn selbst. zeitraum_bis*stringAbrechnungsende, ISO YYYY-MM-DD oder DE TT.MM.JJJJ zeitraum_von*stringAbrechnungsbeginn, ISO YYYY-MM-DD oder DE TT.MM.JJJJ Ausgabe (oberste Ebene)
gespeichertbooleanimmer true — bei Ablehnung wird NICHTS gespeichert. hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). rechnungobject | nullErgebnis der Capability 'finalize_invoice' — der Rechenweg, aus dem die Eingaben für tariff_compare stammen (nicht erneut beim User erfragen). workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
submit_lastgang_factsGridbert-DomäneSpeichert Profil-Fakten zum Haushalt (Heizung, PV-Eckdaten, Dauerläufer, Lastverschiebung, Heizstromtarif, Q15-Opt-in). ZWEI Anlässe, beide richtig: (1) die beantworteten Rückfragen aus der Lastgang-Analyse (lastganganalyse-Prozess, Schritt 'rueckfragen_persistieren'); (2) alles, was der User von sich aus über seinen Verbrauch erzählt — typischerweise direkt nach analyze_load_profile, wenn er die Auffälligkeit auf dem Schirm hat und sie ungefragt erklärt ('der Verbrauch in der Früh ist der Boiler', 'das Auto lade ich unregelmäßig'). Speichere das, statt es im Gesprächsverlauf zu lassen: aus Viertelstundenwerten ist es nie wieder ableitbar. Liegt dagegen eine KONKRETE offene Rückfrage zu einem Ereignis vor, gehört sie über answer_lastgang_question beantwortet — nur so wird sie als erledigt vermerkt. Validiert deterministisch gegen die bekannten Felder — unbekannte Felder oder unplausible Werte werden mit error_class=validation_rejected abgelehnt (nichts wird gespeichert). Gleiche Rejection-Semantik wie submit_invoice_facts (D2.2).
Eingabe
fakten*arrayListe der Fakten als Feld/Wert/Beleg-Objekte — beantwortete Rückfragen ebenso wie ungefragt Erzähltes. Ausgabe (oberste Ebene)
anzahl_faktenintegerWie viele Fakten übernommen wurden. gespeichertbooleanimmer true — bei Ablehnung wird NICHTS gespeichert. hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
tariff_compareRechenwerk (energietools) nur lesendVergleicht den aktuellen STROMtarif mit tagesaktuellen Alternativen (Rechenweg je Alternative). Braucht KEINEN Lastgang und KEINE serie_ref — die fünf Rechnungswerte unten reichen (serie_ref gehört zu spot_backtest/load_trend, nicht hierher). Bei Tarif-/Preisfragen dieses Tool nutzen statt Websuche: der Katalog ist tagesaktuell und jede Zahl kommt mit Rechenweg. Aktuell nur Strom: energieart ist PFLICHT (strom|gas) und 'gas' wird sauber als not_supported abgelehnt — setze es bewusst, nicht raten. Erfrage beim User zuerst: PLZ, Jahresverbrauch (kWh), aktueller Lieferant, Arbeitspreis (ct/kWh brutto), Grundgebühr (€/Monat brutto). Beträge in €/kWh bzw. €/Jahr vorher in ct/kWh bzw. €/Monat umrechnen. Je Tarif im Ergebnis: rabatt_befristet=true bedeutet ein NUR im 1. Jahr wirkender Neukundenbonus — dann jahreskosten_jahr2_eur (Preis ab Jahr 2) mit ausweisen, den Bonus NICHT als Dauer-Ersparnis verkaufen. Beachte netzkosten_vollstaendig: ist es false, ist kein Netzbetreiber hinterlegt und der €-Betrag heißt energiepreis_anteil_eur (nur Energiepreis-Anteil, NICHT jahreskosten_eur) — dem User NICHT als Gesamtrechnung präsentieren. Die VNB-Auflösung macht der Gateway (nb_key vorgelöst): gib den zaehlpunkt mit, wenn du ihn hast. netzbetreiber_herkunft im Ergebnis sagt, worauf sie beruht — bei 'plz' ist der Netzbetreiber ANGENOMMEN (und die Netzkosten mit ihm), bei 'zaehlpunkt' belegt. Vor einer Gesamtkosten-Aussage auf 'plz'-Basis den Zählpunkt erfragen, statt die Zahl als exakt zu verkaufen.
Eingabe
aktuelle_grundgebuehr_brutto_eur_monat*numberGrundgebühr brutto in €/Monat (nicht €/Jahr) aktueller_energiepreis_brutto_ct_kwh*numberArbeitspreis brutto in ct/kWh (nicht €/kWh) aktueller_lieferant*stringName des aktuellen Stromlieferanten. energieart*stringPflicht: 'strom' (aktuell einziger Support) oder 'gas' (→ not_supported) jahresverbrauch_kwh*numberJahresverbrauch in kWh. plz*stringPLZ des Lieferorts (4-stellig). zaehlpunktstringOptional, aber für die Netzkosten der bessere Schlüssel: 33-stelliger AT-Zählpunkt aus den Invoice-Fakten oder list_load_series (kein Abtippen durch den User). Er benennt den Netzbetreiber eindeutig; ohne ihn wird er aus der PLZ angenommen und liegt in Gemeinden mit fremdem Netzbetreiber falsch. Ausgabe (oberste Ebene)
dataobjectVergleichsergebnis der energietools-Capability 'tariff_compare'. hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. metaobject | nullHerkunft der Rechnung/Daten aus energietools (quelle, stand, snapshot_version) — Inhalt variiert je Capability. netzbetreiber_herkunftstring | nullWorauf die Netzbetreiber-Auflösung beruht: 'zaehlpunkt' = belegt, 'plz' = ANGENOMMEN (und mit ihm die Netzkosten). Gateway-seitig gesetzt, nicht von energietools. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
upsert_pageGedächtnis (engram)Schreibt eine Seite FAITHFULLY (1:1, kein LLM). Serverseitiges Verify-Gate auf diesem Pfad: NUR der Orphan-Check; Quellen-Anker- und Typing-Checks gaten compile_done. Clobber-Guard: bestehende Seite wird nur mit overwrite=true ersetzt — vorher mit get_page lesen.
Eingabe
body*stringVoller Seiten-Body (Markdown), 1:1 gespeichert. key*stringOpaker external_key (Slug). overwritebooleantrue = bestehende Seite ersetzen; Default false = Ablehnung, wenn sie existiert. title*stringSeitentitel — wirkt nur beim Neuanlegen (Update behält den Titel). Ausgabe (oberste Ebene)
hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). proxiedbooleanimmer true — die Nutzlast kommt aus der engram-Instanz, nicht aus dem Gateway. resultobject | nullRohes MCP-Tool-Result der Instanz: {content: [...], isError: bool}. Der eigentliche Inhalt steckt als JSON-Text in content[0].text. toolstringName des proxierten Vault-Tools. workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
versorger_abdeckungRechenwerk (energietools) nur lesendWelche STROM-Lieferanten sind an einer PLZ/im Netzgebiet verfügbar (Abdeckungs-Block). Aktuell nur Strom: energieart='gas' wird als not_supported abgelehnt (die Abdeckungsdaten sind Strom-only — es würden sonst Strom-Marken als vermeintliche Gas-Liste erscheinen).
Eingabe
energieartstringaktuell nur 'strom'; 'gas' wird als not_supported abgelehnt plz*stringPLZ des Lieferorts (4-stellig). Ausgabe (oberste Ebene)
dataobjectAbdeckungs-Block der Capability 'versorger_abdeckung'. hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. metaobject | nullHerkunft der Rechnung/Daten aus energietools (quelle, stand, snapshot_version) — Inhalt variiert je Capability. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht.
Berater-Werkzeuge
Ein Beraterkonto sieht zusätzlich 6 Portfolio-Werkzeuge. Für Zugriff auf einen Kundenbereich gibst du deinem Berater die Freigabe im eigenen Konto, nicht umgekehrt.
-
get_tboxGedächtnis (engram) nur lesendLiefert die deklarative Union-T-Box (core ∪ gridbert-at-energie) + Version der Instanz — für Ontologie-Diagnose ausserhalb eines laufenden Compile-Jobs (der normale Compile-Flow bekommt das Vokabular bereits inline über compile_next.tbox).
Ausgabe (oberste Ebene)
hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). proxiedbooleanimmer true — die Nutzlast kommt aus der engram-Instanz, nicht aus dem Gateway. resultobject | nullRohes MCP-Tool-Result der Instanz: {content: [...], isError: bool}. Der eigentliche Inhalt steckt als JSON-Text in content[0].text. toolstringName des proxierten Vault-Tools. workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
invite_clientBerater-PortfolioLädt einen Kunden per E-Mail-Adresse ein, den eigenen Bereich für diesen Berater freizugeben. Funktioniert auch, wenn der Kunde noch kein Gridbert-Konto hat. Der Kunde entscheidet selbst: die Einladung verschafft KEINEN Zugriff, sie führt nur zu einer Anfrage, der er in seinem Konto zustimmen muss. Das Result enthält einen Einladungslink, den der Berater auch selbst weitergeben kann.
Eingabe
bezeichnung*stringAnzeigename dieses Mandats im Berater-Portfolio, z.B. 'Haushalt Familie K, Wien 1070' oder 'Betrieb Mustermann GmbH' einwilligungstringVermerk, wie die Zusage zustande kam, z.B. 'Am Telefon besprochen, 05.08.2026'. Der Kunde sieht ihn in seinem Konto — er ersetzt die Zustimmung NICHT. email*stringE-Mail-Adresse des Kunden kundentypstring'betrieb' für Unternehmen mit Lastprofilzähler; dann Sie-Form und Betriebs-Wortwahl in allen Mails. Weggelassen = 'haushalt' (Du-Form, Default). Ausgabe (oberste Ebene)
bezeichnungstringAnzeigename des Mandats im Portfolio. eingeladenstringDie eingeladene E-Mail-Adresse. einladungslinkstringLink, den der Berater auch selbst weitergeben kann. gueltig_bisstringAblauf der Einladung als ISO-Zeitstempel. hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. zugriffstringImmer der Wartezustand — nie ein 'ja'. Der Kunde entscheidet. -
list_workspacesBerater-Portfolio nur lesendListet die Arbeitsbereiche des Beraters: eigener Bereich + alle Kunden mit aktiver Freigabe (Grant), inkl. Datenstand.
Ausgabe (oberste Ebene)
aktiver_workspacestring | nullSlug des aktiven Bereichs, null = eigener Bereich. eigener_bereichobjectDer eigene Bereich des Beraters. hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. workspacesarrayEin Eintrag je aktivem Grant. -
portfolio_overviewBerater-Portfolio nur lesendStatus-Übersicht über ALLE Mandanten des Beraters auf einen Blick: je Mandant, ob eine Rechnung und ob Lastgang-Daten hinterlegt sind, wann zuletzt gerechnet wurde, und ob der Zugriff gerade trägt. Beantwortet 'bei wem fehlt was?'. Enthält BEWUSST keine Zahlen — keinen Verbrauch, keinen Preis, keinen Betrag. Für die Werte eines Mandanten mit select_workspace dorthin wechseln.
Ausgabe (oberste Ebene)
anzahlintegerAnzahl Mandanten. hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. mandantenarrayEine Status-Zeile je Mandant. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
portfolio_tariff_checkBerater-Portfolio nur lesendRechnet für JEDEN Mandanten mit hinterlegter Rechnung einen Tarifvergleich und gibt je Mandant eine Ampel zurück: 'ok' (unter 5 % Ersparnis), 'pruefen' (5-15 %), 'handeln' (über 15 %), 'keine_daten' (keine vollständige Rechnung), 'nicht_verfuegbar'. Beantwortet 'bei wem lohnt ein genauerer Blick?'. Das Result enthält KEINE Beträge — nenne dem Berater keine, sie stehen nicht drin. Für den vollen Rechenweg eines Mandanten mit select_workspace dorthin wechseln und tariff_compare rufen. Beachte netzkosten_vollstaendig je Zeile: bei false beruht die Ampel nur auf dem Energiepreis-Anteil.
Ausgabe (oberste Ebene)
ampel_bedeutungobject | nullLegende der fünf Ampelwerte. anzahlintegerAnzahl Mandanten. hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. mandantenarrayEine Ampel-Zeile je Mandant. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht. -
select_workspaceBerater-PortfolioWechselt den aktiven Arbeitsbereich des Beraters (Kunde per Slug oder eindeutigem Label; 'eigen' = eigener Bereich). Die Auswahl gilt account-weit bis zum nächsten Wechsel.
Eingabe
workspace*stringKunden-Slug oder eindeutiges Label aus list_workspaces; 'eigen' wechselt zurück in den eigenen Bereich Ausgabe (oberste Ebene)
aktiver_workspacestring | nullSlug des NEU gewählten Bereichs. null = eigener Bereich. hinweisstring | nullOptionaler Hinweis ans Modell (F14) — Datenstand-Warnung, nächster Schritt, Granularitäts-Caveat. Darf null sein. labelstringAnzeigename des neuen Bereichs. okbooleanimmer true. Fehler kommen als isError ohne structuredContent zurück (errors.error_result: {ok:false, error_class, fehler}). workspaceobjectNur bei Berater-Accounts: der Arbeitsbereich, in dem dieser Call gelandet ist (dispatch.py stempelt ihn zentral an JEDES Result). Haushalts-Results tragen das Feld nicht.
Ein Beraterkonto sieht zusätzlich sechs Portfolio-Werkzeuge (oben gelistet) und bekommt dieselben Werkzeug-Texte in der Sie-Form, wenn ein Kunde als 'betrieb' markiert ist (kundentyp='betrieb'). Der Katalog selbst ändert sich dadurch nicht.
HTTP-Endpunkte
46 Endpunkte, nach Aufgabe gruppiert. Die Auth-Spalte zeigt, was ein Aufruf braucht: ein Sitzungs-Cookie (Browser, angemeldet), ein Bearer-Token (MCP-Client), einen signierten Link aus einer E-Mail, oder gar nichts.
Konto
-
POST/accounts/deleteSession-CookieLöscht das eigene Konto endgültig, inklusive Instanz, Zugängen und Messwerten.
Request
bestaetigung*stringDie eigene E-Mail-Adresse, zur Bestätigung wörtlich eingetippt. Antwort
JSON
fertig: true, wenn die Löschung vollständig durch ist.konto_geloescht: true/false.offen: Schritte, die beim nächsten Aufruf weiterlaufen, falls einer offen blieb.
Fehler
400bestaetigung_stimmt_nicht: Die eingetippte Adresse stimmt nicht mit der Konto-Adresse überein.401no_session: Keine Sitzung.429rate_limited: Zu viele Versuche von dieser IP-Adresse.503loeschung_unvollstaendig: Ein Teilschritt war gerade nicht erreichbar. Derselbe Aufruf macht dort weiter.
Limits
- 20 Aktionen pro Minute je IP-Adresse
-
POST/accounts/lastgangSession-CookieLädt eine Verbrauchsdatei aus dem Netzbetreiber-Portal hoch, die zweite Quelle für Lastgang-Daten neben der Datenfreigabe.
Request
datei*multipart/form-dataDie Portal-Exportdatei. Antwort
JSON, Status 201
status: 'gespeichert'.quellformat: Erkanntes Dateiformat.serien: Eine Zeile je erkannter Zählserie, mit Zeitraum und Anzahl neuer/aktualisierter Messwerte.
Fehler
401no_session: Keine Sitzung.413file_too_large: Datei über dem Limit.422unreadable: Datei nicht lesbar oder falsches Format.429rate_limited: Zu viele Uploads von dieser IP-Adresse.503storage_unavailable: Lastgang-Speicher gerade nicht angebunden.
Limits
- 3 Uploads pro Minute je IP-Adresse
- Datei bis 20 MB
-
POST/accounts/loginöffentlichMeldet ein bestätigtes Konto an und setzt das Sitzungs-Cookie für den Kontobereich.
Request
email*stringE-Mail-Adresse. password*stringPasswort. Antwort
JSON + Set-Cookie
ok: true bei Erfolg.
Fehler
401invalid_credentials: E-Mail-Adresse oder Passwort falsch, bewusst eine Meldung für beide Fälle.429rate_limited: Zu viele Anmeldeversuche von dieser IP-Adresse.
Limits
- 10 Anmeldeversuche pro Minute je IP-Adresse
-
POST/accounts/logoutSession-CookieBeendet die Sitzung und löscht das Sitzungs-Cookie.
Antwort
Status 204, kein Inhalt
-
GET/accounts/meSession-CookieZeigt den Stand des eigenen Kontos: Bestätigung, Einrichtung, Kundentyp, Alarm-Einstellung.
Antwort
JSON
email: Hinterlegte Adresse.email_verified: Bestätigt oder nicht.provisioning_status: Stand der Einrichtung.instance_slug: Kennung der eigenen Instanz.created_at: Angelegt am.alarm_mails: true = bekommt Nachrichten, wenn dem Zähler etwas auffällt.kundentyp: haushalt oder betrieb, steuert Du/Sie in den Texten.
Fehler
401no_session: Keine oder abgelaufene Sitzung.
-
POST/accounts/password/reset-confirmöffentlichSetzt mit dem Link-Token aus der Reset-Mail ein neues Passwort.
Request
token*stringReset-Token aus der Mail. password*stringNeues Passwort. Antwort
JSON
ok: true bei Erfolg.
Fehler
401kein fester Code: 'error' trägt Klartext, keinen festen Code: z. B. 'invalid or already used reset token', 'reset token expired' oder 'unknown account'.429rate_limited: Zu viele Versuche von dieser IP-Adresse.
Limits
- 5 Anfragen pro Minute je IP-Adresse
- Link 1 Stunde gültig
-
POST/accounts/password/reset-requestöffentlichStößt den Passwort-Reset an und verschickt bei einer bekannten Adresse einen Link.
Request
email*stringE-Mail-Adresse. Antwort
JSON, Status 202
status: 'accepted': immer dieselbe Antwort, unabhängig davon, ob die Adresse existiert.
Fehler
429rate_limited: Zu viele Anfragen von dieser IP-Adresse.
Limits
- 5 Anfragen pro Minute je IP-Adresse
-
POST/accounts/rechnungBearer-TokenNimmt eine Rechnungsdatei entgegen und gibt eine Kennung zurück, mit der read_invoice_facts sie liest. Die Datei passt nicht durch die Werkzeug-Schnittstelle und geht deshalb diesen Weg.
Request
datei*multipart/form-dataDie Rechnung als PDF, JPG oder PNG. Antwort
JSON, Status 201
rechnung_ref: Kennung für read_invoice_facts. Eine Stunde gültig.seiten: Seitenzahl der Datei.quellformat: pdf, jpeg oder png, aus der Datei erkannt und nicht aus dem Namen.textebene: true heisst, die Rechnung wird ohne Modell exakt gelesen. false heisst Foto oder Scan; dafür ist der Modell-Pfad noch nicht gebaut.
Fehler
401no_session: Keine Sitzung und kein gültiges Token.413file_too_large: Datei über dem Limit.415unsupported_format: Kein PDF, JPG oder PNG.422unreadable: Datei nicht zu öffnen oder zu viele Seiten.429rate_limited: Zu viele Uploads von dieser IP-Adresse.
Limits
- 3 Rechnungs-Uploads pro Minute je IP-Adresse
- höchstens 20 MB pro Rechnungsdatei
-
DELETE/accounts/rechnung/{rechnung_ref}Bearer-TokenLöscht eine hochgeladene Rechnung sofort, sobald die Werte bestätigt sind. Ohne diesen Aufruf verschwindet sie spätestens nach einer Stunde von selbst.
Request
rechnung_ref*Pfad-SegmentDie Kennung aus dem Upload. Antwort
Status 204, kein Inhalt
Fehler
401no_session: Keine Sitzung und kein gültiges Token.
-
POST/accounts/registeröffentlichLegt ein neues Konto an und verschickt eine Bestätigungsmail.
Request
email*stringE-Mail-Adresse, gleichzeitig der Login-Name. password*stringPasswort, mindestens 8 Zeichen. Antwort
JSON, Status 201
account_id: Kennung des neuen Kontos.
Fehler
422kein fester Code: 'error' trägt Klartext, keinen festen Code: z. B. 'gültige E-Mail erforderlich' oder 'E-Mail bereits registriert', je nachdem was nicht passt.429rate_limited: Zu viele Registrierungen von dieser IP-Adresse.
Limits
- 5 Registrierungen pro Minute je IP-Adresse
- 20 neue Konten pro Tag je IP-Adresse
-
POST/accounts/resend-verifyöffentlichSchickt die Bestätigungsmail erneut, wenn sie nicht angekommen ist.
Request
email*stringE-Mail-Adresse. Antwort
JSON, Status 202
status: 'accepted': immer dieselbe Antwort, unabhängig davon, ob die Adresse existiert.
Fehler
429rate_limited: Zu viele Anfragen von dieser IP-Adresse.
Limits
- 5 Anfragen pro Minute je IP-Adresse
-
POST/accounts/verifyöffentlichBestätigt die E-Mail-Adresse mit dem Token aus der Bestätigungsmail und stößt danach die Einrichtung des Kontos im Hintergrund an.
Request
account_id*stringKontokennung aus der Registrierung. token*stringBestätigungs-Token aus der Mail. Antwort
JSON
verified: true, wenn bestätigt.provisioning_scheduled: true: die Einrichtung läuft im Hintergrund weiter.
Fehler
401kein fester Code: 'error' trägt Klartext, keinen festen Code: z. B. 'unknown account or no pending verification' oder 'invalid verification token'.429rate_limited: Zu viele Bestätigungsversuche von dieser IP-Adresse.
Limits
- 10 Bestätigungen pro Minute je IP-Adresse
Zugriff & Freigaben
-
GET/accounts/einladungöffentlichZeigt, wer einen Zugriff angeboten hat, bevor man sich dafür anmeldet oder registriert.
Request
token*queryEinladungs-Token aus dem Einladungslink. Antwort
JSON
berater: E-Mail-Adresse der einladenden Person.email: Eingeladene Adresse.bezeichnung: Name des Mandats.gueltig_bis: Ablauf der Einladung.kundentyp: haushalt oder betrieb.
Fehler
404kein fester Code: 'error' trägt Klartext, keinen festen Code: 'kein Token', wenn der Query-Parameter fehlt, oder 'Einladung nicht gefunden', wenn der Token unbekannt, zurückgezogen oder abgelaufen ist. Bewusst dieselbe Antwort in allen Fällen, damit der Statuscode keine Auskunft über ein fremdes Konto verrät.
-
POST/accounts/me/alarmeSession-CookieSchaltet die Nachrichten ein oder aus, die kommen, wenn dem eigenen Zähler etwas auffällt.
Request
aus*booleantrue = Nachrichten abstellen, false = wieder einschalten. Antwort
JSON
alarm_mails: Neuer Stand: true = eingeschaltet.
Fehler
401no_session: Keine Sitzung.422kein fester Code: 'error' trägt Klartext, keinen festen Code: 'invalid body' bei kaputtem JSON, 'aus muss true oder false sein' wenn das Feld fehlt oder kein Wahrheitswert ist.429rate_limited: Zu viele Aktionen von dieser IP-Adresse.
Limits
- 20 Aktionen pro Minute je IP-Adresse
-
GET/accounts/me/freigabenSession-CookieZeigt, wer auf die eigenen Daten schauen darf, inklusive beendeter Freigaben.
Antwort
JSON
freigaben: Eine Zeile je Freigabe: Status, Gegenseite, Zeitpunkte.
Fehler
401no_session: Keine Sitzung.
-
POST/accounts/me/freigaben/{grant_id}/widerrufenSession-CookieBeendet eine Freigabe, wirkt ab dem nächsten Aufruf der Gegenseite.
Request
grant_id*PfadKennung der Freigabe. Antwort
JSON
status: Neuer Zustand der Freigabe.
Fehler
401no_session: Keine Sitzung.404kein fester Code: 'error' trägt Klartext ('Freigabe nicht gefunden.'), keinen festen Code: Freigabe existiert nicht oder gehört nicht zu diesem Konto.429rate_limited: Zu viele Aktionen von dieser IP-Adresse.
Limits
- 20 Aktionen pro Minute je IP-Adresse
-
POST/accounts/me/freigaben/{grant_id}/zustimmenSession-CookieStimmt einer angebotenen Freigabe zu. Erst danach kann die Gegenseite die Daten sehen.
Request
grant_id*PfadKennung der Freigabe. Antwort
JSON
status: Neuer Zustand der Freigabe.
Fehler
401no_session: Keine Sitzung.404kein fester Code: 'error' trägt Klartext ('Freigabe nicht gefunden.'), keinen festen Code: Freigabe existiert nicht oder gehört nicht zu diesem Konto.429rate_limited: Zu viele Aktionen von dieser IP-Adresse.
Limits
- 20 Aktionen pro Minute je IP-Adresse
-
GET/accounts/me/verbindungenSession-CookieZeigt, welche Chatbots gerade mit dem eigenen Konto verbunden sind.
Antwort
JSON
verbindungen: Eine Zeile je verbundener App: Name, ob Dauerzugriff, gültig bis, zuletzt verbunden.
Fehler
401no_session: Keine Sitzung.
-
POST/accounts/me/verbindungen/entziehenSession-CookieTrennt eine verbundene App sofort, nicht erst zum Ablauf des Zugangs.
Request
client_id*stringKennung der zu trennenden App, aus der Verbindungsliste. Antwort
JSON
entzogen: Anzahl entwerteter Zugänge.verbindungen: Die aktualisierte Liste.
Fehler
401no_session: Keine Sitzung.422kein fester Code: 'error' trägt Klartext, keinen festen Code: 'invalid body' bei kaputtem JSON, 'client_id fehlt' wenn das Feld fehlt oder leer ist.429rate_limited: Zu viele Aktionen von dieser IP-Adresse.
Limits
- 20 Aktionen pro Minute je IP-Adresse
-
GET/alarm/abmeldensignierter Link aus einer E-MailEin-Klick-Abmeldung von den Alarm-Mails direkt aus der E-Mail, ohne Anmeldung.
Request
token*querySignierter Abmelde-Token aus der Mail. Antwort
HTML-Seite
Fehler
400kein fester Code: Token nicht lesbar. Die Seite zeigt einen Hinweis, keine Auskunft über die Adresse.
App-Session
-
GET/app/aktivitaetSession-CookieMitschrift, was der Chat zuletzt an Werkzeugen aufgerufen hat: Werkzeug, Zeit, Erfolg, nie Argumente oder Ergebnisse.
Request
tagequery, 1–30Zeitraum zurück, Default 1 Tag. Antwort
JSON
eintraege: Eine Zeile je Aufruf: Werkzeug, Familie, Zeitpunkt, Erfolg, Fehlerklasse.
Fehler
401no_session: Keine Sitzung.422invalid_tage: 'tage' außerhalb 1–30.
-
POST/app/eda-abfrageSession-CookieStößt eine Datenfreigabe-Anfrage beim Netzbetreiber aus der App heraus an, dasselbe Werkzeug wie im Chat.
Request
(Body)*objectDie Argumente des Werkzeugs request_data_release (zaehlpunkt, plz, energy_direction). Antwort
JSON: dasselbe Result wie im Chat
Fehler
401no_session: Keine Sitzung.415unsupported_media_type: Content-Type ist nicht application/json.422invalid_body: Body kein gültiges JSON-Objekt.429rate_limited: Zu viele Aufrufe von dieser IP-Adresse.
Limits
- 60 Aufrufe pro Minute je IP-Adresse
-
POST/app/rueckfrageSession-CookieBeantwortet eine offene Lastgang-Rückfrage aus der App heraus, dasselbe Werkzeug wie im Chat.
Request
(Body)*objectDie Argumente des Werkzeugs answer_lastgang_question. Antwort
JSON: dasselbe Result wie im Chat
Fehler
401no_session: Keine Sitzung.415unsupported_media_type: Content-Type ist nicht application/json.422invalid_body: Body kein gültiges JSON-Objekt.429rate_limited: Zu viele Aufrufe von dieser IP-Adresse.
Limits
- 60 Aufrufe pro Minute je IP-Adresse
-
POST/app/toolSession-CookieRuft ein lesendes Werkzeug des Katalogs über das Sitzungs-Cookie auf, dieselbe Antwort wie im Chat.
Request
name*stringWerkzeugname aus dem Katalog. argumentsobjectEingabe des Werkzeugs, wie im inputSchema beschrieben. Antwort
JSON: dasselbe Result wie ein MCP-tools/call
Fehler
401no_session: Keine Sitzung.403nur_lesend: Das Werkzeug ist über diesen Weg nicht aufrufbar. Nur lesende Werkzeuge, unbekannte Namen bekommen dieselbe Antwort.415unsupported_media_type: Content-Type ist nicht application/json.422invalid_body: Body kein gültiges JSON-Objekt oder 'name' fehlt.429rate_limited: Zu viele Aufrufe von dieser IP-Adresse.
Limits
- 60 Aufrufe pro Minute je IP-Adresse
Lastgang-Rückfragen
-
GET/lastgang/antwortsignierter Link aus einer E-MailZeigt die Antwortmöglichkeiten zu einer Auffälligkeit aus der Alarm-Mail.
Request
t*queryVerschlüsselter Token aus der Mail (Ereignis + Option). Antwort
HTML-Seite
Fehler
404kein fester Code: Link gilt nicht mehr: schon beantwortet oder abgeschnitten.
-
POST/lastgang/antwortsignierter Link aus einer E-MailSpeichert die gewählte oder frei getippte Antwort zu einer Auffälligkeit.
Request
t*string (Form)Derselbe Token wie beim Anzeigen. freitextstring (Form), bis 200 ZeichenEigene Erklärung, wenn keine der Optionen passt. Antwort
HTML-Seite (Dankesseite, ggf. mit Rückschau)
Fehler
404kein fester Code: Link gilt nicht mehr.429kein fester Code: Zu viele Versuche von dieser IP-Adresse in kurzer Zeit.500kein fester Code: Speichern fehlgeschlagen, später erneut versuchen.
Limits
- 10 Antworten pro Minute je IP-Adresse
Match meinen Strom
-
POST/matchme/demoöffentlichRechnet ohne Anmeldung ein Beispielergebnis der Partnersuche vor, aus frei eingegebenen Eckdaten.
Request
jahresverbrauch_kwh*numberJahresverbrauch laut Rechnung. waermepumpe*booleanWärmepumpe vorhanden? eauto*booleanE-Auto vorhanden? warmwasser_elektrisch*booleanWarmwasser elektrisch? Antwort
JSON
Fehler
422validation_rejected: Eingabe außerhalb der erlaubten Werte.429rate_limited: Zu viele Aufrufe: je IP-Adresse und insgesamt.
Limits
- 5 Aufrufe pro Minute je IP-Adresse
- 60 Aufrufe pro Minute insgesamt (zusätzliche Bremse, nicht an eine einzelne IP-Adresse gebunden)
-
POST/matchme/einladungSession-CookieErzeugt einen persönlichen Einladungslink fürs Matching mit einer bestimmten Person.
Antwort
JSON, Status 201
link: Einladungslink zum Weitergeben.gueltig_bis: Ablaufdatum.
Fehler
401no_session: Keine Sitzung.429rate_limited: Zu viele Aktionen von dieser IP-Adresse.
Limits
- 20 Aktionen pro Minute je IP-Adresse
-
POST/matchme/einladung/einloesenSession-CookieNimmt eine Matching-Einladung an und bildet das Paar.
Request
token*stringToken aus dem Einladungslink. Antwort
JSON
partner_label: E-Mail-Adresse der einladenden Person.
Fehler
401no_session: Keine Sitzung.429rate_limited: Zu viele Aktionen von dieser IP-Adresse.
Limits
- 20 Aktionen pro Minute je IP-Adresse
-
POST/matchme/einladung/vorschauöffentlichZeigt vor der Anmeldung, von wem eine Matching-Einladung kommt.
Request
token*stringToken aus dem Einladungslink, nur im Body, nie in der Adresszeile. Antwort
JSON
von: E-Mail-Adresse der einladenden Person.
Fehler
429rate_limited: Zu viele Anfragen von dieser IP-Adresse.
Limits
- 20 Aktionen pro Minute je IP-Adresse
-
POST/matchme/einladung/widerrufSession-CookieZieht eine eigene, noch offene Einladung zurück.
Request
id*stringKennung der Einladung. Antwort
JSON
Fehler
401no_session: Keine Sitzung.422validation_rejected: 'id' fehlt.429rate_limited: Zu viele Aktionen von dieser IP-Adresse.
Limits
- 20 Aktionen pro Minute je IP-Adresse
-
GET/matchme/einladungenSession-CookieListet die eigenen Einladungen, verschickte und erhaltene.
Antwort
JSON
einladungen: Eine Zeile je Einladung: Status, Rolle, Zeitpunkte, Partner (nur bei eingelöst).
Fehler
401no_session: Keine Sitzung.
-
GET/matchme/matchesSession-CookieZeigt die Rangliste passender Partnerprofile, ohne Namen, ohne Zählpunkte, ohne genaue Jahresmengen.
Antwort
JSON
Fehler
401no_session: Keine Sitzung.403kein_optin: Eigenes Profil ist nicht für die Partnersuche freigegeben.409kein_lastgang: Keine verwertbare eigene Verbrauchsserie.
-
GET/matchme/optinSession-CookieZeigt, ob das eigene Profil gerade für die Partnersuche anderer mitgerechnet werden darf.
Antwort
JSON
status: 'active' | 'revoked' | 'none'.
Fehler
401no_session: Keine Sitzung.
-
POST/matchme/optinSession-CookieGibt das eigene Profil für die Partnersuche frei.
Antwort
JSON
status: 'active'.
Fehler
401no_session: Keine Sitzung.429rate_limited: Zu viele Aktionen von dieser IP-Adresse.
Limits
- 20 Aktionen pro Minute je IP-Adresse
-
POST/matchme/optin/widerrufSession-CookieNimmt das eigene Profil wieder aus der Partnersuche.
Antwort
JSON
status: 'revoked' oder 'none', wenn es ohnehin keinen aktiven Opt-in gab.
Fehler
401no_session: Keine Sitzung.429rate_limited: Zu viele Aktionen von dieser IP-Adresse.
Limits
- 20 Aktionen pro Minute je IP-Adresse
-
GET/matchme/statusSession-CookieZeigt den eigenen Stand: Opt-in, Zählpunkt (maskiert), Datenlage.
Antwort
JSON
Fehler
401no_session: Keine Sitzung.
Kontakt
-
POST/contactöffentlichKontaktformular der Website, schickt eine Nachricht.
Request
(Formularfelder)*objectName, E-Mail-Adresse, Nachricht. Antwort
JSON, Status 202
status: 'accepted'.
Fehler
422kein fester Code: Body fehlt oder ungültig.429rate_limited: Zu viele Nachrichten von dieser IP-Adresse.
Limits
- 5 Nachrichten pro Minute je IP-Adresse
OAuth / Verbindung
-
GET/.well-known/oauth-authorization-serveröffentlichDiscovery-Dokument des Authorization Servers (RFC 8414): Endpunkte, Scopes, unterstützte Verfahren.
Antwort
JSON
-
GET/.well-known/oauth-protected-resourceöffentlichDiscovery-Dokument der geschützten Ressource (RFC 9728). Bindet mcp.gridbert.at an seinen Authorization Server.
Antwort
JSON
-
GET/authorizeöffentlich (Anmelde-/Verbindungsseite)Zeigt die Anmelde- bzw. Registrierungsseite, über die ein Mensch die Verbindung seines Chatbots bestätigt.
Request
client_id, redirect_uri, …*queryOAuth-Parameter des Connectors (PKCE, Scope, State). Antwort
HTML-Seite
Fehler
400kein fester Code: Pflichtangaben fehlen oder die Anfrage ist unbekannt.
-
POST/authorizeöffentlich (Zugangsdaten im Formular, kein Cookie/Header)Verarbeitet Anmeldung, Registrierung oder Bestätigung auf der Verbindungsseite und leitet mit einem Autorisierungs-Code zurück.
Request
intentstring'login' (Default), 'register' oder 'connect': welches der drei Formulare abgeschickt wurde. email, passwordstringBei Anmeldung oder Registrierung. client_id, redirect_uri, code_challenge, …*stringOAuth-Parameter, unverändert aus dem vorherigen Schritt übernommen. Antwort
302-Redirect mit Code (oder erneut die HTML-Seite bei einem Fehler)
Fehler
401access_denied: Anmeldedaten falsch.429rate_limited: Zu viele Anmeldeversuche von dieser IP-Adresse.
Limits
- 30 Anmeldungen pro Minute je IP-Adresse
-
GET/jwks.jsonöffentlichÖffentlicher Schlüssel, mit dem Zugangs-Token signiert sind (JWK Set).
Antwort
JSON
-
POST/mcpBearer-TokenDer eine JSON-RPC-Endpunkt, über den ein verbundener Chatbot alle Werkzeuge aufruft.
Request
jsonrpc, id, method, params*JSON-RPC 2.0method ist eine der unterstützten Methoden (initialize, tools/list, tools/call, notifications/initialized). Antwort
JSON-RPC-Antwort mit content[] und structuredContent
Fehler
401invalid_token: Kein oder ungültiges Bearer-Token.400parse error: Body kein gültiges JSON.400unknown method: Nicht unterstützte Methode.
Limits
- 30 Aufrufe Startguthaben
- füllt mit 0.5 Aufrufen pro Sekunde nach
- 2000 Aufrufe pro Tag je Konto
- Anfrage bis 256 KB
- Werkzeug-Eingabe bis 150 KB
-
POST/registeröffentlich (Client-Registrierung, DCR)Dynamic Client Registration (RFC 7591). Ein Chatbot meldet sich einmalig als Client an, bevor er eine Verbindung anbietet.
Request
client_namestringAnzeigename des Clients. redirect_uris*string[]Erlaubte Rücksprung-Adressen nach der Anmeldung. Antwort
JSON, Status 201
client_id: Neue Client-Kennung.token_endpoint_auth_method: 'none': öffentlicher Client mit PKCE.
Fehler
400invalid_client_metadata: Body kein gültiges JSON.422invalid_redirect_uri: Rücksprung-Adresse nicht erlaubt oder Cap erreicht.
Limits
- 5 Registrierungen pro Minute je IP-Adresse
- höchstens 20 offene Client-Registrierungen je IP-Adresse
-
POST/tokenöffentlich (Client-Zugangsdaten im Body)Tauscht einen Autorisierungs-Code oder ein Refresh-Token gegen ein Zugangs-Token.
Request
grant_type*string'authorization_code' oder 'refresh_token'. code, redirect_uri, client_id, code_verifierstringBei grant_type=authorization_code (PKCE). refresh_token, client_idstringBei grant_type=refresh_token. Antwort
JSON
access_token: Kurzlebiges Zugangs-Token.refresh_token: Langlebiges Token zum Erneuern.expires_in: Gültigkeit des Zugangs-Tokens in Sekunden.
Fehler
400unsupported_grant_type: grant_type ist weder authorization_code noch refresh_token.400invalid_grant: Code, Token oder PKCE passt nicht oder ist abgelaufen.429rate_limited: Zu viele Anfragen von diesem Client.
Limits
- 30 Token-Anfragen pro Minute je Client
Grenzen und Regeln
Rate-Limits
- 10 Anmeldeversuche pro Minute je IP-Adresse
- 10 Antworten pro Minute je IP-Adresse
- 10 Bestätigungen pro Minute je IP-Adresse
- 20 Aktionen pro Minute je IP-Adresse
- 20 neue Konten pro Tag je IP-Adresse
- 2000 Aufrufe pro Tag je Konto
- 3 Rechnungs-Uploads pro Minute je IP-Adresse
- 3 Uploads pro Minute je IP-Adresse
- 30 Anmeldungen pro Minute je IP-Adresse
- 30 Aufrufe Startguthaben
- 30 Token-Anfragen pro Minute je Client
- 5 Anfragen pro Minute je IP-Adresse
- 5 Aufrufe pro Minute je IP-Adresse
- 5 Nachrichten pro Minute je IP-Adresse
- 5 Registrierungen pro Minute je IP-Adresse
- 60 Aufrufe pro Minute insgesamt (zusätzliche Bremse, nicht an eine einzelne IP-Adresse gebunden)
- 60 Aufrufe pro Minute je IP-Adresse
- füllt mit 0.5 Aufrufen pro Sekunde nach
- höchstens 20 MB pro Rechnungsdatei
Größe der Anfragen
- Anfrage bis 16 KB auf den OAuth-/Konto-Endpunkten
- Anfrage bis 256 KB auf /mcp
- Werkzeug-Eingabe bis 150 KB je Werkzeug-Aufruf
- Datei bis 20 MB beim Lastgang-Upload
Herkunft im Browser
Nur eine hinterlegte Liste von Ursprüngen darf die Konto-Endpunkte per Browser-JavaScript ansprechen. Ein weiterer Ursprung wird über den Kontakt freigeschaltet, nicht selbst eingetragen.
Umgang mit Daten
- Rechnungs- und Lastgang-Inhalte stehen nie in Server-Logs, nur in den Tool-Ergebnissen selbst.
- Ein Fehler nennt die Fehlerklasse (z. B. rate_limited, not_configured), nie den internen Grund dahinter.
- Jede Euro-Zahl aus einem Werkzeug trägt ihren Rechenweg mit. Es wird nichts im Sprachmodell nachgerechnet.
Nicht Teil der Schnittstelle
GET /lastgang/antwort, POST /lastgang/antwort: Ein Link aus einer E-Mail, kein Aufruf für einen eigenen Client. Der Token gehört zu genau einer Mail.GET /alarm/abmelden: Ebenfalls ein Link aus einer E-Mail, kein Aufruf für einen eigenen Client./admin/*: Betreiber-Werkzeug, nicht öffentlich. Kein Bearer-Token dieser Schnittstelle öffnet es.
Stand
16. September 2026, erzeugt aus dem Code, nicht von Hand nachgetragen. Ändert sich ein Werkzeug oder ein Endpunkt im Gateway, zieht diese Seite beim nächsten Build nach.
Du willst selbst etwas auf Gridbert bauen? Die Einrichtung je Agent zeigt den Klickweg, diese Seite die Referenz dahinter. Fragen dazu gehen an den Kontakt.