Supabase (eigene Datenbank)
Workspace-eigene Postgres-DB via Supabase als Backend.
Wenn dein Workspace eigene strukturierte Daten braucht — eigene Tabellen, Queries, Beziehungen — ist Supabase eine leichtgewichtige Variante: Postgres + auto-generierte REST-API, ohne eigenen Backend-Server.
Setup
- Du hast einen eigenen Supabase-Account (kostenlos für kleine Projekte).
- Im Manage-Bereich
/manage/supabase: URL und Service-Key eintragen. - Tabellen in Supabase anlegen (über deren Dashboard).
- Tools in deinem Workspace definieren, die diese Tabellen lesen / schreiben.
API-Definition
// apis.php
'supabase' => [
'base_url' => 'https://xxx.supabase.co/rest/v1/',
'headers' => [
'apikey' => 'eyJhbGciOi…',
'Authorization' => 'Bearer ' . 'eyJhbGciOi…',
'Content-Type' => 'application/json',
'Prefer' => 'return=representation',
],
],
Einfache Tools
'tools' => [
'createLead' => [
'description' => 'Lead in unserer Supabase-DB anlegen.',
'parameters' => [
'type' => 'object',
'properties' => [
'name' => ['type' => 'string'],
'email' => ['type' => 'string'],
'source' => ['type' => 'string'],
],
'required' => ['name', 'email'],
],
'api' => 'supabase',
'method' => 'POST',
'path' => 'leads',
'body' => [
'name' => '{name}',
'email' => '{email}',
'source' => '{source}',
],
'mapping' => [
'id' => '[0].id',
'created' => '[0].created_at',
],
],
'findLeads' => [
'description' => 'Leads suchen nach E-Mail-Teilstring.',
'parameters' => [
'type' => 'object',
'properties' => [
'email' => ['type' => 'string'],
'limit' => ['type' => 'integer'],
],
'required' => ['email'],
],
'api' => 'supabase',
'method' => 'GET',
'path' => 'leads?email=ilike.%25{email}%25&limit={limit}',
'mapping' => [
'results' => [
'id' => 'id',
'name' => 'name',
'email' => 'email',
],
],
],
];
Supabase-Query-Syntax
PostgREST (Supabase) nutzt Query-Operatoren im URL-Parameter:
| Operator | Beispiel | SQL |
|---|---|---|
eq |
status=eq.active |
= 'active' |
neq |
status=neq.archived |
!= 'archived' |
gt / gte |
created_at=gt.2026-01-01 |
> '2026-01-01' |
lt / lte |
price=lte.100 |
<= 100 |
like / ilike |
email=ilike.%example% |
ILIKE '%example%' |
in |
status=in.(active,pending) |
IN ('active','pending') |
order |
order=created_at.desc |
ORDER BY created_at DESC |
limit |
limit=10 |
LIMIT 10 |
Volle Referenz: postgrest.org/en/stable/api.html
Foreign-Key Joins
Supabase/PostgREST kann Beziehungen inline auflösen:
GET /orders?select=id,total,customer:customers(name,email)
Gibt Orders zurück mit verschachtelten Customer-Daten. In Tool-Form:
'getOrderWithCustomer' => [
'api' => 'supabase',
'method' => 'GET',
'path' => 'orders?id=eq.{id}&select=id,total,status,customer:customers(name,email)',
'mapping' => [
'id' => '[0].id',
'total' => '[0].total',
'customer' => '[0].customer',
],
];
Browser-UI zum Durchsuchen
Im Manage-Bereich unter /manage/supabase gibt's einen vollwertigen Daten-Browser im Supabase-Stil. Was er kann:
Tabellen-Browser
- Multi-Filter mit Operatoren:
=, !=, >, >=, <, <=, like, ilike, in, is. Klick auf "Filter hinzufügen" → Spalte → Operator → Wert. Beliebig viele Filter, alle als AND verknüpft. Auch mehrere Filter auf dieselbe Spalte möglich (z.B.created_at >= 2026-01-01 AND created_at < 2026-06-01). - Multi-Sort: Klick auf Spaltenkopf sortiert. Shift+Klick fügt eine weitere Sortierspalte hinzu (Priorität wird am Header angezeigt).
- Inline-Edit: Doppelklick auf Zelle, ändern, Enter zum Speichern.
- FK-Navigation: Klick auf eine UUID-Spalte (z.B.
customer_id) springt zur referenzierten Tabelle. - Combobox-Suggestions: Bei Spalten mit endlichen Werten (Enums, Status) zeigt der Editor existierende Werte als Vorschlag.
Group + Aggregation
Klick auf "Group" oben rechts schaltet den Aggregationsmodus ein. Dann:
- Group by eine oder mehrere Spalten
- Aggregation hinzufügen (
count, sum, avg, min, max) über beliebige Spalte - "Ausführen" rendert die Gruppenresultate als Tabelle
Das ist echtes Postgres GROUP BY, kein Client-Side-Aggregat — funktioniert auch bei Tabellen mit Millionen Zeilen. Die aktiven Filter werden in die WHERE-Klausel übernommen.
SQL Editor
Klick auf "SQL Editor" in der Sidebar öffnet einen Monaco-Editor mit Postgres-SQL-Syntax-Highlighting. Was er kann:
- Beliebige SELECT-Queries mit ergebnisbasierter Tabellen-Anzeige
- Writes (INSERT, UPDATE, DELETE, CREATE TABLE etc.) — vor dem Senden warnt eine gelbe Banderole
- Dry-Run: Bei Writes wrappt das System das Statement in
BEGIN ... ROLLBACK, sodass die Daten unverändert bleiben — perfekt um Auswirkungen zu prüfen - Snippets: SQL-Statements als Browser-lokale Bookmarks speichern (per Tenant)
- Shortcuts:
Ctrl/Cmd + Enterführt aus
Voraussetzung für den SQL Editor: exec_sql-Funktion muss in der Tenant-Supabase existieren (siehe Abschnitt "Schema-Änderungen via Tool" weiter unten).
Saved Views
Aktueller Tabellen-Browser-Zustand (Tabelle + Filter + Sort) als wiederverwendbare View speichern:
- "Speichern" oben rechts → Name eingeben → "Mit allen teilen?" (OK = shared, Abbrechen = privat)
- Views erscheinen in der Sidebar unter "Saved Views" — Klick lädt sie
- Eigene Views löschbar (Trash-Icon)
- Fremde shared Views kopierbar (Copy-Icon) — werden als neue private View angelegt
- Persistiert in der Tabelle
taskmonkey_views(wird beim ersten Zugriff automatisch im Tenant-Supabase angelegt)
Multi-Tenant-Setup
Der Browser ist generisch und funktioniert für jeden Tenant, der apis.supabase in seiner apis.php konfiguriert hat. Pflichtfelder:
'apis' => [
'supabase' => [
'url' => 'https://your-project.supabase.co',
'anon_key' => 'eyJhbG…',
'service_role_key' => 'eyJhbG…', // nötig für Writes und SQL Editor
'timeout' => 15, // optional
],
],
Optional: SQL Editor + Saved Views brauchen exec_sql (siehe unten).
Row-Level Security (RLS)
Supabase bietet RLS — pro-Zeile Zugriffsrechte. Entscheide:
- RLS an + Service-Role-Key: TaskMonkey umgeht RLS (bequem, aber alle Zeilen sichtbar)
- RLS an + User-Key: TaskMonkey respektiert RLS (komplexer, aber sicherer bei Multi-User-Szenarien)
Für rein interne Workspace-Automation reicht meist Variante 1. Für kundenorientierte Daten (mehrere Kunden teilen sich die DB) ist Variante 2 Pflicht.
Backup / Migration
Supabase macht automatische Daily-Backups (im Plan inkl.). Schema-Änderungen solltest du als SQL-Migrations versionieren, z. B. in deinem Workspace unter sql/ committen.
Schema-Änderungen via Tool (execSupabaseSql)
PostgREST (das HTTP-Frontend von Supabase) kann kein DDL — also kein ALTER TABLE, CREATE VIEW, CREATE INDEX. Trotzdem soll man von TaskMonkey aus Schema-Änderungen anstoßen können (Migrationen, neue Views, Bulk-Updates), ohne sich jedes Mal manuell ins Supabase SQL Editor einzuloggen.
Lösung: eine SECURITY-DEFINER-Function exec_sql(text) in der DB anlegen, die beliebiges SQL ausführt. Die ist nur für service_role aufrufbar, kein anon-User kommt da ran. Das Tool execSupabaseSql ruft diese Function über HTTP-RPC auf.
Einmal pro Supabase-Projekt, im SQL Editor ausführen:
CREATE OR REPLACE FUNCTION exec_sql(statement text)
RETURNS jsonb
LANGUAGE plpgsql
SECURITY DEFINER
AS $$
BEGIN
EXECUTE statement;
RETURN jsonb_build_object('ok', true);
EXCEPTION WHEN OTHERS THEN
RETURN jsonb_build_object('ok', false, 'error', SQLERRM, 'sqlstate', SQLSTATE);
END;
$$;
REVOKE EXECUTE ON FUNCTION exec_sql(text) FROM PUBLIC, anon, authenticated;
GRANT EXECUTE ON FUNCTION exec_sql(text) TO service_role;
Danach kann der Workspace-Assistent (oder du via CLI) Migrationen ausführen:
tm test-tool execSupabaseSql statements='[
"ALTER TABLE leads ADD COLUMN IF NOT EXISTS enriched_at TIMESTAMPTZ",
"CREATE INDEX IF NOT EXISTS idx_leads_enriched_at ON leads(enriched_at)"
]'
Konventionen:
- Immer idempotent (
IF NOT EXISTS,CREATE OR REPLACE) - Ein Statement pro Schritt — der Tool-Output meldet pro Statement Erfolg/Fehler einzeln
- DDL zuerst, danach Backfill-
UPDATEals eigenes Statement
Was nicht geht: Multi-Statement-Transactions, Session-Settings, Statements > 30 s Laufzeit (PostgREST-Timeout). Für solche Fälle lieber direkt im Supabase SQL Editor.
Mehr Details siehe docs/supabase-migrations.md.
Debug
tm test-tool findLeads email=test
tm logs # bei 400 → wahrscheinlich Syntax-Fehler in der Query
Supabase gibt bei Syntax-Fehlern sehr präzise Fehlermeldungen — lies sie genau.