Система State и Переменных
Единая система для работы с сессионными данными и переменными в агентах.
Архитектура
State
State - единый TypedDict для всех агентов (ReAct и StateGraph), который:
- Автоматически персистится через checkpointer
- Доступен в тулах через контекст get_state()
- Содержит сессионное хранилище store
from app.core.state import State
class State(TypedDict):
messages: List # История диалога
store: Dict[str, Any] # Сессионное хранилище
task_id: str
session_id: str
user_id: str
Context
Context - глобальный контекст запроса, который содержит:
- Данные пользователя и компании
- Переменные flow и компании
- Ссылку на текущий state агента
from app.core.context import get_context
context = get_context()
# context.user - пользователь
# context.active_company - компания
# context.flow_variables - переменные flow
# context.state - текущий state агента
Использование
1. Переменные в конфигурации
Переменные Flow
{
"flow_id": "support_flow",
"name": "Поддержка",
"variables": {
"bot_name": "Помощник",
"support_email": "support@company.com",
"working_hours": "9:00-18:00",
"max_wait_time": 30
}
}
Переменные Агента
{
"agent_id": "greeting_agent",
"name": "Приветствие",
"prompt": "Привет! Я {bot_name}. Наши часы работы: {working_hours}.",
"local_variables": {
"greeting": "Здравствуйте!",
"max_attempts": 3
}
}
2. Использование переменных в промптах
Переменные автоматически подставляются при использовании {variable}:
prompt = """
Привет! Я {bot_name} компании {company_name}.
Наши часы работы: {working_hours}
Email: {support_email}
Доступные переменные:
- user_name: {user_name}
- current_date: {current_date}
"""
Доступные системные переменные:
- current_date - текущая дата (YYYY-MM-DD)
- current_time - текущее время (HH:MM)
- current_datetime - дата и время
- current_year, current_month, current_day
- company_name - название компании
- company_id - ID компании
- user_name - имя пользователя
- user_id - ID пользователя
3. Сессионное хранилище в тулах
Используйте готовые тулы для работы с сессией:
from app.tools.session.session_tools import (
session_set,
session_get,
session_has,
session_delete,
session_keys,
get_variable
)
# В конфигурации агента
tools = [
ToolReference(tool_id="app.tools.session.session_tools.session_set"),
ToolReference(tool_id="app.tools.session.session_tools.session_get"),
]
Примеры использования в агенте:
# Агент может сохранять данные между запросами
tools = [session_set, session_get, session_has]
prompt = """
Ты агент поддержки.
ВАЖНО: Используй session_set для сохранения важной информации:
- session_set("user_warehouse", "название склада")
- session_get("user_warehouse") - получить склад
Сохраняй все что узнаешь о пользователе.
"""
4. Доступ к State из кастомных тулов
from langchain_core.tools import tool
from app.core.variables import get_state
@tool
def my_custom_tool(data: str) -> str:
"""Кастомный тул с доступом к state"""
state = get_state()
if not state:
return "State недоступен"
# Читаем из store
previous_data = state.get("store", {}).get("my_key")
# Пишем в store
if "store" not in state:
state["store"] = {}
state["store"]["my_key"] = data
return f"Сохранено: {data}"
5. Работа с переменными в коде
from app.core.variables import VariableResolver
# Получить все переменные
variables = VariableResolver.resolve_all()
# Получить с локальными переменными
variables = VariableResolver.resolve_all(
local_vars={"my_var": "value"}
)
# Рендерить шаблон
result = VariableResolver.render_template(
"Привет, {user_name}! Компания: {company_name}",
local_vars={"custom": "value"}
)
Примеры сценариев
Сценарий 1: Сбор данных о пользователе
# Агент последовательно собирает данные
class DataCollectorAgent(BaseAgent):
prompt = """
Собери информацию о пользователе:
1. Имя склада
2. Номер курьера
3. Описание проблемы
Используй session_set для сохранения каждого ответа:
- session_set("warehouse_name", "...")
- session_set("courier_id", "...")
- session_set("issue_description", "...")
Проверяй что уже сохранено с помощью session_has.
"""
tools = [session_set, session_get, session_has, ask_user]
Сценарий 2: Передача данных между агентами
# Первый агент сохраняет
class Agent1(BaseAgent):
prompt = """
Узнай у пользователя склад и сохрани:
session_set("warehouse_id", "12345")
"""
tools = [session_set, ask_user]
# Второй агент использует
class Agent2(BaseAgent):
prompt = """
Получи склад из сессии:
warehouse_id = session_get("warehouse_id")
Используй его для дальнейшей работы.
"""
tools = [session_get]
Сценарий 3: StateGraph с единым State
from app.core.state import State
def warehouse_node(state: State) -> State:
"""Нода определения склада"""
warehouse_id = "12345" # Логика определения
# Сохраняем в store
state["store"]["warehouse_id"] = warehouse_id
state["store"]["warehouse_name"] = "Большие Каменщики"
return state
def courier_node(state: State) -> State:
"""Нода работы с курьером"""
# Читаем из store
warehouse_id = state["store"].get("warehouse_id")
# Работаем с данными
courier_id = find_courier(warehouse_id)
state["store"]["courier_id"] = courier_id
return state
Приоритет переменных
- Локальные переменные агента (наивысший приоритет)
- Переменные flow
- Переменные компании
- Системные переменные
Персистентность
Что персистится автоматически:
messages- история диалогаstore- сессионное хранилище- Весь
Stateчерез checkpointer
Что НЕ персистится:
variablesиз Context (заполняются при каждом запросе)flow_variablesиз Context (заполняются из FlowConfig)
Best Practices
-
Используйте
storeдля данных между запросами -
Используйте переменные для констант
-
Проверяйте наличие данных
-
Документируйте переменные в промпте
-
Используйте понятные ключи
Миграция с существующего кода
Было (SessionConfig.metadata):
Стало (State.store):
# В агенте
session_set("warehouse_id", "12345")
# В кастомном коде
state["store"]["warehouse_id"] = "12345"