Перейти к содержанию

Конфигурация

agate-server (точка входа в Docker) настраивается одним файлом agate.toml со слоем переопределений из окружения. Смонтируйте файл в контейнер и укажите на него AGATE_CONFIG. Готовый шаблон — agate.example.toml.

Источники и приоритет

От низшего к высшему — каждый следующий слой переопределяет предыдущий:

  1. Встроенные значения по умолчанию.
  2. agate.toml — путь из AGATE_CONFIG (по умолчанию /etc/agate/agate.toml). Отсутствие файла допустимо — применяются значения по умолчанию.
  3. ОкружениеAGATE__SECTION__KEY (в верхнем регистре, __ между уровнями). Секреты предпочтительно задавать через окружение.

То есть [audit].database_url переопределяется через AGATE__AUDIT__DATABASE_URL.

docker run --rm \
  -v "$PWD/agate.toml:/etc/agate/agate.toml:ro" \
  -e AGATE_CONFIG=/etc/agate/agate.toml \
  -e AGATE__AUDIT__DATABASE_URL='postgres://agate:secret@db:5432/agate' \
  ghcr.io/c3equalzz/agate

Отсутствие обязательного значения (proxy.agent_endpoint, audit.database_url) прерывает запуск — отказ при неверной конфигурации вместо работы в деградированном режиме.

[proxy]

Ключ Обязателен По умолчанию Значение
agent_endpoint да URL вышестоящего AG-UI-агента, которому Agate пересылает проинспектированный трафик.
bind нет 0.0.0.0:8080 Адрес/порт, который Agate слушает для входящего AG-UI-трафика.
connect_timeout_secs нет 5 Быстрый таймаут подключения к вышестоящему агенту.
read_timeout_secs нет 60 Таймаут простоя между чанками SSE-ответа. Не общий дедлайн — здоровый поток работает дальше.
max_body_bytes нет 1048576 Максимальный размер тела запроса (1 МиБ). Слишком большие запросы получают 413.
max_concurrent_requests нет 256 Максимум одновременно обрабатываемых прогонов. Каждый держит соединение с агентом на всё время потока; запросы сверх лимита отбрасываются с 503 (не ставятся в очередь), чтобы наплыв не исчерпал память/соединения.
api_key нет Одиночный API-ключ в заголовке X-API-Key (сокращение, объединяется с api_keys). Секрет лучше через AGATE__PROXY__API_KEY.
api_keys нет [] Принятые API-ключи; запрос аутентифицирован, если совпал с любым (иначе 401). Несколько ключей одновременно дают ротацию без даунтайма: добавить новый, перевести клиентов, убрать старый. Если api_key и api_keys пусты — прокси открыт.

Пробы liveness и readiness

/healthz (liveness) возвращает 200, пока процесс жив. /readyz (readiness) возвращает 200 только когда хранилище журнала прозрачности доступно, иначе 503 — направьте на него readiness-пробу оркестратора, чтобы трафик удерживался, пока Agate не сможет записывать. Проверка доступности скрыта за портом HealthCheck, поэтому остаётся корректной при смене бэкенда хранилища. Обе пробы обходят проверки API-ключа и размера тела.

[audit]

Ключ Обязателен По умолчанию Значение
database_url да Строка подключения PostgreSQL для журнала прозрачности (дерево Меркла). Миграции выполняются при старте. Пароль лучше задавать через AGATE__AUDIT__DATABASE_URL.
max_connections нет 10 Максимум подключений в пуле к базе.
acquire_timeout_secs нет 30 Сколько ждать свободного подключения из пула до ошибки.
connect_max_retries нет 10 Сколько раз повторить начальное подключение перед отказом старта (0 = одна попытка). Позволяет переждать БД, которая ещё поднимается рядом с Agate (compose/Kubernetes), вместо падения на первой неудаче.
connect_backoff_secs нет 1 Базовый бэкофф между попытками подключения (удваивается каждый повтор, с потолком).

Журнал, в который добавляются записи, закрепляется переменной окружения AUDIT_LOG_ID (UUID). Если она не задана, при старте создаётся новый журнал и его id печатается, чтобы закрепить его при следующем запуске.

[policy.tools] и [policy]

Все ключи политики необязательны. Если ничего не задано, все инструменты разрешены и ничего не редактируется.

Ключ Формат Значение
[policy.tools].mode allow-all | allowlist | denylist Как авторизуются вызовы инструментов. По умолчанию allow-all.
[policy.tools].names массив имён инструментов Инструменты, управляемые mode (игнорируются при allow-all).
[policy].redact массив литеральных маркеров Подстроки, маскируемые (без учёта регистра) в исходящем тексте до его доставки клиенту.
[policy].fail_mode open | closed Что делать при таймауте решения политики: переслать (open) или заблокировать (closed). По умолчанию closed (безопасность важнее доступности).
[policy].decision_timeout_ms целое (мс) Дедлайн одного решения политики. По умолчанию 5000; должен быть > 0.

Неверная политика прерывает запуск

Пустое или некорректное имя инструмента, либо пустой паттерн редактирования, прерывает запуск — опечатка не должна молча ослаблять контроль.

[observability.logging]

