No description
Find a file
2026-05-08 15:24:15 +03:00
adapter add sandbox extra env config 2026-05-08 15:24:15 +03:00
config add sandbox extra env config 2026-05-08 15:24:15 +03:00
docs add sandbox runtime control endpoints 2026-04-28 21:53:26 +03:00
domain include docker error reason in sandbox start failure response 2026-05-05 10:04:58 +03:00
meetings [feat] add context and tasks for master-service 2026-04-02 11:57:20 +03:00
repository add sandbox observability contracts 2026-04-03 00:37:35 +03:00
tasks [feat] add tasks 2026-04-07 19:11:51 +03:00
test add sandbox extra env config 2026-05-08 15:24:15 +03:00
usecase add sandbox runtime control endpoints 2026-04-28 21:53:26 +03:00
.gitignore ref #9: [feat] add tests 2026-04-02 20:28:14 +03:00
AGENTS.md [feat] add tasks 2026-04-07 19:11:51 +03:00
docker-compose.yml auto-create sandbox dirs and switch to host socket compose 2026-05-05 10:03:00 +03:00
Dockerfile [feat] add docker 2026-03-20 22:44:46 +03:00
main.py [feat] add fastapi adapter 2026-03-20 15:06:39 +03:00
Makefile update local dev token defaults 2026-05-05 09:19:15 +03:00
pyproject.toml ref #5: [feat] add docker impl 2026-04-02 12:55:38 +03:00
README.md update sandbox control docs 2026-04-28 21:56:06 +03:00
tasks.md update sandbox control task plan 2026-04-28 21:53:34 +03:00
uv.lock ref #5: [feat] add docker impl 2026-04-02 12:55:38 +03:00

master-service

master-service — это control-plane сервис для sandbox-контейнеров с AI-агентом. Он поднимает и переиспользует sandbox на чат, подключает рабочие volume, восстанавливает state после рестарта и отдает наружу минимальный HTTP API под /api/v1.

Важно: в локальном config/app.yaml исторически еще стоят template-имена web-python-skelet. Если хочешь, чтобы /health и OTel service name локально тоже показывали master-service, переопредели:

  • APP_NAME=master-service
  • APP_OTEL_SERVICE_NAME=master-service

Сервис реализован на Python с Clean Architecture:

  • domain/ — сущности и доменные ошибки
  • usecase/ — сценарии приложения и порты
  • repository/ — реализации repository
  • adapter/ — HTTP, config, DI, Docker runtime и observability

Что умеет сейчас

Текущий sandbox MVP покрывает:

  • GET /api/v1/health
  • POST /api/v1/create с chat_id, agent_id и volume_host_path
  • DELETE /api/v1/sandboxes/{chat_id} для удаления активной sandbox
  • одну активную sandbox на чат
  • reuse активной sandbox до истечения TTL при совпадении agent_id и volume_host_path
  • возврат Docker-network endpoint ip:port после создания или reuse sandbox
  • cleanup просроченных sandbox в фоне
  • startup reconciliation по Docker labels после рестарта сервиса
  • chat mount rw, request volume mount rw, dependencies mount ro, lambda-tools mount ro
  • прокидывание AGENT_ID в env sandbox-контейнера
  • логи, метрики и трейсы через порты Logger, Metrics, Tracer

Пока вне scope:

  • auth и access control
  • p2p/WebSocket lease
  • workspace/chat CRUD API
  • central DB, artifacts, S3, quota и retention policy

Как устроен проект

  • FastAPI живет только во внешнем adapter слое
  • Docker живет только во внешнем adapter слое
  • конфиг собирается из config/app.yaml, .env и env vars в один dataclass tree
  • repository и usecase создаются один раз на старте в adapter/di/container.py
  • observability не протекает во внутренние слои через OpenTelemetry SDK

Структура

  • domain/ — core model и domain errors
  • usecase/ — use cases и interfaces
  • repository/ — in-memory и другие repository implementations
  • adapter/config/ — typed config models и loader
  • adapter/docker/ — Docker sandbox runtime
  • adapter/observability/ — logger/metrics/tracer runtime factory
  • adapter/otel/ — OpenTelemetry adapters
  • adapter/di/ — composition root
  • adapter/http/fastapi/ — app, middleware, schemas, routers
  • adapter/sandbox/ — sandbox reconciliation logic
  • config/ — YAML config files
  • docs/ — ADR и проектные гайды

