Я давно перестала верить в магию, когда дело касается хранения данных. Если AI-агент должен помнить контекст, понимать пользователя и предлагать точные действия — ему нужна системная память. В этой статье показываю, как я использую Supabase как надежную систему хранения данных для AI-агентов: от проектирования схемы в PostgreSQL и RLS до интеграции с n8n и Make.com, реального времени и Edge Functions. Разберем supabase auth, supabase api, самохостинг на supabase docker и нюансы 152-ФЗ. Материал для тех, кто строит автоматизацию без хайпа, предпочитает прозрачные процессы и честные метрики, и хочет, чтобы контент делался сам, а люди возвращали себе время.
Время чтения: ~15 минут
Зачем AI-агенту собственная память и почему здесь Supabase
Утро, кофе остыл, агент бодро реагирует на запросы, но через пять минут не может вспомнить, что обещал пользователю. Знакомо. Без устойчивого хранилища данных в компьютерных системах агент неизбежно превращается в попугая, который красиво отвечает, но не держит контекст и не учится. Для хранения данных используется не просто таблица, а продуманная система хранения баз данных: история сессий, сообщения, свойства пользователя, события, результаты вызовов инструментов, файлы. Мне важно, чтобы это работало прозрачно, с понятной авторизацией, с ролевой безопасностью и без танцев вокруг очередной заглушки. В supabase я получаю PostgreSQL, supabase auth, файловое хранилище, realtime, Edge Functions и удобный supabase api в одном месте — и не гадаю, где какой компонент потеряется.
Актуальность очевидна: AI-агенты переезжают из демо в процессы и требуют дисциплины. Если вы строите пайплайны в n8n или Make.com, если у вас есть требования по 152-ФЗ, если хотите контроль над данными пользователей и кодирование данных при хранении — supabase self hosted решает большую часть головной боли. Я выбираю подход, где хранение данных информации не размазано по трем сервисам, а собрано в систему хранения данных, которую можно поддерживать и масштабировать. И да, я люблю, когда метрики честные, а права доступа проверяются политиками, а не комментариями в чате.
AI-агент без памяти — это чат. AI-агент с продуманным хранением данных — это инструмент.
Архитектура без сюрпризов: что храню и где это живет
Я начинаю с базовой картины, чтобы не тонуть в деталях. Слои простые: интерфейс агента, оркестратор действий, база и очереди. В качестве базы — PostgreSQL внутри Supabase, как ядро системы хранения данных. Таблицы для пользователей и auth не придумываю, беру supabase auth и RLS. Для сообщений и сессий делаю свои таблицы, для файлов — встроенное хранилище. Реальное время использую там, где нужна мгновенная синхронизация: обновление статуса задач, сигнал агенту о новом событии. Edge Functions отдаю под серверную логику рядом с данными: валидация, дергание внешних API, простые вебхуки без лишних прыжков.
Если коротко про сущности: users из auth, profiles с доп. полями, agents с настройками и лимитами, sessions для контекста, messages как поток сообщений, tools_calls для вызовов инструментов агента, events для логов, tasks для операционных задач пользователя. Для векторного поиска включаю pgvector — embeddings в отдельной таблице, связанной с messages или документами. Хранилище файлов беру нативное, чтобы не тянуть отдельный S3. Для хранения базы данных важно не только качество модели, но и дисциплина запросов: индексы по user_id, session_id, created_at, и четкие политики доступа.
Вопрос, который мне часто задают: почему не только векторная СУБД. Ответ приземленный. Пока агент живет в реальном продукте, ему нужны транзакции, связи, RLS и обычная обработка хранения данных: статусы, флаги, аналитика, внешние ключи. Векторный поиск отлично дополняет, но не заменяет систему хранения данных пользователей. Если объемы большой, добавляю внешний векторный сервис, но Supabase оставляю как источник правды. По пути появляются мелочи: ретенции, политики на удаление, storage buckets для вложений, лимиты на размер. Ничего романтичного, зато работает.
Самохостинг без боли: supabase docker и требования 152-ФЗ
Когда речь о данных российских пользователей, я включаю режим white-data-зоны и зашиваю локализацию. Вариантов два: облачный проект на supabase com для прототипа и supabase self hosting для продакшена, когда требуется хранение данных пользователей в РФ. Самый быстрый путь — supabase docker, который поднимает Postgres, Studio, Kong, storage и остальные сервисы. Дальше уже дело привычки: параметры БД, ключи, конфиги для инициализации расширений, ограничители на сетевой доступ. На выходе получается самодостаточная система хранения баз данных, которую можно развернуть на своем сервере или в отечественном облаке.
Пример docker compose для старта я держу под рукой. Да, упрощено, но хорошо передает идею минимального набора сервиса для dev и теста. В продакшене добавляю внешние тома, мониторинг, бэкапы и секреты из хранилища секретов.
version: "3.9"
services:
db:
image: supabase/postgres:15.1.0.43
environment:
POSTGRES_PASSWORD: supersecret
POSTGRES_DB: postgres
volumes:
- db-data:/var/lib/postgresql/data
kong:
image: supabase/kong:latest
depends_on: [db]
auth:
image: supabase/gotrue:latest
environment:
GOTRUE_JWT_SECRET: verysecret
GOTRUE_SITE_URL: http://localhost:3000
rest:
image: supabase/postgrest:latest
environment:
PGRST_DB_URI: postgres://postgres:supersecret@db:5432/postgres
realtime:
image: supabase/realtime:latest
storage:
image: supabase/storage-api:latest
volumes:
db-data:
Чтобы соответствовать 152-ФЗ я делаю три вещи. Первое — география: размещение инстанса в дата-центре в РФ и договор с провайдером на обработку персональных данных. Второе — политика ролей и разграничение доступа: supabase auth, RLS, отдельные ключи для сервисов, и строгий запрет отдавать service_role в клиент. Третье — бэкапы и журналирование с учетом класса систем: расписание, хранение данных в компьютерных системах по регламенту, документированная процедура восстановления. Кодирование данных при хранении можно организовать на уровне диска и отдельных колонок pgcrypto — не серебряная пуля, но снижает риски в случае компрометации диска.
Без плана бэкапов вы не храните данные, вы их временно держите.
Схема данных, RLS и supabase auth: безопасность как по нотам
Я проектирую схему с мыслью, что любая запись должна быть однозначно привязана к пользователю и агенту. Базовый минимальный набор: profiles, agents, sessions, messages, tasks, events, embeddings. В Supabase сразу включаю расширение pgvector и создаю индексы для быстрого поиска. Политики RLS держу максимально простыми: каждая таблица проверяет, что user_id из токена совпадает с owner_id записи. Это снижает количество сюрпризов на проде и делает систему хранения данных предсказуемой.
Ниже — пример SQL, который я использую как стартовую точку. Тут и таблицы, и индексы, и политики. Не идеал для всех, но рабочий каркас для большинства агентских сценариев.
-- включаем pgvector
create extension if not exists vector;
-- профили
create table public.profiles (
user_id uuid primary key references auth.users(id) on delete cascade,
full_name text,
created_at timestamp with time zone default now()
);
-- агенты
create table public.agents (
id uuid primary key default gen_random_uuid(),
user_id uuid not null references public.profiles(user_id) on delete cascade,
name text not null,
config jsonb not null default '{}'::jsonb,
created_at timestamptz default now()
);
create index on public.agents (user_id);
-- сессии
create table public.sessions (
id uuid primary key default gen_random_uuid(),
agent_id uuid not null references public.agents(id) on delete cascade,
user_id uuid not null references public.profiles(user_id) on delete cascade,
title text,
created_at timestamptz default now()
);
create index on public.sessions (user_id);
-- сообщения
create table public.messages (
id bigserial primary key,
session_id uuid not null references public.sessions(id) on delete cascade,
user_id uuid not null references public.profiles(user_id) on delete cascade,
role text check (role in ('user','assistant','system')),
content text not null,
created_at timestamptz default now()
);
create index on public.messages (session_id, created_at);
-- вектора
create table public.embeddings (
message_id bigint primary key references public.messages(id) on delete cascade,
embedding vector(1536)
);
create index on public.embeddings using ivfflat (embedding vector_cosine_ops);
-- задачи
create table public.tasks (
id uuid primary key default gen_random_uuid(),
user_id uuid not null references public.profiles(user_id) on delete cascade,
description text,
status text default 'pending',
created_at timestamptz default now()
);
-- включаем RLS и политики
alter table public.profiles enable row level security;
alter table public.agents enable row level security;
alter table public.sessions enable row level security;
alter table public.messages enable row level security;
alter table public.embeddings enable row level security;
alter table public.tasks enable row level security;
create policy "user_is_owner_profiles" on public.profiles
using (auth.uid() = user_id);
create policy "user_is_owner_agents" on public.agents
using (auth.uid() = user_id);
create policy "user_is_owner_sessions" on public.sessions
using (auth.uid() = user_id);
create policy "user_is_owner_messages" on public.messages
using (auth.uid() = user_id);
create policy "user_is_owner_embeddings" on public.embeddings
using (exists (
select 1 from public.messages m
where m.id = embeddings.message_id and m.user_id = auth.uid()
));
create policy "user_is_owner_tasks" on public.tasks
using (auth.uid() = user_id);
Аутентификацию беру supabase auth, потому что стандартные провайдеры, магия JWT и простые правила. Если нужен сервисный доступ, использую отдельный ключ, в n8n он хранится в креденшелах, а все клиентские операции идут через пользовательский токен. Для внешних интеграций — supabase api на базе PostgREST: можно дергать REST эндпоинты для таблиц, фильтровать и пагинировать без написания лишнего кода. Для примера запрос на выборку задач по статусу выглядит так:
GET /rest/v1/tasks?status=eq.in_progress&select=id,description,created_at
apikey: <public-anon-key>
Authorization: Bearer <user-jwt>
Интеграции с n8n и Make: события, очереди, логи
Когда в игру вступает оркестровка, главное — предсказуемость. В n8n я использую два пути: нативный Postgres node для вызовов SQL и HTTP Request к supabase api. Для Make.com аналогично — HTTP и Webhooks. Логи пишу в таблицу events, где храню тип события, источник, payload и ссылку на сущность. Это помогает и для отладки, и для метрик. Сама обработка хранения данных получается линейной: пришло событие — записали — посчитали — обновили статус — отправили уведомление в реальном времени.
Типичный сценарий в n8n для агента у меня выглядит так: вебхук принимает запрос, извлекаем токен, проверяем права через supabase auth, пишем сообщение, считаем эмбеддинг, сохраняем в embeddings, дергаем модель, записываем ответ, публикуем через realtime канал обновление интерфейсу. Если интеграция с внешними системами, добавляю очереди и ретраи с backoff. Да, иногда сценарий заводится с третьей попытки — н8n умеет удивлять — но после пары вечеров все стабилизируется.
Я стараюсь не плодить мутаторов состояния в десяти местах. Если агент меняет статус задачи, он делает это через один маршрут, который и пишет в tasks, и публикует событие. Тогда интерфейс и другие сценарии получают одну правду. В Make.com мне нравится визуальная ясность, но критические транзакции я всё равно отдаю на сторону БД, потому что нет ничего надежнее коммита в таблице и RLS, который не даст случайно обновить чужую строку.
Сначала событие в базе, потом уведомление. Не наоборот. Иначе однажды вы потеряете чей-то важный статус при сбое сети.
Для интеграции с MCP инструментами я добавляю простой HTTP слой поверх supabase api. supabase mcp в моей практике — это соглашение: агент через MCP вызывает модуль, модуль читает и пишет в таблицы через сервисный ключ и четко ограниченные эндпоинты. Тут дисциплина важнее модных слов — легко утечь с правами service_role. Всегда храню такой ключ только на сервере, никогда в клиенте. И да, проверку входящих параметров делаю дважды, не стыжусь.
Реальное время, Edge и supabase api: как ускорить реакцию
Реальное время в Supabase — это легкий способ отправить фронту сигнал, что что-то изменилось. Я использую каналы по session_id или user_id, чтобы минимизировать шум. Когда агент записал новое сообщение в messages, подписчик получает событие и обновляет интерфейс. Это лучше, чем опрашивать базу каждые пять секунд и грузить систему хранения данных без пользы. Edge Functions беру там, где нужна быстрая реакция рядом с данными: вебхуки из внешних систем, предварительная валидация перед записью, подготовка агрегатов.
supabase api выручает, когда вам нужен быстрый REST поверх таблиц. Фильтры, сортировка, ограничения — всё есть из коробки. Пример запроса в n8n через HTTP Request я держу стандартным: заголовки apikey и Authorization, параметры в URL, лимиты и пагинация через range. Для долгих операций делаю отложенные задачи: записать событие, подобрать контекст через embeddings, сгенерировать ответ моделью, обновить статус. В кодовой базе я стараюсь без лишней магии — комментарии и названия таблиц говорят сами за себя.
Небольшой штрих: если вы строите свой pipeline по правилам вроде руководство по использованию api open ai, то Supabase отлично сочетается с такой дисциплиной. Сначала логируем вход, затем создаем контекст, затем выполняем вызов, затем фиксируем выход. Если вам ближе генеративные задачи с аудио и музыкой, сохраните где-нибудь ссылку на полное руководство по тегам для suno ai — пригодится для унификации метаданных в таблицах. Я не смешиваю разные домены в одном потоке, но хранение базы данных делает эти миры дружелюбными к аналитике.
Эксплуатация: метрики, бэкапы, оптимизация и экономия времени
В эксплуатации меня интересуют три вещи: скорость отклика, надежность коммита и предсказуемая стоимость поддержки. Метрики держу на уровне БД и приложения: время ответа на запись и чтение, количество сообщений в секунду, количество активных сессий, доля ошибок по категориям. Бэкапы по расписанию, проверка восстановления — обязательная рутина раз в квартал. Для хранения данных информации прописываю сроки жизни: события 90 дней, сырые логи 30, агрегаты — бессрочно. Это экономит диск и поддерживает гигиену. Кодирование данных при хранении колонок с чувствительными данными через pgcrypto плюс шифрование диска — достаточно, чтобы спать спокойнее.
Оптимизации стандартные: индексы по часто используемым фильтрам, партиционирование messages по месяцам при больших объемах, сжатие в хранилище файлов, аккуратные политики RLS без сложных подзапросов. На стороне n8n и Make.com — ретраи с джиттером, ограничители для внешних API, очереди с приоритетами. Если судорожно масштабироваться — дороже, чем изначально держать систему хранения данных в порядке. Сколько времени это экономит? Много, я перестала считать, как только количество инцидентов упало вдвое после того, как мы запретили записи без транзакций.
Хорошая система — та, которую легко чинить. Плохая — та, которую страшно трогать.
Из практических наблюдений. supabase co и supabase com как домены в документации встречаются в примерах, но в проде я фиксирую свой домен и не полагаюсь на редиректы. Версионность схемы веду миграциями, а не SQL по памяти. Для realtime лучше сразу ограничить количество каналов, иначе чат с тысячами тем превратится в печь. Для Edge Functions следите за лимитами времени и памяти, иначе внезапные тайм-ауты начнут съедать нервы. И еще маленькая, но важная мелочь: вынесите ключи в секреты окружения, не храните их в репозитории, это 5 минут сегодня и минус одна бессонная ночь завтра.
Практические советы: берите и делайте
Ниже список шагов, которые помогут запустить хранение данных для агента без суеты. Да, звучит базово, но я сама регулярно ловлю себя на том, что перескакиваю через какие-то пункты, потом возвращаюсь и чиню. Лучше сразу ровно пройтись.
- Определите схему. Начните с users, agents, sessions, messages, tasks, events, embeddings. Пропишите связи и индексы. Включите pgvector.
- Включите RLS и напишите простые политики. Стратегия одна — каждый видит только свое. Проверьте запросами от разных пользователей.
- Выберите способ размещения. Для прототипа можно облако, для продакшена с российскими пользователями — supabase self hosted через supabase docker в РФ.
- Соберите интеграцию. В n8n используйте Postgres node для транзакций и HTTP для supabase api. В Make.com настройте Webhooks и REST вызовы.
- Продумайте эксплуатацию. Бэкапы, журналирование, ретенции, мониторинг. Заведите графики по ответам БД и ошибкам.
Несколько правил, которые я держу перед глазами. Правило 1: сначала запись в базу, потом нотификация. Правило 2: ни один сервисный ключ не попадает в клиент. Правило 3: каждый запрос идет не напрямую, а через контролируемый слой — Edge или подготовленные эндпоинты. Правило 4: раз в месяц прогоняем сценарий восстановления из бэкапа. Правило 5: тесты на RLS, чтобы случайно не открыть доступ чужим данным. Дисциплина скучна, зато хранение данных пользователей становится предсказуемым, а система хранения данных ведет себя взрослым образом.
Тихая развязка: на что ставлю в проектах
Я выбрала Supabase не потому, что модно, а потому что он экономит мне часы в неделе. Это полноценная система хранения данных с PostgreSQL в центре, где supabase auth закрывает аутентификацию, supabase api — быстрый REST к таблицам, realtime — сигналы для фронта, Edge — легкая серверная логика. В самохостинге через supabase docker я выполняю требования 152-ФЗ, оставляю данные в РФ и контролирую окружение. Если нужны вектора — включаю pgvector и живу спокойно. Если нужен рост — добавляю индексы, партиционирование и аккуратно масштабирую оркестровку.
На уровне процессов всё просто: хранение данных не должно быть квестом. Схема, RLS, логи, бэкапы, мониторинг — базовый чеклист. Интеграции с n8n и Make.com строятся вокруг одного принципа: сначала фиксируем, затем уведомляем. Там, где нужна скорость, приходят realtime и Edge. Там, где нужна гибкость, помогает supabase mcp как тонкий слой над API. Главное — не забывать, что это не магия, а ремесло: меньше хака, больше читаемого кода и проверенных маршрутов. Если в какой-то момент вам показалось, что стало слишком сложно — скорее всего, пора вынести часть логики в базу и убрать два лишних шага из своей цепочки.
Если хочется продолжить вместе
Если интересен спокойный разбор таких стеков, у меня есть пространство, где я без спешки показываю, как это собирается у меня: в моем телеграм-канале MAREN я разбираю сценарии n8n supabase, самохостинг и честные метрики. А на сайте MAREN можно посмотреть, чем я занимаюсь, какие продукты и форматы практики использую. Если хочется структурировать эти знания и собрать свой пилот, берите идеи, адаптируйте под свои процессы и не забывайте про белую зону данных.
Частые вопросы по этой теме
Можно ли обойтись без самохостинга и использовать облако
Для прототипов и внутренних экспериментов можно. Если у вас есть обязательства по локализации данных в РФ, смотрите в сторону supabase self hosting. Иногда делю среду: dev в облаке, prod в самохостинге.
Как правильно хранить сервисные ключи и защищать доступ
Храните service_role только на сервере, в менеджере секретов. В клиент отправляйте только anon key. Проверяйте права через RLS и не доверяйте клиенту даже если очень хочется ускориться.
Нужен ли отдельный векторный движок
Если объемы невелики, pgvector внутри Supabase закрывает задачи похожести. При росте и миллионах эмбеддингов можно вынести векторный индекс во внешний сервис, оставив Supabase источником правды.
Как связать n8n и supabase без лишней магии
Для критичных операций используйте Postgres node и транзакции. Для простых CRUD подойдут HTTP вызовы к supabase api. Логи пишите в таблицу events и следите за ретраями.
Что делать с файлами и мультимедиа
Используйте встроенное хранилище файлов и политики доступа. Для больших объектов включайте CDN и ограничение размера. Метаданные держите в таблицах, чтобы не плодить поисковые дырки.
Реальное время нагружает базу, стоит ли его включать везде
Нет, включайте точечно. Подписки по session_id или user_id эффективнее, чем одна большая тема для всех. Остальное лучше обслуживать периодическими задачами или событиями.
Где почитать про настройки моделей и API
Технические тонкости удобно собирать в одном месте, например внутреннее руководство по использованию api open ai. А для генеративных аудио подойдет полное руководство по тегам для suno ai — это помогает нормализовать данные в таблицах.
Метки: ai-agents, rag, контент-план