# 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: UUID` - одну активную sandbox на чат - reuse активной sandbox до истечения TTL - cleanup просроченных sandbox в фоне - startup reconciliation по Docker labels после рестарта сервиса - chat mount `rw`, dependencies mount `ro`, lambda-tools mount `ro` - логи, метрики и трейсы через порты `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` ### Установка ```bash make install ``` ### Локальный запуск ```bash 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` должны существовать В дефолтном `config/app.yaml` это значит: ```bash mkdir -p var/sandbox/dependencies var/sandbox/lambda-tools 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: ```bash curl http://127.0.0.1:8123/api/v1/health ``` Создание или reuse sandbox: ```bash 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"}' ``` Пример ответа: ```json { "session_id": "3701cfe3-e05e-48af-8385-442dcd954ca2", "chat_id": "11111111-1111-1111-1111-111111111111", "container_id": "64d839c6007de9396ee08ad4af4a22a59a6410ec5f4892a9277a87eb49c3ff5d", "status": "running", "expires_at": "2026-04-02T21:11:38.292893Z" } ``` ## Запуск через Docker Compose Для локального smoke-run есть `docker-compose.yml`. Он поднимает: - `app` - `docker-engine` в режиме Docker-in-Docker - `otel-collector` При этом `app` получает compose-specific config из: - `config/docker-compose.yml` Запуск: ```bash make compose-up ``` Проверка: ```bash make compose-ps make compose-logs ``` Остановка: ```bash make compose-down ``` Важно: - в `config/docker-compose.yml` сейчас для smoke-проверки стоит `sandbox.image: nginx:1.27-alpine` - для реального agent runtime замени `sandbox.image` на образ своего sandbox/agent контейнера - в 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/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_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` #### Security - `APP_API_TOKEN_HEADER` - `APP_API_TOKEN` - `APP_SIGNING_KEY` ### Что важно в sandbox config - `docker.base_url` — адрес Docker daemon - `sandbox.image` — образ sandbox контейнера - `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 ## Основные команды - `make install` — установить зависимости через `uv` - `make run` — локальный запуск - `make run-otel` — запуск с OTel endpoints из env - `make test` — `pytest` - `make lint` — `ruff` - `make typecheck` — `mypy` - `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` — смотреть статус сервисов ## Документация ### Гайды - [Правила проекта и ограничения для агента](AGENTS.md) - [Кодстайл проекта](docs/CODESTYLE.md) - [Чистая архитектура, SOLID, DIP, Protocol и repository](docs/CLEAN_ARCHITECTURE_RU.md) - [Логи, метрики и трейсы в этом проекте](docs/OBSERVABILITY_RU.md) - [Как чистая архитектура реализована здесь](docs/PROJECT_GUIDE_RU.md) - [План задач и история работ](tasks.md) ### ADR - [001 Composition Root and Lifetimes](docs/001-composition-root-and-lifetimes.md) - [002 Config From YAML and Env](docs/002-config-yaml-plus-env.md) - [003 Observability Via Interfaces](docs/003-observability-via-interfaces.md) - [004 Versioned HTTP API](docs/004-versioned-http-api.md) - [005 Early FastAPI OTel Instrumentation](docs/005-fastapi-otel-early-instrumentation.md) - [006 MVP Docker Sandbox Orchestration](docs/006-mvp-docker-sandbox-orchestration.md) - [007 Startup Sandbox Reconciliation](docs/007-startup-sandbox-reconciliation.md) - [008 Sandbox Lifecycle Observability](docs/008-sandbox-lifecycle-observability.md) ## Для AI-агента Если ты меняешь проект как AI-агент, сначала прочитай: 1. [AGENTS.md](AGENTS.md) 2. [docs/CODESTYLE.md](docs/CODESTYLE.md) 3. [docs/PROJECT_GUIDE_RU.md](docs/PROJECT_GUIDE_RU.md) 4. [docs/CLEAN_ARCHITECTURE_RU.md](docs/CLEAN_ARCHITECTURE_RU.md) 5. [docs/OBSERVABILITY_RU.md](docs/OBSERVABILITY_RU.md) 6. релевантные ADR в `docs/` 7. [tasks.md](tasks.md) Главные правила: - сначала определи слой изменения - зависимости только внутрь - не тащи FastAPI и OpenTelemetry во внутренние слои - архитектурные решения сверяй с ADR