Демо-проект про AI-агента в квест-комнате. ИИ пытается выбраться, исследуя комнату и взаимодействуя с её сущностями. Человек общается с ним через интерком и старается запутать его, чтобы не дать найти выход.
- LangChain
create_agentи GPT через OpenAI-compatible API. - Два характера агента: инженер и тестировщик.
- Декларативный YAML-сценарий с сущностями, действиями, условиями и исходами.
- Не более одного игрового действия за ход; ответ без действия тоже допустим.
- Каждое выполненное действие расходует ход. После достижения
max_actionsИИ проигрывает. - Состояние комнаты и история сообщений хранятся в checkpoint LangGraph по
session_id. - FastAPI API, статичная главная страница и игровой интерфейс на
/game. - Опциональная трассировка LangChain в Phoenix.
escape_agent/game/ содержит чистую игровую логику без импортов LangChain и LangGraph:
scenario.py— модели и загрузка YAML-сценария;engine.py— применение правил и формирование видимого состояния;models.pyиtypes.py— состояние и типы игрового домена.
Интеграционный слой:
agent.pyсоздаёт граф, запускает партии и выполняет ходы;middleware/game.pyрегистрирует игровые tools, подключаетEscapeAgentStateи формирует системный prompt;tools.pyадаптирует методы движка к LangChain tools и обновляет состояние черезCommand;results.pyпреобразует сообщения LangChain в компактные ответы API;dependencies.pyзагружает конфигурацию, модель и сценарий при старте приложения.
dependencies.py
→ EscapeAgent
→ EscapeGameMiddleware
→ tools.py
→ EscapeGameEngine
EscapeGameEngine не хранит сессии и не знает конкретных идентификаторов комнаты. Единственным хранилищем партий служит InMemorySaver; session_id одновременно используется как thread_id LangGraph.
Активный сценарий выбирается через game.default_scenario в config.yml и загружается из scenarios/<name>.yml.
В sealed_room.yml описаны:
characters— стартовые реплики и характеры персонажей;entities— сущности комнаты и условия их доступностиavailable_when;action_rules— правила дляinteract_with,use_onиenter_code;endings— сообщения победы и поражения;max_actions— максимальное число действий.
Правила проверяются по порядку. applies_when ограничивает применимость правила, а результат может активировать сущности, изменить статус игры и вернуть наблюдаемый текст. Ключ из открытого ящика сразу становится доступной сущностью и не требует отдельного инвентаря.
Игровой движок универсален, но визуальная раскладка /game рассчитана на сценарий sealed_room.
Требуется Python 3.13 или 3.14 и uv.
uv syncСоздайте .env на основе .env.example и укажите ключ:
OPENAI_API_KEY=your_key_hereGPT настраивается в единственном разделе llm файла config.yml:
llm:
model: "gpt-5.4-mini"
base_url: "https://llm.inzhenerka-cloud.com/"
timeout: 60
max_output_tokens: 700Поднимите сервер в режиме разработки:
uv run fastapi dev- Главная страница:
http://127.0.0.1:8000/ - Игра:
http://127.0.0.1:8000/game - Swagger UI:
http://127.0.0.1:8000/docs
Сессии находятся в памяти процесса. После перезапуска сервера они теряются; игровой UI также начинает новую партию после обновления страницы.
Трассировка отключена, пока не задан ключ:
PHOENIX_API_KEY=your_phoenix_keyEndpoint и имя проекта находятся в разделе observability файла config.yml.
Тесты используют fake chat models и не вызывают внешний LLM:
uv run python -m unittest discover -s tests -v