Быстрый старт

Требования

  • Python 3.13
  • uv
  • локальный Docker daemon
  • секреты APP_API_TOKEN и APP_SIGNING_KEY

Установка

make install

Локальный запуск

APP_API_TOKEN=local-api-token APP_SIGNING_KEY=local-signing-key make run

Это поднимет сам API, но для успешного POST /api/v1/create локально нужен еще рабочий sandbox runtime:

  • Docker daemon должен быть доступен по docker.base_url
  • образ sandbox.image должен существовать локально
  • директории sandbox.dependencies_host_path и sandbox.lambda_tools_host_path должны существовать
  • Docker network sandbox.network_name должен существовать заранее
  • volume_host_path из request должен быть абсолютным host path

В дефолтном config/app.yaml это значит:

mkdir -p var/sandbox/dependencies var/sandbox/lambda-tools
mkdir -p /tmp/master-volume
docker network inspect sandbox >/dev/null || docker network create sandbox
docker image inspect ai-agent:latest >/dev/null

Если у тебя нет готового ai-agent:latest, проще начать с Docker Compose smoke path ниже.

После старта сервис доступен на:

  • http://127.0.0.1:8123/api/v1/health

Проверка health:

curl http://127.0.0.1:8123/api/v1/health

Создание или reuse sandbox:

curl -X POST http://127.0.0.1:8123/api/v1/create \
  -H 'Content-Type: application/json' \
  -d '{
    "chat_id":"11111111-1111-1111-1111-111111111111",
    "agent_id":"agent-local",
    "volume_host_path":"/tmp/master-volume"
  }'

Пример ответа:

{
  "session_id": "3701cfe3-e05e-48af-8385-442dcd954ca2",
  "chat_id": "11111111-1111-1111-1111-111111111111",
  "agent_id": "agent-local",
  "volume_host_path": "/tmp/master-volume",
  "container_id": "64d839c6007de9396ee08ad4af4a22a59a6410ec5f4892a9277a87eb49c3ff5d",
  "endpoint": {
    "ip": "172.18.0.5",
    "port": 8000
  },
  "status": "running",
  "expires_at": "2026-04-02T21:11:38.292893Z"
}

Повторный create для того же chat_id вернет существующую sandbox только если совпадают agent_id и canonical volume_host_path. Если параметры отличаются, API вернет 409 sandbox_conflict.

Удаление sandbox по chat:

curl -X DELETE http://127.0.0.1:8123/api/v1/sandboxes/11111111-1111-1111-1111-111111111111

Пример ответа:

{
  "chat_id": "11111111-1111-1111-1111-111111111111",
  "result": "deleted",
  "session_id": "3701cfe3-e05e-48af-8385-442dcd954ca2",
  "container_id": "64d839c6007de9396ee08ad4af4a22a59a6410ec5f4892a9277a87eb49c3ff5d"
}

Если активной sandbox нет, result будет not_found. Возвращенный endpoint.ip доступен из контейнеров, подключенных к той же Docker network.

Запуск через Docker Compose

Для локального smoke-run есть docker-compose.yml. Он поднимает:

  • app
  • docker-engine в режиме Docker-in-Docker
  • otel-collector

При этом app получает compose-specific config из:

  • config/docker-compose.yml

Запуск:

make compose-up

Проверка:

make compose-ps
make compose-logs

Остановка:

make compose-down

Важно:

  • в config/docker-compose.yml сейчас для smoke-проверки стоит sandbox.image: nginx:1.27-alpine
  • для реального agent runtime замени sandbox.image на образ своего sandbox/agent контейнера
  • sandbox подключается к Docker network из sandbox.network_name; внешний контейнер-интеграцию нужно подключить к этой же сети
  • в compose auth env vars нужны для startup config, но текущий MVP API еще не проверяет request token

Как конфигурировать

Источники конфига

Конфиг собирается в таком порядке:

  1. базовый YAML из config/app.yaml
  2. значения из .env
  3. process env vars поверх .env

То есть env vars имеют наивысший приоритет.

Обязательные секреты

