Зачем LangGraph-агенту Postgres вместо in-memory
LangGraph-агент, который бронирует встречи, без постоянного хранилища теряет все данные при перезапуске. Подтвержденные записи, история диалога, состояние графа исчезают. Приложение Streamlit после обновления страницы начинает с чистого листа. Для демо это допустимо, для реального сценария бронирования нет.
Postgres решает эту проблему. Агент сохраняет встречи в долговечной базе, читает уже созданные записи и учитывает их при новых запросах. После перезапуска приложение подключается к той же базе и продолжает работу с прежними данными. Это и есть персистентность.
Что теряется в in-memory-режиме
In-memory хранилище живет только в текущем процессе. Закрыли терминал, перезапустили Streamlit, обновили страницу - все пропало. Нет истории, нет записей, нет контекста. Несколько пользователей не могут работать с общими данными, каждый видит свою копию. Для агента бронирования это критично: два человека могут выбрать один и тот же слот, потому что агент не видит чужие записи.
Что дает LangGraph persistence на базе Postgres
Postgres хранит состояние графа, историю диалога и бизнес-данные бронирования. Агент может восстановить контекст после перезапуска и продолжить сессию. Он видит ранее созданные записи и не предлагает занятое время. Важно разделять эти три слоя: состояние графа для checkpointing, историю для восстановления диалога и таблицы бронирования для бизнес-логики. Они могут жить в одной базе, но в разных таблицах.
Как меняется сценарий бронирования после подключения базы
С базой агент работает иначе. Пользователь просит встречу, агент читает существующие бронирования за нужный период, проверяет доступность слота, при конфликте предлагает альтернативу, после подтверждения сохраняет запись. База становится источником фактического состояния, а не просто журналом сообщений.
Чтение уже созданных записей перед новым бронированием
Перед созданием новой встречи агент должен запросить актуальные записи. Сравнить дату, время и другие параметры. Если слот занят, агент сообщает об этом и предлагает другое время. Такой подход предотвращает дублирование и конфликты.
Проверка конфликтующих слотов
Проверка доступности слота - ключевой шаг. Агент ищет записи с тем же временем. Нашел - отказывает и предлагает варианты. Не нашел - создает новую запись. Для конкурентных запросов одной проверки перед записью может быть недостаточно. Нужны ограничения на уровне базы или транзакционная логика. В демо-сценарии последовательная проверка работает, в production стоит продумать защиту от гонок.
Сохранение подтвержденной встречи
После подтверждения агент сохраняет встречу в базу. Какие поля нужны: идентификатор встречи, время, участник или контакт, статус, служебные поля. Точная схема зависит от проекта. Главное - запись должна быть постоянной и доступной для будущих проверок.
Как запустить Postgres локально в Docker
Для разработки и первичной проверки удобно поднять Postgres в Docker. Контейнер изолирует базу, не трогает систему и легко удаляется. Главное - использовать постоянный volume, чтобы данные не исчезли вместе с контейнером.
Какие параметры нужны локальному Postgres
Для подключения нужны хост, порт, имя базы, пользователь и пароль. При запуске контейнера задайте их через переменные окружения. Например, POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB. Volume сохранит данные между перезапусками контейнера.
Создание базы и ограничение CREATE DATABASE IF NOT EXISTS
PostgreSQL не поддерживает прямую конструкцию CREATE DATABASE IF NOT EXISTS. Если нужно создать базу только при отсутствии, используйте проверку через pg_database и \gexec:
SELECT 'CREATE DATABASE exp_db' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'exp_db')\gexecЭта команда выполнит CREATE DATABASE только если базы exp_db нет. Но это относится к созданию базы, а не к подключению приложения к уже существующему серверу.
Подключение агента через DATABASE_URL
Строка подключения DATABASE_URL передает приложению параметры базы. Формат обычно такой: postgresql://user:password@host:port/dbname. Для локального контейнера host может быть localhost, если приложение запущено на хостовой системе. Если приложение тоже в Docker, host будет именем контейнера или сервиса. Уточняйте под свою архитектуру.
Проверка записи после первого бронирования
Контрольный сценарий: создайте встречу через агента, остановите или перезапустите Streamlit, снова запросите тот же слот. Если агент видит занятость и отказывает, значит, данные сохранились в Postgres, а не в памяти процесса.
Как подключить LangGraph к облачному Postgres через .env
Облачная база подходит, когда приложение должно быть доступно извне или работать с общей базой. Настройка похожа на локальную, но добавляются сетевые требования и безопасность.
Что указать в DATABASE_URL для удаленной базы
В строке подключения укажите endpoint или host, порт, имя базы, пользователя, пароль и дополнительные параметры, если их требует провайдер. Например, SSL-режим. Конкретные значения зависят от облачного сервиса.
Как использовать .env в Streamlit-приложении
Храните DATABASE_URL в файле .env, который не попадает в публичный репозиторий. Приложение загружает переменную из окружения или .env при старте. После изменения .env перезапустите приложение. Точный способ загрузки зависит от используемого инструмента конфигурации.
Что проверить до запуска агента
Проверьте сетевую доступность базы, разрешенные IP или правила доступа, корректность учетных данных, название базы, порт и требования к защищенному соединению. Разделяйте ошибки сети, аутентификации и схемы данных.
Как проверить persistence в Streamlit после перезапуска
После настройки базы проверьте, что агент действительно использует Postgres. Создайте встречу, перезапустите Streamlit, снова запросите тот же слот. Агент должен увидеть занятость.
Контрольный сценарий для занятого слота
Первое обращение создает встречу. Второе обращение с теми же параметрами должно прочитать запись и обработать конфликт: отказать или предложить альтернативу. Если агент снова предлагает тот же слот, persistence не работает.
Что должно сохраниться после перезапуска
Запись остается в базе. Приложение может подключиться к ней снова. Агент учитывает ранее сохраненные данные. Не обещайте автоматическое восстановление любого состояния, если это не предусмотрено реализацией checkpointing.
Как отличить проблему базы от проблемы Streamlit
Проверьте доступность Postgres, наличие таблиц и записей, корректность DATABASE_URL, загрузку конфигурации при старте и логику чтения данных агентом. Если база доступна и записи есть, но агент их не видит, проблема в коде чтения.
Как визуально проверить записи Postgres через TablePro
GUI-клиент TablePro позволяет увидеть данные без SQL. Подключитесь к базе, откройте таблицы и найдите созданную запись. Это быстрый способ убедиться, что агент действительно пишет в Postgres.
Подключение к локальной базе
Введите параметры локального Postgres: host, port, пользователь, пароль, имя базы. После подключения откройте нужные таблицы и проверьте наличие новых записей после работы агента.
Подключение к облачной базе
Подключение к облачной базе выполняется так же, если база доступна по сети. Укажите endpoint, порт и учетные данные. Сетевые правила и SSL-параметры задаются облачным провайдером.
Какие данные искать в таблицах
Проверьте наличие записи встречи, ее времени, статуса и идентификаторов. Убедитесь, что для занятого слота нет второй записи, если сценарий должен предотвращать дублирование.
Типичные ошибки при подключении LangGraph-агента к Postgres
Разберем частые проблемы и способы их решения.
Приложение не подключается к Postgres
Проверьте формат DATABASE_URL, host и port, доступность сервера, учетные данные и правила сетевого доступа. Начните диагностику с минимального подключения к базе, затем проверяйте LangGraph и Streamlit.
Агент подключается, но не видит старые записи
Убедитесь, что приложение подключено к той же базе и схеме, что записи действительно созданы, а код читает нужные таблицы или checkpoint-хранилище. Отделите сохранение истории графа от чтения прикладных записей бронирования.
Дублирование встреч при одновременных запросах
Последовательная проверка слота в демо не защищает от конкурентных запросов. Нужна продуманная транзакционная логика, ограничения и проверка модели данных. Persistence не решает автоматически вопросы конкурентных бронирований.
Секреты и облачное подключение
Не храните реальные пароли в исходном коде и публичном репозитории. Используйте переменные окружения или секрет-хранилище, ограничивайте права пользователя базы и учитывайте требования облачного провайдера.
Локальный Docker или облачный Postgres: что выбрать
Выбор зависит от этапа разработки.
Когда достаточно локального Postgres
Локальный Docker-сценарий подходит для проверки схемы, подключения, записи встречи и поведения после перезапуска. Он не зависит от внешней сети и быстро настраивается.
Когда нужна облачная база
Облачная база нужна, когда Streamlit-приложение или другие пользователи должны обращаться к общей базе через сеть. Отдельно проверьте безопасность, доступность и настройки подключения.
Итог: минимальная схема устойчивого LangGraph-агента
Рабочая архитектура: LangGraph-агент получает состояние и данные, Postgres хранит их между запусками, DATABASE_URL передает конфигурацию, .env отделяет настройки от кода, Streamlit использует backend после перезапуска, а проверка через SQL или TablePro подтверждает фактическую запись.
Чек-лист готовности:
- База доступна
- Схема создана
- Переменная загружена
- Встреча сохраняется
- Занятый слот распознается
- Повторный запуск не стирает данные