Track
Большинство агентов LLM каждый раз стартуют с нуля. Они забывают имя пользователя, последний разговор и файл, над которым он работал. Любую информацию о пользователе приходится восстанавливать шаг за шагом.
В этом руководстве мы добавим агенту постоянную память, чтобы следующий запуск продолжал работу с того места, где закончился предыдущий. В качестве слоя памяти используется Supermemory — размещаемый API, который хранит факты по пользователям и возвращает их одним вызовом. Вы создадите персонального тренера по упражнениям на Python. Агент фиксирует тренировки, предлагает следующую сессию и запоминает предпочтения и недавние результаты между отдельными запусками скрипта.
Стек минимален. Supermemory отвечает за память. OpenAI Agents SDK запускает цикл агента. Тренер состоит из двух файлов Python и файла pyproject.toml.
Потребуются Python 3.10 или новее, аккаунт OpenAI, аккаунт Supermemory и базовые навыки работы в командной строке.
Что такое Supermemory?
Supermemory лучше всего описать как API памяти для AI-агентов. Когда вы передаёте Supermemory строки о вашем пользователе, позже она возвращает сжатое представление о том, кто этот пользователь и чем он недавно занимался. Встраивание, индексация и поиск выполняются внутри Supermemory, поэтому код агента остаётся компактным.
Бенчмарк LongMemEval проверяет, насколько хорошо система памяти отвечает на вопросы по длинной истории диалога. Supermemory вспоминает 81,6% верных фактов. Zep, следующая по качеству система, набирает 71,2% — разрыв в 10 пунктов, что эквивалентно примерно одному дополнительному правильному ответу на каждые 10 вопросов пользователя. В репозитории с открытым исходным кодом более 22 тыс. звёзд на GitHub — ещё один признак реального использования.
Память vs RAG
Большинство читателей, которым нужен инструмент агентской памяти, уже использовали RAG. Яснее всего рассматривать Supermemory рядом с ним. RAG и память решают разные задачи и часто сосуществуют в одном агенте.
Система RAG указывает на корпус документов, который разработчик готовит один раз. Инструкции по продукту, статьи поддержки, внутренние документы. Корпус загружается при деплое, запрашивается во время выполнения и редко меняется. Агент использует его, чтобы отвечать на вопросы, ответы на которые известны самому продукту.
Система памяти нацелена на пользователя. Supermemory записывает факты, специфичные для пользователя, по мере общения агента, и хранилище растёт с каждым разговором. Агент использует его для ответов на вопросы, на которые может ответить только пользователь: предпочтения, история, недавняя активность.

В реальном продукте они работают бок о бок. RAG по базе знаний компании отвечает на «какова наша политика возврата?». Supermemory — на вопрос пользователя «Какой у меня был жим лёжа на прошлой неделе?». Один агент, два хранилища данных, две задачи.
Профили пользователей: статические и динамические факты
Главная идея Supermemory — профиль пользователя. Каждый лог распределяется по двум корзинам: статические факты, которые редко меняются, и динамические факты о текущей активности. Повторяющиеся паттерны повышаются в статусе до статических. Недавняя активность остаётся динамической.
При чтении профиля одним вызовом возвращаются обе корзины плюс соответствующие фрагменты памяти.
Разделение важно, потому что статические и динамические факты отвечают на разные вопросы об одном и том же пользователе:
|
Статические факты |
Динамические факты |
|
Тренируется дома с гантелями и турником |
Текущий фокус: сила верхней части тела |
|
Травма левого колена, избегает глубоких приседаний |
Последний жим: 4 подхода по 5 повторений с весом 185 фунтов |
|
Хочет прибавить 20 фунтов к жиму к концу года |
На этой неделе — подтягивания по методу «смазывания канавки» |
|
Тренируется только по вечерам, никогда по утрам |
Вчера пробежал 5 км за 28 минут |
Прочитайте первую строку. Статическая сторона описывает, как тренируется пользователь: дома и с имеющимся оборудованием. Это не меняется из недели в неделю. Динамическая сторона говорит, над чем он работает прямо сейчас: верхняя часть тела, текущий цикл.
Рекомендатору тренировок нужны оба вида. Статическая часть исключает упражнения, доступные только в зале, динамическая — выбирает сессию на сегодня.
За профилем Supermemory выполняет четыре задачи, которые иначе вы бы реализовали сами: хранит сырые воспоминания, встраивает каждый фрагмент, выполняет поиск по сходству при чтении и извлекает факты профиля из записанного контента. Ничего из этого не появляется в вашем коде.

