diff --git a/README.md b/README.md index 3ff3dd6..715fedc 100644 --- a/README.md +++ b/README.md @@ -18,12 +18,15 @@ Текущий sandbox MVP покрывает: - `GET /api/v1/health` -- `POST /api/v1/create` с `chat_id: UUID` +- `POST /api/v1/create` с `chat_id`, `agent_id` и `volume_host_path` +- `DELETE /api/v1/sandboxes/{chat_id}` для удаления активной sandbox - одну активную sandbox на чат -- reuse активной sandbox до истечения TTL +- reuse активной sandbox до истечения TTL при совпадении `agent_id` и `volume_host_path` +- возврат Docker-network endpoint `ip:port` после создания или reuse sandbox - cleanup просроченных sandbox в фоне - startup reconciliation по Docker labels после рестарта сервиса -- chat mount `rw`, dependencies mount `ro`, lambda-tools mount `ro` +- chat mount `rw`, request volume mount `rw`, dependencies mount `ro`, lambda-tools mount `ro` +- прокидывание `AGENT_ID` в env sandbox-контейнера - логи, метрики и трейсы через порты `Logger`, `Metrics`, `Tracer` Пока вне scope: @@ -81,11 +84,15 @@ APP_API_TOKEN=local-api-token APP_SIGNING_KEY=local-signing-key make run - 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` это значит: ```bash 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 ``` @@ -105,7 +112,11 @@ curl http://127.0.0.1:8123/api/v1/health ```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"}' + -d '{ + "chat_id":"11111111-1111-1111-1111-111111111111", + "agent_id":"agent-local", + "volume_host_path":"/tmp/master-volume" + }' ``` Пример ответа: @@ -114,12 +125,41 @@ curl -X POST http://127.0.0.1:8123/api/v1/create \ { "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: + +```bash +curl -X DELETE http://127.0.0.1:8123/api/v1/sandboxes/11111111-1111-1111-1111-111111111111 +``` + +Пример ответа: + +```json +{ + "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`. @@ -153,6 +193,7 @@ 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 ## Как конфигурировать @@ -172,7 +213,7 @@ make compose-down - `APP_API_TOKEN` - `APP_SIGNING_KEY` -Сейчас это startup config, а не активная request auth для `/api/v1/create` и `/api/v1/health`. +Сейчас это startup config, а не активная request auth для `/api/v1/create`, `/api/v1/sandboxes/{chat_id}` и `/api/v1/health`. То есть в текущем MVP токен не нужно передавать в HTTP headers для вызова этих endpoint. ### Основные секции YAML @@ -215,6 +256,8 @@ make compose-down #### 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` @@ -223,6 +266,7 @@ make compose-down - `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` @@ -233,6 +277,8 @@ make compose-down - `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 @@ -241,6 +287,7 @@ make compose-down - `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` ## Основные команды @@ -278,6 +325,7 @@ make compose-down - [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) +- [009 Sandbox HTTP Control and Runtime Params](docs/009-sandbox-http-control-and-runtime-params.md) ## Для AI-агента