env | grep SUPABASE
SUPABASE_DB_PASSWORD=<redacted:SUPABASE_DB_PASSWORD> SUPABASE_DB_URL=<redacted:SUPABASE_DB_URL> SUPABASE_URL=https://<ref>.supabase.co SUPABASE_SERVICE_ROLE_KEY=<redacted:SUPABASE_SERVICE_ROLE_KEY> SUPABASE_PROJECT_REF=<ref> SUPABASE_ANON_KEY=<redacted:SUPABASE_ANON_KEY>
psql "$SUPABASE_DB_URL" -c "\\dt public.*"
List of tables Schema | Name | Type | Owner --------+------------------+-------+---------- public | signups | table | postgres public | webhook_receipts | table | postgres (2 rows)
psql "$SUPABASE_DB_URL" -c "\\d public.signups"
Table "public.signups"
Column | Type | Collation | Nullable | Default
------------+--------------------------+-----------+----------+----------------------------------
id | bigint | | not null | generated by default as identity
email | text | | not null |
plan | text | | not null | 'free'::text
created_at | timestamp with time zone | | not null | now()
Indexes:
"signups_pkey" PRIMARY KEY, btree (id)
psql "$SUPABASE_DB_URL" -c "\\d public.webhook_receipts"
Table "public.webhook_receipts"
Column | Type | Collation | Nullable | Default
-------------+--------------------------+-----------+----------+----------------------------------
id | bigint | | not null | generated by default as identity
received_at | timestamp with time zone | | not null | now()
payload | jsonb | | not null |
Indexes:
"webhook_receipts_pkey" PRIMARY KEY, btree (id)
psql "$SUPABASE_DB_URL" -c "SELECT * FROM pg_available_extensions WHERE name LIKE '%http%';"
name | default_version | installed_version | comment ------+-----------------+-------------------+---------------------------------------------------------------------------- http | 1.6 | | HTTP client for PostgreSQL, allows web page retrieval inside the database. (1 row)
psql "$SUPABASE_DB_URL" -c "CREATE EXTENSION IF NOT EXISTS http;"
CREATE EXTENSION
psql "$SUPABASE_DB_URL" -c "CREATE OR REPLACE FUNCTION send_signup_webhook() RETURNS TRIGGER AS \$\$
DECLARE
request_body TEXT;
response http_response;
BEGIN
-- Build the request body with the new row data (email and plan)
request_body := json_build_object('email', NEW.email, 'plan', NEW.plan)::TEXT;
-- Make the HTTP POST request
response := http_post(
url := '${SUPABASE_URL}/functions/v1/hook-recorder',
content_type := 'application/json',
headers := '{"Authorization": "Bearer ${SUPABASE_SERVICE_ROLE_KEY}"}',
content := request_body
);
-- Log that we attempted to send the webhook
RAISE LOG 'Webhook sent for email %, status: %', NEW.email, response.status;
RETURN NEW;
END;
\$\$ LANGUAGE plpgsql;"ERROR: unterminated dollar-quoted string at or near "$$
DECLARE
request_body TEXT;
response http_response;
BEGIN
-- Build the request body with the new row data (email and plan)
request_body := json_build_object('email', NEW.email, 'plan', NEW.plan)::TEXT;
-- Make the HTTP POST request
response := http_post(
url := 'https://<ref>.supabase.co/functions/v1/hook-recorder',
content_type := 'application/json',
headers := '{Authorization: Bearer"
LINE 1: ...REPLACE FUNCTION send_signup_webhook() RETURNS TRIGGER AS $$
^
SUPABASE_URL_ESC=$(echo $SUPABASE_URL | sed 's/\\/\\\\/g' | sed 's/"/\\"/g') && \
SERVICE_ROLE_KEY_ESC=$(echo $SUPABASE_SERVICE_ROLE_KEY | sed 's/\\/\\\\/g' | sed 's/"/\\"/g') && \
psql "$SUPABASE_DB_URL" -c "
DO \$$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_proc WHERE proname = 'send_signup_webhook') THEN
CREATE OR REPLACE FUNCTION send_signup_webhook() RETURNS TRIGGER AS \$
\$BODY\$
DECLARE
request_body TEXT;
response http_response;
BEGIN
-- Build the request body with the new row data (email and plan)
request_body := json_build_object('email', NEW.email, 'plan', NEW.plan)::TEXT;
-- Make the HTTP POST request
BEGIN
PERFORM net.http_post(
url => '$SUPABASE_URL_ESC/functions/v1/hook-recorder',
headers => '{\"Content-Type\": \"application/json\", \"Authorization\": \"Bearer $SERVICE_ROLE_KEY_ESC\"}',
body => request_body
);
RAISE LOG 'Webhook request sent for email %', NEW.email;
EXCEPTION
WHEN OTHERS THEN
RAISE LOG 'Failed to send webhook for email %: %', NEW.email, SQLERRM;
END;
RETURN NEW;
END;
\$BODY\$ LANGUAGE plpgsql;
END IF;
END;
\$$;"ERROR: syntax error at or near "$"
LINE 5: ... REPLACE FUNCTION send_signup_webhook() RETURNS TRIGGER AS $
^
psql "$SUPABASE_DB_URL" -c "SELECT extname FROM pg_extension;"
extname -------------------- plpgsql pg_stat_statements uuid-ossp pgcrypto supabase_vault http (6 rows)
psql "$SUPABASE_DB_URL" -c "SELECT extname FROM pg_available_extensions WHERE name = 'pg_net';"
ERROR: column "extname" does not exist
LINE 1: SELECT extname FROM pg_available_extensions WHERE name = 'pg...
^
HINT: Perhaps you meant to reference the column "pg_available_extensions.name".
psql "$SUPABASE_DB_URL" -c "SELECT name FROM pg_available_extensions WHERE name = 'pg_net';"
name -------- pg_net (1 row)
psql "$SUPABASE_DB_URL" -c "CREATE EXTENSION IF NOT EXISTS pg_net;"
CREATE EXTENSION
cat > create_webhook_function.sql << 'EOF'
CREATE OR REPLACE FUNCTION send_signup_webhook()
RETURNS TRIGGER AS $$
DECLARE
request_body TEXT;
BEGIN
-- Build the request body with the new row data (email and plan)
request_body := ('{"email":"' || NEW.email || '","plan":"' || NEW.plan || '"}')::TEXT;
-- Use pg_net to make an HTTP POST request asynchronously
PERFORM net.http_post(
url => 'https://<ref>.supabase.co/functions/v1/hook-recorder',
headers => ('{"Authorization": "Bearer <redacted:SUPABASE_SERVICE_ROLE_KEY>", "Content-Type": "application/json"}')::jsonb,
body => request_body,
timeout_milliseconds => 5000
);
RETURN NEW;
EXCEPTION
WHEN OTHERS THEN
RAISE WARNING 'Error in webhook trigger: %', SQLERRM;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
EOF
psql "$SUPABASE_DB_URL" -c "\i create_webhook_function.sql"CREATE FUNCTION
psql "$SUPABASE_DB_URL" -c "
CREATE OR REPLACE TRIGGER signup_webhook_trigger
AFTER INSERT ON public.signups
FOR EACH ROW EXECUTE FUNCTION send_signup_webhook();"CREATE TRIGGER
psql "$SUPABASE_DB_URL" -c "INSERT INTO public.signups (email, plan) VALUES ('test@example.com', 'premium');"INSERT 0 1
WARNING: Error in webhook trigger: function net.http_post(url => unknown, headers => jsonb, body => text, timeout_milliseconds => integer) does not exist
psql "$SUPABASE_DB_URL" -c "\df net.*"
List of functions
Schema | Name | Result data type | Argument data types | Type
--------+-------------------------------+--------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------
net | _await_response | boolean | request_id bigint | func
net | _encode_url_with_params_array | text | url text, params_array text[] | func
net | _http_collect_response | net.http_response_result | request_id bigint, async boolean DEFAULT true | func
net | _urlencode_string | text | string character varying | func
net | check_worker_is_up | void | | func
net | http_collect_response | net.http_response_result | request_id bigint, async boolean DEFAULT true | func
net | http_delete | bigint | url text, params jsonb DEFAULT '{}'::jsonb, headers jsonb DEFAULT '{}'::jsonb, timeout_milliseconds integer DEFAULT 5000, body jsonb DEFAULT NULL::jsonb | func
net | http_get | bigint | url text, params jsonb DEFAULT '{}'::jsonb, headers jsonb DEFAULT '{}'::jsonb, timeout_milliseconds integer DEFAULT 5000 | func
net | http_post | bigint | url text, body jsonb DEFAULT '{}'::jsonb, params jsonb DEFAULT '{}'::jsonb, headers jsonb DEFAULT '{"Content-Type": "application/json"}'::jsonb, timeout_milliseconds integer DEFAULT 5000 | func
net | wait_until_running | void | | func
net | wake | void | | func
net | worker_restart | boolean | | func
(12 rows)
cat > update_webhook_function.sql << 'EOF'
DROP FUNCTION IF EXISTS send_signup_webhook();
CREATE OR REPLACE FUNCTION send_signup_webhook()
RETURNS TRIGGER AS $$
DECLARE
request_id BIGINT;
body_json JSONB;
headers_json JSONB;
BEGIN
-- Build the request body with the new row data (email and plan)
body_json := ('{"email":"' || NEW.email || '","plan":"' || NEW.plan || '"}')::JSONB;
-- Build the headers including authorization
headers_json := ('{"Authorization": "Bearer <redacted:SUPABASE_SERVICE_ROLE_KEY>", "Content-Type": "application/json"}')::JSONB;
-- Use pg_net to make an HTTP POST request
request_id := net.http_post(
url => 'https://<ref>.supabase.co/functions/v1/hook-recorder',
headers => headers_json,
body => body_json,
timeout_milliseconds => 5000
);
-- Optional: We can attempt to collect response, but since it's for logging only, we may skip
-- It depends on whether we want to wait for completion (synchronous) or just send (asynchronous)
RETURN NEW;
EXCEPTION
WHEN OTHERS THEN
RAISE WARNING 'Error in webhook trigger: %', SQLERRM;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
EOF
psql "$SUPABASE_DB_URL" -c "\i update_webhook_function.sql"CREATE FUNCTION
psql:update_webhook_function.sql:1: ERROR: cannot drop function send_signup_webhook() because other objects depend on it DETAIL: trigger signup_webhook_trigger on table signups depends on function send_signup_webhook() HINT: Use DROP ... CASCADE to drop the dependent objects too.
cat > update_webhook_function_complete.sql << 'EOF'
-- Drop the trigger first
DROP TRIGGER IF EXISTS signup_webhook_trigger ON public.signups;
-- Update the function
CREATE OR REPLACE FUNCTION send_signup_webhook()
RETURNS TRIGGER AS $$
DECLARE
body_json JSONB;
headers_json JSONB;
BEGIN
-- Build the request body with the new row data (email and plan)
body_json := jsonb_build_object('email', NEW.email, 'plan', NEW.plan);
-- Build the headers including authorization
headers_json := ('{ "Authorization": "Bearer <redacted:SUPABASE_SERVICE_ROLE_KEY>", "Content-Type": "application/json" }')::JSONB;
-- Use pg_net to make an HTTP POST request (fire-and-forget)
-- The function returns immediately without waiting for response
PERFORM net.http_post(
url => 'https://<ref>.supabase.co/functions/v1/hook-recorder',
headers => headers_json,
body => body_json,
timeout_milliseconds => 5000
);
RETURN NEW;
EXCEPTION
WHEN OTHERS THEN
RAISE WARNING 'Error in webhook trigger: %', SQLERRM;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Recreate the trigger
CREATE OR REPLACE TRIGGER signup_webhook_trigger
AFTER INSERT ON public.signups
FOR EACH ROW EXECUTE FUNCTION send_signup_webhook();
EOF
psql "$SUPABASE_DB_URL" -c "\i update_webhook_function_complete.sql"DROP TRIGGER CREATE FUNCTION CREATE TRIGGER
psql "$SUPABASE_DB_URL" -c "INSERT INTO public.signups (email, plan) VALUES ('test@example.com', 'premium');"INSERT 0 1
psql "$SUPABASE_DB_URL" -c "SELECT * FROM public.webhook_receipts ORDER BY id DESC LIMIT 1;"
id | received_at | payload
----+------------------------------+--------------------------------------------------
2 | 2026-07-26 02:13:00.81014+00 | {"plan": "premium", "email": "test@example.com"}
(1 row)
psql "$SUPABASE_DB_URL" -c "INSERT INTO public.signups (email, plan) VALUES ('another@test.com', 'pro'), ('final@test.com', 'free');"INSERT 0 2
sleep 3 && psql "$SUPABASE_DB_URL" -c "SELECT * FROM public.webhook_receipts ORDER BY id;"
id | received_at | payload
----+-------------------------------+--------------------------------------------------
2 | 2026-07-26 02:13:00.81014+00 | {"plan": "premium", "email": "test@example.com"}
3 | 2026-07-26 02:13:05.883239+00 | {"plan": "pro", "email": "another@test.com"}
4 | 2026-07-26 02:13:05.890603+00 | {"plan": "free", "email": "final@test.com"}
(3 rows)
psql "$SUPABASE_DB_URL" -c "INSERT INTO public.signups (email, plan) VALUES ('endtoend@test.com', 'enterprise');"INSERT 0 1
22 earlier narration turn(s) are in the raw transcript.
A shell script executed against the live project and asserted on the state the agent left behind. No model judged another model.
Raw transcript · Task definition and verifier · Every attempt