Каждое воспоминание помечается строковым тегом по выбору разработчика. Каждый запрос на чтение передаёт этот же тег, ограничивая выдачу. В тренере тег жёстко задан, потому что одного пользователя достаточно, чтобы показать работу профиля. В реальных приложениях тег вычисляется из аутентифицированного пользователя, например из его JWT.
Настройка окружения Supermemory
Тренеру нужны два API-ключа (Supermemory и OpenAI) и проект на Python с тремя зависимостями. Короткий скрипт туда-обратно подтвердит, что оба ключа работают, ещё до того, как код агента к ним обратится.
Получение API-ключей
Ключ API Supermemory находится на console.supermemory.ai, НЕ app.supermemory.ai. Поддомен app — это потребительский продукт памяти (для сохранения заметок, работы с вашим пространством). В нём нет страницы с API-ключами. Пропустите его и перейдите сразу в консоль.
На console.supermemory.ai:
-
Войдите в аккаунт.
-
Нажмите API Keys в боковой панели.
-
Нажмите Create API Key.
-
Дайте имя (в демо тренера используется
datacamp-tutorial). -
Скопируйте полученный ключ. Он начинается с
sm_.

Вам также нужен ключ OpenAI для LLM-вызовов агента. Если у вас его ещё нет, получите его на platform.openai.com/api-keys.
Создайте файл .env в корне проекта с обоими ключами. Не добавляйте его в репозиторий.
SUPERMEMORY_API_KEY=sm_your_key_here
OPENAI_API_KEY=sk-your_key_here
Бесплатный тариф Supermemory покрывает это руководство без ввода платёжной информации. Точные лимиты указаны на странице с тарифами.
Установка зависимостей
В учебнике используется uv для настройки проекта и запуска. Если у вас нет uv, установите его однострочной командой с astral.sh/uv.
Инициализируйте проект:
uv init supermemory-trainer
cd supermemory-trainer
Удалите автоматически сгенерированный README.md, который добавляет uv init. Автосгенерированный hello.py будет перезаписан на следующем шаге, так что пока оставьте его.
Добавьте три зависимости:
-
supermemory==3.37.0— клиент памяти, закреплённый на версии, проверенной для этого руководства. -
openai-agents — это OpenAI Agents SDK. Имя пакета через дефис, путь импорта —
agents. -
python-dotenvчитает файл.env, который вы только что создали.
uv add supermemory==3.37.0 openai-agents python-dotenv
Получившийся pyproject.toml:
[project]
name = "supermemory-trainer"
version = "0.1.0"
description = "Personal exercise trainer agent built with Supermemory and the OpenAI Agents SDK."
requires-python = ">=3.10"
dependencies = [
"openai-agents>=0.10.2",
"python-dotenv>=1.2.1",
"supermemory==3.37.0",
]
Проверка настройки
Прежде чем писать код агента, посмотрите, как Supermemory отрабатывает на одном предложении. Скрипт ниже отправляет один факт в Supermemory, ждёт выполнения конвейера, затем читает профиль. Если он отрабатывает без ошибок, ключи верные и SDK доступен. Вывод также даёт первое представление о том, что Supermemory делает с сырым текстом.
Откройте hello.py в корне проекта и замените автосгенерированное содержимое на импорты и вызов записи:
import time
from dotenv import load_dotenv
from supermemory import Supermemory
load_dotenv()
client = Supermemory()
USER_ID = "demo_warmup"
response = client.add(
content="The user is learning Supermemory by building a personal trainer agent.",
container_tag=USER_ID,
)
print(f"client.add() -> id={response.id} status={response.status}")
load_dotenv() читает ключ API из .env в окружение до создания Supermemory(). Клиент автоматически подхватывает SUPERMEMORY_API_KEY. Значение container_tag="demo_warmup" ограничивает этот факт одноразовым пользователем.
Теперь добавьте ожидание и чтение в конец того же файла:
print("Waiting 20 seconds for processing...")
time.sleep(20)
prof = client.profile(container_tag=USER_ID, q="learning")
print(f"profile.static ({len(prof.profile.static)}): {prof.profile.static}")
print(f"profile.dynamic ({len(prof.profile.dynamic)}): {prof.profile.dynamic}")
print(f"search_results.results ({len(prof.search_results.results)}):")
for r in prof.search_results.results[:3]:
print(f" - {r['memory']} (similarity={r['similarity']:.3f})")
Пауза в 20 секунд даёт конвейеру встраивания и извлечения Supermemory время обработать новую запись. Без этого чтение ничего не вернёт, и может показаться, что скрипт сломан, хотя это не так.
Запустите файл:
uv run python hello.py
Ожидаемый вывод:
client.add() -> id=zNLsJBrY1PZupAeZ3Qn6EL status=queued
Waiting 20 seconds for processing...
profile.static (0): []
profile.dynamic (1): ['Building a personal trainer agent to learn Supermemory.']
search_results.results (1):
- Building a personal trainer agent to learn Supermemory. (similarity=0.650)
В этом выводе важны три детали. client.add() возвращает управление сразу со статусом status="queued", поскольку Supermemory обрабатывает документы асинхронно. Ожидание в 20 секунд покрывает работу конвейера встраивания и извлечения. К моменту чтения сырое предложение уже стало одним фрагментом памяти, доступным для поиска.
Интересная строка — profile.dynamic. На входе было предложение «The user is learning Supermemory by building a personal trainer agent.» На выходе — динамический факт 'Building a personal trainer agent to learn Supermemory.'. Supermemory переписала фразу от третьего лица в факт от первого лица о пользователе. Так работает извлечение профиля.
profile.static — пустой список. Статические факты консолидируются медленно, после накопления нескольких связанных логов, поэтому единичная пробная запись их не даёт. Инструмент предложений в тренере учитывает это и рассматривает static как бонус, а не как гарантию.
Создание агента Supermemory: персональный тренер по упражнениям на Python
Тренер оборачивает client.add() и client.profile() в два инструмента агента, чтобы чтение и запись происходили автоматически по мере общения с пользователем. История тренировок хорошо ложится на память. Оборудование, травмы и недавние результаты не живут в обучающих данных LLM и накапливаются сессия за сессией.