Нужны всегда:

  • APP_API_TOKEN
  • APP_SIGNING_KEY

Сейчас это startup config, а не активная request auth для /api/v1/create, /api/v1/sandboxes/{chat_id} и /api/v1/health. То есть в текущем MVP токен не нужно передавать в HTTP headers для вызова этих endpoint.

Основные секции YAML

В config/app.yaml и config/docker-compose.yml есть секции:

  • app
  • http
  • logging
  • metrics
  • tracing
  • otel
  • docker
  • sandbox
  • security

Полезные env overrides

Чаще всего полезны:

Общие

  • APP_NAME
  • APP_ENV
  • APP_HTTP_HOST
  • APP_HTTP_PORT

Логирование и observability

  • APP_LOGGING_LEVEL
  • APP_LOGGING_OUTPUT
  • APP_LOGGING_FORMAT
  • APP_LOGGING_FILE_PATH
  • APP_METRICS_ENABLED
  • APP_TRACING_ENABLED
  • APP_OTEL_SERVICE_NAME
  • APP_OTEL_LOGS_ENDPOINT
  • APP_OTEL_METRICS_ENDPOINT
  • APP_OTEL_TRACES_ENDPOINT

Docker runtime

  • APP_DOCKER_BASE_URL

Sandbox

  • APP_SANDBOX_IMAGE
  • APP_SANDBOX_NETWORK_NAME
  • APP_SANDBOX_AGENT_SERVICE_PORT
  • APP_SANDBOX_TTL_SECONDS
  • APP_SANDBOX_CLEANUP_INTERVAL_SECONDS
  • APP_SANDBOX_CHATS_ROOT
  • APP_SANDBOX_DEPENDENCIES_HOST_PATH
  • APP_SANDBOX_LAMBDA_TOOLS_HOST_PATH
  • APP_SANDBOX_CHAT_MOUNT_PATH
  • APP_SANDBOX_DEPENDENCIES_MOUNT_PATH
  • APP_SANDBOX_LAMBDA_TOOLS_MOUNT_PATH
  • APP_SANDBOX_VOLUME_MOUNT_PATH

Security

  • APP_API_TOKEN_HEADER
  • APP_API_TOKEN
  • APP_SIGNING_KEY

Что важно в sandbox config

  • docker.base_url — адрес Docker daemon
  • sandbox.image — образ sandbox контейнера
  • sandbox.network_name — Docker network для sandbox и интеграций
  • sandbox.agent_service_port — порт agent service внутри sandbox, возвращается в response endpoint
  • sandbox.ttl_seconds — TTL sandbox
  • sandbox.cleanup_interval_seconds — частота cleanup loop
  • sandbox.chats_root — корень chat directories
  • sandbox.dependencies_host_path — host path для dependency cache
  • sandbox.lambda_tools_host_path — host path для read-only lambda-tools
  • sandbox.chat_mount_path — путь внутри sandbox для chat volume
  • sandbox.dependencies_mount_path — путь внутри sandbox для dependency cache
  • sandbox.lambda_tools_mount_path — путь внутри sandbox для lambda-tools
  • sandbox.volume_mount_path — путь внутри sandbox для request volume_host_path

Основные команды

  • make install — установить зависимости через uv
  • make run — локальный запуск
  • make run-otel — запуск с OTel endpoints из env
  • make testpytest
  • make lintruff
  • make typecheckmypy
  • make pre-commit — lint + typecheck + test
  • make compose-build — собрать compose images
  • make compose-up — поднять локальный stack
  • make compose-down — остановить stack
  • make compose-logs — смотреть логи
  • make compose-ps — смотреть статус сервисов

Документация

Гайды

ADR

Для AI-агента

Если ты меняешь проект как AI-агент, сначала прочитай:

  1. AGENTS.md
  2. docs/CODESTYLE.md
  3. docs/PROJECT_GUIDE_RU.md
  4. docs/CLEAN_ARCHITECTURE_RU.md
  5. docs/OBSERVABILITY_RU.md
  6. релевантные ADR в docs/
  7. tasks.md

Главные правила:

  • сначала определи слой изменения
  • зависимости только внутрь
  • не тащи FastAPI и OpenTelemetry во внутренние слои
  • архитектурные решения сверяй с ADR