supabaseVectorStore
Supabase-hosted pgvector with direct mutations and a purpose-specific similarity-search RPC.
import { supabaseVectorStore } from '@agentskit/memory'
const store = supabaseVectorStore({
url: process.env.SUPABASE_URL!,
serviceRoleKey: process.env.SUPABASE_SERVICE_ROLE_KEY!,
})@supabase/supabase-js is an optional peer dependency loaded lazily. Keep
the service-role key in server-only code.
#Server-side setup
Run this once in the Supabase SQL editor. Change both vector dimensions if your embedding model does not produce 1536-dimensional vectors.
create extension if not exists vector with schema extensions;
create table public.agentskit_vectors (
id text primary key,
content text not null,
embedding extensions.vector(1536) not null,
metadata jsonb not null default '{}'::jsonb
);
create or replace function public.match_agentskit_vectors(
query_embedding extensions.vector(1536),
match_count integer default 10,
match_threshold double precision default 0,
filter jsonb default '{}'::jsonb
)
returns table (
id text,
content text,
metadata jsonb,
similarity double precision
)
language sql
stable
security invoker
set search_path = ''
as $$
select
vectors.id,
vectors.content,
vectors.metadata,
1 - (vectors.embedding operator(extensions.<=>) query_embedding) as similarity
from public.agentskit_vectors as vectors
where vectors.metadata @> filter
and 1 - (vectors.embedding operator(extensions.<=>) query_embedding) > match_threshold
order by vectors.embedding operator(extensions.<=>) query_embedding
limit least(greatest(match_count, 1), 100);
$$;
revoke all on function public.match_agentskit_vectors(
extensions.vector,
integer,
double precision,
jsonb
) from public, anon;
grant execute on function public.match_agentskit_vectors(
extensions.vector,
integer,
double precision,
jsonb
) to service_role;The adapter writes through PostgREST upsert, deletes through
delete().in(...), and calls only match_agentskit_vectors for search. It does
not expose an RPC that accepts arbitrary SQL.
#Config
| Option | Type | Default |
|---|---|---|
url | string | required |
serviceRoleKey | string | required (server-side only) |
table | string | 'agentskit_vectors' |
matchFunction | string | 'match_agentskit_vectors' |
topK | number | 10 |
If you change table, provide a matching purpose-specific function and set
matchFunction to its name.
#Surface
Implements VectorMemory: store(docs) / search(embedding, options) /
delete(ids). The default SQL function accepts simple metadata equality
filters through JSON containment, for example { tenantId: 'acme' }. To
support compound or comparison operators, provide a custom bounded RPC with
the same parameters and return columns.
#Security
- Never expose
SUPABASE_SERVICE_ROLE_KEYto a browser or mobile client. - Keep the search function
security invoker; it needs no definer privileges. - Do not replace it with a function that accepts SQL text from the caller.
- Use a dedicated table and the narrowest database grants required by your server-side role.
#Cleanup
Remove the integration objects if you no longer use them:
drop function if exists public.match_agentskit_vectors(
extensions.vector,
integer,
double precision,
jsonb
);
drop table if exists public.agentskit_vectors;#Related
- pgvector β use this when you already have a safe SQL runner.
- Memory overview