| adapter | ||
| config | ||
| docs | ||
| domain | ||
| meetings | ||
| repository | ||
| tasks | ||
| test | ||
| usecase | ||
| .gitignore | ||
| AGENTS.md | ||
| docker-compose.yml | ||
| Dockerfile | ||
| main.py | ||
| Makefile | ||
| pyproject.toml | ||
| README.md | ||
| tasks.md | ||
| uv.lock | ||
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-serviceAPP_OTEL_SERVICE_NAME=master-service
Сервис реализован на Python с Clean Architecture:
domain/— сущности и доменные ошибкиusecase/— сценарии приложения и портыrepository/— реализации repositoryadapter/— HTTP, config, DI, Docker runtime и observability
Что умеет сейчас
Текущий sandbox MVP покрывает:
GET /api/v1/healthPOST /api/v1/createсchat_id,agent_idиvolume_host_pathDELETE /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 mountrw, dependencies mountro, lambda-tools mountro - прокидывание
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 errorsusecase/— use cases и interfacesrepository/— in-memory и другие repository implementationsadapter/config/— typed config models и loaderadapter/docker/— Docker sandbox runtimeadapter/observability/— logger/metrics/tracer runtime factoryadapter/otel/— OpenTelemetry adaptersadapter/di/— composition rootadapter/http/fastapi/— app, middleware, schemas, routersadapter/sandbox/— sandbox reconciliation logicconfig/— YAML config filesdocs/— 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.
Он поднимает:
appdocker-engineв режиме Docker-in-Dockerotel-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
Как конфигурировать
Источники конфига
Конфиг собирается в таком порядке:
- базовый YAML из
config/app.yaml - значения из
.env - process env vars поверх
.env
То есть env vars имеют наивысший приоритет.
Обязательные секреты
Нужны всегда:
APP_API_TOKENAPP_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 есть секции:
apphttploggingmetricstracingoteldockersandboxsecurity
Полезные env overrides
Чаще всего полезны:
Общие
APP_NAMEAPP_ENVAPP_HTTP_HOSTAPP_HTTP_PORT
Логирование и observability
APP_LOGGING_LEVELAPP_LOGGING_OUTPUTAPP_LOGGING_FORMATAPP_LOGGING_FILE_PATHAPP_METRICS_ENABLEDAPP_TRACING_ENABLEDAPP_OTEL_SERVICE_NAMEAPP_OTEL_LOGS_ENDPOINTAPP_OTEL_METRICS_ENDPOINTAPP_OTEL_TRACES_ENDPOINT
Docker runtime
APP_DOCKER_BASE_URL
Sandbox
APP_SANDBOX_IMAGEAPP_SANDBOX_NETWORK_NAMEAPP_SANDBOX_AGENT_SERVICE_PORTAPP_SANDBOX_TTL_SECONDSAPP_SANDBOX_CLEANUP_INTERVAL_SECONDSAPP_SANDBOX_CHATS_ROOTAPP_SANDBOX_DEPENDENCIES_HOST_PATHAPP_SANDBOX_LAMBDA_TOOLS_HOST_PATHAPP_SANDBOX_CHAT_MOUNT_PATHAPP_SANDBOX_DEPENDENCIES_MOUNT_PATHAPP_SANDBOX_LAMBDA_TOOLS_MOUNT_PATHAPP_SANDBOX_VOLUME_MOUNT_PATH
Security
APP_API_TOKEN_HEADERAPP_API_TOKENAPP_SIGNING_KEY
Что важно в sandbox config
docker.base_url— адрес Docker daemonsandbox.image— образ sandbox контейнераsandbox.network_name— Docker network для sandbox и интеграцийsandbox.agent_service_port— порт agent service внутри sandbox, возвращается в response endpointsandbox.ttl_seconds— TTL sandboxsandbox.cleanup_interval_seconds— частота cleanup loopsandbox.chats_root— корень chat directoriessandbox.dependencies_host_path— host path для dependency cachesandbox.lambda_tools_host_path— host path для read-only lambda-toolssandbox.chat_mount_path— путь внутри sandbox для chat volumesandbox.dependencies_mount_path— путь внутри sandbox для dependency cachesandbox.lambda_tools_mount_path— путь внутри sandbox для lambda-toolssandbox.volume_mount_path— путь внутри sandbox для requestvolume_host_path
Основные команды
make install— установить зависимости черезuvmake run— локальный запускmake run-otel— запуск с OTel endpoints из envmake test—pytestmake lint—ruffmake typecheck—mypymake pre-commit— lint + typecheck + testmake compose-build— собрать compose imagesmake compose-up— поднять локальный stackmake compose-down— остановить stackmake compose-logs— смотреть логиmake compose-ps— смотреть статус сервисов
Документация
Гайды
- Правила проекта и ограничения для агента
- Кодстайл проекта
- Чистая архитектура, SOLID, DIP, Protocol и repository
- Логи, метрики и трейсы в этом проекте
- Как чистая архитектура реализована здесь
- План задач и история работ
ADR
- 001 Composition Root and Lifetimes
- 002 Config From YAML and Env
- 003 Observability Via Interfaces
- 004 Versioned HTTP API
- 005 Early FastAPI OTel Instrumentation
- 006 MVP Docker Sandbox Orchestration
- 007 Startup Sandbox Reconciliation
- 008 Sandbox Lifecycle Observability
- 009 Sandbox HTTP Control and Runtime Params
Для AI-агента
Если ты меняешь проект как AI-агент, сначала прочитай:
- AGENTS.md
- docs/CODESTYLE.md
- docs/PROJECT_GUIDE_RU.md
- docs/CLEAN_ARCHITECTURE_RU.md
- docs/OBSERVABILITY_RU.md
- релевантные ADR в
docs/ - tasks.md
Главные правила:
- сначала определи слой изменения
- зависимости только внутрь
- не тащи FastAPI и OpenTelemetry во внутренние слои
- архитектурные решения сверяй с ADR