Структура проекта и агент
Тренер достаточно мал, чтобы весь проект уместился в два файла Python плюс уже имеющийся pyproject.toml:
supermemory-trainer/
├── .env # your real keys (gitignored)
├── .env.example # placeholders, committed
├── .gitignore
├── .python-version
├── main.py # agent definition, system prompt, REPL loop
├── pyproject.toml
└── tools.py # log_workout and suggest_next_session
tools.py содержит два инструмента с поддержкой памяти, которые вы напишете далее. log_workout записывает тренировку в Supermemory через client.add(). suggest_next_session читает профиль пользователя через client.profile(). main.py импортирует оба и подключает к агенту.
Большая часть main.py — это шаблонный код OpenAI Agents SDK. Одно предложение в системном сообщении делает работу Supermemory: каждый факт о пользователе должен возвращаться через вызовы инструментов. Агенту сообщается, что собственной памяти у него нет. Это единственное правило и делает тренер поддерживаемым памятью.
Откройте main.py и начните с импортов и системного промпта:
import asyncio
from agents import Agent, Runner, SQLiteSession
from tools import log_workout, suggest_next_session
SYSTEM_PROMPT = """You are a personal exercise trainer who logs the user's
workouts and recommends what to do next.
You have no memory of the user's history on your own. Every fact about the
user lives in Supermemory and reaches you only through tool calls.
Two rules, no exceptions:
1. Whenever the user reports completing a workout, call log_workout immediately, before responding. Extract the exercise, sets, reps, weight, and any notes from what they said. If a value is missing, ask one short follow-up question instead of guessing. After logging, confirm in one short sentence and stop. Do NOT recommend the next session unless the user asks for one.
2. When the user explicitly asks what to do next (or asks for a recommendation, suggestion, or plan), call suggest_next_session first. Never recommend from your own training data. The tool returns the user's
recent activity, stable preferences, and matching past sessions. Reference those facts directly in your reply.
Keep replies concise (2-4 sentences). Be specific: name the exercise, sets, reps, and weight. Honor any injuries or equipment constraints the tool surfaces.
"""
Оба правила в системном сообщении направляют модель через Supermemory.
Правило 1 принуждает к записи через log_workout всякий раз, когда пользователь сообщает о тренировке, так что каждая тренировка попадает в хранилище памяти. Правило 2 принуждает к чтению через suggest_next_session перед любой рекомендацией, чтобы каждая рекомендация опиралась на знания Supermemory.
Без этих правил агент будет отвечать из своих обучающих данных, что сводит на нет смысл слоя памяти.
Теперь определите агента и чат-цикл в том же файле:
def build_agent() -> Agent:
return Agent(
name="Trainer",
instructions=SYSTEM_PROMPT,
tools=[log_workout, suggest_next_session],
model="gpt-5",
)
async def chat() -> None:
agent = build_agent()
session = SQLiteSession(session_id="trainer-cli")
print("Trainer ready. Type a message, or 'exit' to quit.\n")
while True:
try:
message = input("You: ").strip()
except (EOFError, KeyboardInterrupt):
print()
break
if not message:
continue
if message.lower() in {"exit", "quit"}:
break
result = await Runner.run(agent, message, session=session)
print(f"\nTrainer: {result.final_output}\n")
if __name__ == "__main__":
asyncio.run(chat())
В этом блоке стоит отметить две строки. tools=[log_workout, suggest_next_session] регистрирует два инструмента с поддержкой памяти. Декоратор @function_tool на каждом из них (в tools.py) сообщает SDK, что их можно вызывать. Без декоратора у агента не будет инструментов во время выполнения, даже если конструктор вызван успешно.
SQLiteSession(session_id="trainer-cli") хранит краткосрочную историю ходов внутри запущенного процесса Python. Supermemory хранит долгосрочные факты пользователя между процессами. Завершение процесса Python удаляет сессию SQLite, но данные Supermemory сохраняются.
Важно: Запускайте main.py как скрипт, а не в ячейке Jupyter, поскольку цикл событий Jupyter конфликтует с asyncio.run(). Синхронный клиент Supermemory() работает внутри асинхронных функций-инструментов, потому что Agents SDK запускает инструменты в пуле потоков. Подробнее о самом SDK см. в руководстве по OpenAI Agents SDK.
Написание инструмента для логирования тренировок
log_workout — это сторона записи памяти агента. Функция принимает структурированные аргументы от агента: название упражнения, подходы, повторения, вес и необязательные заметки. Она превращает их в одно короткое английское предложение и передаёт его в Supermemory через client.add(). Конвейер встраивания и извлечения работает внутри Supermemory и не требует ничего от тренера.
Откройте tools.py и начните с импортов и одного общего клиента:
from agents import function_tool
from dotenv import load_dotenv
from supermemory import Supermemory
load_dotenv()
USER_ID = "demo_user"
client = Supermemory()
load_dotenv() выполняется при импорте, чтобы SUPERMEMORY_API_KEY попал в окружение до создания Supermemory(). Если создать клиента до загрузки окружения, он будет неаутентифицирован. Первый вызов тогда вернёт сбивающий с толку 401. Обе функции-инструмента в этом файле используют одного клиента и одну константу USER_ID.
Добавьте инструмент логирования ниже клиента:
@function_tool
def log_workout(
exercise: str,
sets: int,
reps: int,
weight: float,
notes: str = "",
) -> str:
"""Log a completed workout to the user's memory.
Args:
exercise: Name of the exercise.
sets: Number of sets performed.
reps: Number of reps per set.
weight: Weight in pounds. Pass 0 for bodyweight or cardio.
notes: Optional notes about the session.
"""
print(f"[log_workout] {exercise=} {sets=} {reps=} {weight=} {notes=}")
content = f"Performed {exercise}: {sets} sets of {reps} reps at {weight} lbs."
if notes:
content += f" Notes: {notes}"
response = client.add(content=content, container_tag=USER_ID)
print(f"[log_workout] -> id={response.id} status={response.status}")
return f"Logged {exercise} ({sets}x{reps} @ {weight} lb)."
Docstring декоратора @function_tool — это то, что видит LLM, решая, вызывать ли инструмент. Блок Args: описывает параметры. Оба — часть контракта агента с функцией.
Инструмент отправляет в client.add() простое предложение, а не JSON. Извлекатель профиля Supermemory читает естественный язык и выводит факты из него. Технически JSON тоже работает, но качество извлечения падает, потому что у модели нет нарратива для суммирования. «Performed bench press: 4 sets of 5 reps at 185.0 lbs» даёт извлекателю чистое предложение для работы.
Два вызова print() пишут в терминал каждый вызов инструмента: сначала распарсенные аргументы, затем ответ.
[log_workout] exercise='bench press' sets=4 reps=5 weight=185.0 notes=''
[log_workout] -> id=xY7AK3qLzBPx5Vd2HnRf1M status=queued
Значение status="queued" совпадает с тем, что вернул пробный скрипт ранее. Сырой лог сохранён, но client.profile() не вернёт его в результатах поиска, пока конвейер не завершится. Позже вы добавите шаг проверки, который подождёт завершения.
Написание инструмента предложений тренировок
suggest_next_session — это сторона чтения, где окупается разделение на статическое и динамическое. Один вызов client.profile(container_tag=USER_ID, q=focus) возвращает три представления пользователя за один проход.
Стабильные предпочтения приходят в profile.static, текущая активность — в profile.dynamic, а наиболее близкие прошлые воспоминания — в search_results.results. Задача инструмента — свернуть эти три представления в один блок контекста, который агент сможет цитировать.
После нескольких тренировок инструмент выдаёт примерно такой вывод:
Recent activity:
- Trains at home instead of a gym
- Performed deadlift: 3 sets of 5 reps at 225.0 lbs
- Performed 5k run in 26 minutes
- Reports no knee pain during bench press
- Performed bench press: 4 sets of 5 reps at 185.0 lbs
Closest matching past entries:
- Trains at home instead of a gym
- Performed deadlift: 3 sets of 5 reps at 225.0 lbs
- Performed bench press: 4 sets of 5 reps at 185.0 lbs
- Performed 5k run in 26 minutes
- Reports no knee pain during bench press
Агент читает этот блок и пишет рекомендацию, опираясь на фактическую историю пользователя. Без профиля Supermemory вы бы строили тот же контекст сами: отдельный семантический поиск, собственное хранилище профиля и объединение результатов. Один вызов client.profile() заменяет все три.
Добавьте это в tools.py под log_workout:
@function_tool
def suggest_next_session(focus: str) -> str:
"""Fetch the user's training history and preferences for a given focus.
Returns a context string the agent can use to recommend the next session.
The agent is responsible for the actual recommendation. This tool only
surfaces what Supermemory knows about the user.
Args:
focus: What the user wants to train next (e.g. "upper body", "legs",
"cardio", "today"). Drives semantic search against past logs.
"""
print(f"[suggest_next_session] focus={focus!r}")
profile = client.profile(container_tag=USER_ID, q=focus)
static_facts = profile.profile.static
dynamic_facts = profile.profile.dynamic
matches = profile.search_results.results
print(
f"[suggest_next_session] static={len(static_facts)} "
f"dynamic={len(dynamic_facts)} matches={len(matches)}"
)
sections = []
if static_facts:
sections.append("Stable preferences and constraints:")
sections.extend(f"- {fact}" for fact in static_facts)
if dynamic_facts:
sections.append("Recent activity:")
sections.extend(f"- {fact}" for fact in dynamic_facts)
if matches:
sections.append("Closest matching past entries:")
for r in matches[:5]:
sections.append(f"- {r['memory']}")
if not sections:
return (
"No prior training history found for this user. "
"Ask the user about their goals, equipment, and recent training."
)
return "\n".join(sections)
client.profile(container_tag=USER_ID, q=focus) возвращает объект ProfileResponse. После 5 коротких логов три поля, которые читает инструмент, выглядят так:
profile.profile.static # [] (list[str])
profile.profile.dynamic # ["Performed bench press: 4 sets of 5 reps at 185.0 lbs", ...]
profile.search_results.results # [{"memory": "...", "similarity": 0.631, ...}, ...] (list[dict])
Каждый результат поиска — это словарь Python, а не объект Pydantic. Используйте r["memory"] для текста и r["similarity"] для оценки. Полный словарь содержит следующие ключи:
-
id -
memory -
rootMemoryId -
metadata -
updatedAt -
version -
similarity -
filepath -
documents
Фрагмент r.memory or r.chunk со страницы интеграции Supermemory с OpenAI Agents SDK вызывает AttributeError на версии supermemory==3.37.0. Используйте доступ по ключу в квадратных скобках.
static здесь пуст, поэтому инструмент ветвится по if static_facts:. Ветви dynamic и search_results выполняют основную работу для первой дюжины логов.
Supermemory также применяет порог сходства по умолчанию. Факт, который вы упомянули один раз, может не возвращаться для каждого запроса. 5 логов выше вернулись для q="today", но более конкретная строка запроса может вернуть меньше. Условие if matches: обрабатывает это без сбоев.
Сессия 1: логирование тренировок
Запустите первую сессию и залогируйте несколько тренировок, чтобы наполнить Supermemory данными для последующего чтения. Выполните скрипт:
uv run python main.py
Залогируйте жим лёжа, затем забег на 5 км, затем становую тягу, плюс одно предпочтение: «Я тренируюсь только дома, без зала». Агент вызывает log_workout по одному разу на каждую тренировку, а строки print() инструмента делают каждый вызов заметным в терминале.