Ключ По умолчанию Значение
enabled true Устанавливать ли подписчик логов вообще; false отключает логи.
format pretty pretty (консоль) или json (по объекту на строку, для сборщиков логов).
level info Директива фильтра (например, agate_proxy=debug,info). RUST_LOG переопределяет её, если задана.

На info видны события жизненного цикла: старт, каждый проксированный прогон, запреты и редакции политики, создание журнала прозрачности. Поднимите до debug (например, level = "agate_proxy=debug,info") для детализации по каждому событию (каждое переданное/буферизованное событие, каждая добавленная запись аудита).

[observability.metrics]

Эндпоинт для Prometheus на отдельном порту, не на публичном data-plane порту (скрейпится из внутренней сети).

Ключ По умолчанию Значение
enabled false Устанавливать ли recorder + экспортёр метрик. Если выключено — метрики no-op.
exporter prometheus prometheus (эндпоинт /metrics) или none.
bind 0.0.0.0:9090 Адрес, который слушает эндпоинт /metrics.

Экспортируемые метрики:

  • agate_runs_total — проксированных прогонов.
  • agate_events_inspected_total{outcome="forward|buffer|transform|deny|terminate"} — проинспектированные события по исходу (разбивка по вердиктам).
  • agate_upstream_errors_total — ошибки запроса/потока к вышестоящему агенту.
  • agate_audit_records_appended_total / agate_audit_records_dropped_total — записи в журнал прозрачности против дропов (ненулевой drop-rate = аудит не успевает, ставьте алерт).

Готовый стек Prometheus + Grafana с преднастроенным дашбордом — в deploy/observability/.

[observability.tracing]

Экспорт трейсов по OTLP — третий столп наблюдаемости наряду с логами и метриками. Когда трейсинг выключен, спаны всё равно создаются, но не экспортируются; в логах они видны, только если [observability.logging].enabled = true (подписчик, который и рендерит спаны в логи, и экспортирует их, поднимается лишь тогда).

Ключ По умолчанию Значение
enabled false Экспортировать спаны в OTLP-коллектор по gRPC.
endpoint http://localhost:4317 OTLP gRPC-эндпоинт коллектора.
service_name agate-server service.name в экспортируемых спанах.

Спаны покрывают путь запроса от края до края:

  • proxy_run — по одному на каждый проксированный прогон на data-plane.
  • audit.request — по одному на каждую отправленную команду/запрос аудита. TracingBehavior оборачивает весь конвейер медиатора (самым внешним звеном, поверх behaviour'ов метрик и транзакции), поэтому каждый use case трассируется единообразно — новые use case'ы получают спан автоматически.
  • db.log.load / db.log.save / db.proof.inclusion / db.proof.consistency — по одному на каждый SQL-оператор, вложенному в спан audit.request, который его инициировал.

Когда трейсинг включён (и [observability.logging].enabled = true, чтобы подписчик был установлен), спаны сбрасываются при graceful shutdown. Укажите endpoint на OpenTelemetry Collector (или любой OTLP/gRPC-бэкенд), чтобы собирать трейсы по каждому прогону.

[tls]

Терминация TLS на собственном слушателе Agate. По умолчанию выключено — тогда Agate отдаёт обычный HTTP, что разумно только за TLS-терминирующим шлюзом (ingress, балансировщик, service mesh). Включите, чтобы отдавать HTTPS напрямую (например, в zero-trust-развёртывании без отдельного терминатора).

Ключ По умолчанию Значение
enabled false Отдавать HTTPS вместо обычного HTTP. При false cert/key игнорируются.
cert Путь к PEM-цепочке сертификатов (листовой сертификат первым). Обязателен при включении.
key Путь к PEM-приватному ключу для cert. Обязателен при включении.

При включении отсутствие или некорректность cert/key прерывает запуск (отказ при неверно настроенном слушателе). Тогда и пробы, и data-plane отдаются по одному TLS-слушателю на proxy.bind.

Полный пример

[proxy]
agent_endpoint = "http://agent:8000/run"
bind = "0.0.0.0:8080"
connect_timeout_secs = 5
read_timeout_secs = 60
max_body_bytes = 1048576
max_concurrent_requests = 256
# api_key = "change-me"          # один ключ; секрет лучше через AGATE__PROXY__API_KEY
# api_keys = ["current", "next"] # несколько ключей для ротации без даунтайма

[audit]
# Пароль лучше задавать через AGATE__AUDIT__DATABASE_URL.
database_url = "postgres://agate@postgres:5432/agate"
max_connections = 10
acquire_timeout_secs = 30
connect_max_retries = 10
connect_backoff_secs = 1

[policy.tools]
mode = "allowlist"
names = ["search", "fetch"]

[policy]
redact = ["sk-", "AKIA"]
fail_mode = "closed"
decision_timeout_ms = 5000

[observability.logging]
enabled = true
format = "pretty"
level = "info"

[observability.metrics]
enabled = true
exporter = "prometheus"
bind = "0.0.0.0:9090"

[observability.tracing]
enabled = false
endpoint = "http://localhost:4317"
service_name = "agate-server"

[tls]
enabled = false
cert = "/etc/agate/tls/cert.pem"
key = "/etc/agate/tls/key.pem"