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 Daten-Browser: Tabelle wählen, filtern, sortieren, einzelne Zeilen inline editieren. Nützlich für schnelle Prüfungen ohne separates Supabase-Dashboard.
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.