Пример вывода. Точная формулировка вашего агента может отличаться, поскольку модель недетерминирована.
Три строки status=queued — это момент, когда Supermemory берёт работу на себя. Каждая соответствует документу, проходящему через конвейер встраивания и извлечения на стороне Supermemory. Для таких коротких логов документ становится доступным для поиска через client.profile() примерно через ~12 секунд.
Код тренера ничего для этого не ждёт. Агент продолжает работу, а Supermemory завершает обработку в фоне.
Каждый лог вызывает ровно один log_workout, и агент останавливается. Никаких проактивных рекомендаций, лишних вызовов инструментов, последующих подсказок. Первое правило системного промпта обеспечивает такое поведение. Без него агент предлагал бы следующую сессию после каждого лога, удваивая количество вызовов.
Введите exit, чтобы закрыть первую сессию. Процесс Python завершится, и SQLiteSession исчезнет вместе с ним. Логи тренировок и заявление о предпочтениях теперь живут в Supermemory под container_tag="demo_user", отдельно от скрипта, который их записал.
Проверка воспроизведения и запуск сессии 2
Перед второй сессией убедитесь, что факты из первой сессии доступны к запросу. Откройте новый REPL Python или сохраните это как короткий скрипт:
from dotenv import load_dotenv
from supermemory import Supermemory
load_dotenv()
client = Supermemory()
prof = client.profile(container_tag="demo_user", q="training")
print(f"static ({len(prof.profile.static)}): {prof.profile.static}")
print(f"dynamic ({len(prof.profile.dynamic)}):")
for fact in prof.profile.dynamic:
print(f" - {fact}")
print(f"matches ({len(prof.search_results.results)}):")
for r in prof.search_results.results[:5]:
print(f" - {r['memory']} (similarity={r['similarity']:.3f})")
Реальный вывод, зафиксированный между двумя сессиями:
static (0): []
dynamic (5):
- Trains at home instead of a gym
- Performed deadlift: 3 sets of 5 reps at 225.0 lbs
- Performed 5k run in 26 minutes
- Reports no knee pain during bench press
- Performed bench press: 4 sets of 5 reps at 185.0 lbs
matches (5):
- Trains at home instead of a gym (similarity=0.682)
- Performed deadlift: 3 sets of 5 reps at 225.0 lbs (similarity=0.643)
- Performed bench press: 4 sets of 5 reps at 185.0 lbs (similarity=0.631)
- Performed 5k run in 26 minutes (similarity=0.585)
- Reports no knee pain during bench press (similarity=0.585)
Посмотрите, что выдал извлекатель Supermemory. Пользователь один раз сказал: «Я тренируюсь только дома, без зала». Извлекатель превратил это в динамический факт "Trains at home instead of a gym".
В лог жима лёжа было добавлено примечание об отсутствии боли в колене. Извлекатель разделил один лог на два динамических факта: один — о тренировке, другой — об отсутствии боли.
Четыре лога превратились в пять нормализованных динамических фактов плюс пять соответствующих фрагментов памяти с коэффициентами сходства от 0,585 до 0,682. Ни разделение, ни нормализация, ни сопоставление не выполнялись кодом тренера. Если у вас dynamic пуст, подождите ещё 10 секунд и повторите запуск. Очередь обработки иногда вырастает.
Теперь запустите вторую сессию в новом процессе:
uv run python main.py
Это свежий интерпретатор Python. Никакой общей памяти с первой сессией. Никакого тёплого кэша. Всё, что агент вспоминает, приходит из Supermemory.
Отправьте одно сообщение: «Что мне сделать на тренировке сегодня?»

Пример вывода. То же хранилище памяти, новый процесс Python.
Агент вызывает suggest_next_session("today"). Инструмент печатает static=0 dynamic=5 matches=5. Зафиксированный запуск ответил сессией для нижней части тела дома (приседания, выпады, степ-апы).
Рекомендация согласовалась с предыдущими логами, потому что профиль Supermemory сообщил агенту, какими они были. Жим, тяга и 5 км — это верх тела или кардио, и пользователь тренируется только дома. Оба факта пришли из одного вызова client.profile(). У вас формулировки могут отличаться, так как модель недетерминирована, но путь воспроизведения памяти будет тот же.
Следующие шаги для вашего агента Supermemory
Демо — это один пользователь, два инструмента и CLI. Реальная версия тренера развивается в трёх направлениях, связанных с Supermemory, прежде чем коснётся цикла агента.
Ограничивайте память реальным пользователем. Константа USER_ID = "demo_user" работает для одного человека. В продакшене тег вычисляют из идентификатора аутентифицированного пользователя: container_tag="user_sarah" или container_tag=customer_id. Память между пользователями остаётся раздельной, потому что каждый запрос на чтение возвращает тег. Меняется одна вещь в tools.py — больше никакой код не трогается.
Добавляйте больше инструментов на памяти. Делод-недели, учёт PR и еженедельные подсказки по мобильности. Каждый — это ещё одна функция с @function_tool, которая вызывает client.add() для записи и client.profile() для чтения с тем же container_tag. Форма инструмента остаётся прежней. Меняется лишь то, что агент записывает и запрашивает.
Обрабатывайте сбои Supermemory. Оборачивайте client.add() и client.profile() в try/except supermemory.APIError, чтобы временные сбои Supermemory не падали агенту в ошибку. Настройте тайм-ауты на запрос, если агент работает в ограниченной среде.
Сторона цикла агента не зависит от Supermemory и может меняться позже. Поставьте над CLI Telegram, Discord или Slack, чтобы пользователь отправлял тренировку текстом, а бот вызывал Runner.run(). Или смените фрамворк. Для Supermemory есть интеграция с LangChain, если ваш стек уже использует агентов LangChain, и код работы с памятью не меняется.
Разделение на статическое и динамическое подходит и для других доменов.
- Агент поддержки: статическое = известные проблемы и предпочтения аккаунта, динамическое = открытые тикеты и последние обращения.
- Кодирующий агент: статическое = предпочитаемые языки и фреймворки, динамическое = текущая задача и недавно тронутые файлы.
Разделение работает везде, где источником истины является пользователь.
Заключение
Вы только что создали тренера на Python с двумя инструментами и постоянной памятью между процессами. client.add() записывает тренировки. client.profile() читает пользователя как статические факты, динамические факты и семантические соответствия одним вызовом, всё в пределах container_tag. Supermemory выполняет разбиение на фрагменты, встраивание, поиск и извлечение профиля, которые демо не пришлось писать.
Сочетая это с RAG, один и тот же агент отвечает на вопросы и о пользователе, и о продукте. Пояснение об LLM-агентах охватывает более широкие паттерны агентов, а трек Associate AI Engineer for Developers глубже погружается в агентов с поддержкой памяти.
Supermemory: ответы на частые вопросы
Что такое Supermemory?
Supermemory — это размещаемый API памяти, который хранит, индексирует и извлекает долгосрочный контекст для AI-агентов, чтобы они могли запоминать пользователей между сессиями.
Чем Supermemory отличается от обычных векторных баз?
Supermemory добавляет поверх хранения эмбеддинги, индексацию, семантический поиск и извлечение фактов в формате профиля, поэтому вы получаете пригодные к использованию воспоминания одним вызовом API.
Может ли Supermemory работать и с RAG, и с пользовательской памятью?
Да. Она поддерживает RAG по документам (файлам и URL) вместе с пользовательской памятью, позволяя одному и тому же API обслуживать знания о продукте и личную историю.
Нужно ли мне самостоятельно управлять моделями эмбеддингов в Supermemory?
Нет, Supermemory сама запускает конвейер встраивания и поиска; вы отправляете сырой текст или контент и запрашиваете его позже без самостоятельного управления моделями или индексами.
Есть ли бесплатный тариф для знакомства с Supermemory?
Да, есть бесплатный план для тестирования и небольших проектов с месячными лимитами по токенам и запросам, чтобы вы могли интегрироваться и экспериментировать перед апгрейдом.