121 lines
18 KiB
Markdown
Executable File
121 lines
18 KiB
Markdown
Executable File
---
|
||
tags:
|
||
- ai-agents
|
||
- security
|
||
- guardrails
|
||
- mcp
|
||
- policy-engine
|
||
title: Gatekeeper Architecture for Agent Tool Calls
|
||
date: '2026-09-29'
|
||
status: complete
|
||
---
|
||
# Привратник для агентских инструментов: контроль tool calls отдельным слоем (2025–2026)
|
||
|
||
> Исследование: как в агентских системах проверяют и одобряют **каждый tool call** отдельным слоем (policy engine / interception / MCP proxy), а не самим агентом.
|
||
> Дата: 2026-09-29. Все ссылки проверены.
|
||
|
||
## Общий вывод
|
||
|
||
Единого стандарта «привратника» в 2025–2026 нет. Сложилось **4 архитектурных уровня**, где может сидеть контроль:
|
||
|
||
1. **In-harness hooks** (Claude Code PreToolUse, ADK callbacks, LangChain middleware) — контроль внутри runtime агента, ближе к самому агенту.
|
||
2. **Policy engines вне агента** (OPA/Rego, Cedar/AVP) — решения принимаются детерминированным внешним движком.
|
||
3. **MCP proxy / gateway** — сетевой слой-посредник, фильтрует трафик tool calls в обе стороны.
|
||
4. **Guardrail/scan слои** (Invariant, LlamaFirewall, NeMo, Lasso) — ML-классификаторы + правила поверх трафика.
|
||
|
||
Ключевой консенсус: **детерминированные проверки — policy engine; семантические («токсично/инъекция») — ML-классификатор, а не policy**. И любое решение должно быть **explainable + логируемым** (для апелляций и итерации правил).
|
||
|
||
---
|
||
|
||
## Подход 1. Claude Code: permissions + PreToolUse hooks
|
||
**Зрелость: ВЫСОКАЯ (production, v2.x, ноябрь 2025+)**
|
||
|
||
- Трёхуровневая система правил `allow` / `ask` / `deny` с порядком вычисления **deny → ask → allow** (первое совпадение побеждает; специфичность не влияет).
|
||
- **PreToolUse hook** срабатывает *перед* permission-промптом на **каждый** tool call (кроме `EndConversation`); hook возвращает JSON `{permissionDecision: "deny"|"ask"|"allow", permissionDecisionReason}` и может заблокировать/форсировать промпт/пропустить его.
|
||
- Hooks — это shell-команды, HTTP-endpoint, MCP tool calls, LLM-промпты или subagents; три уровня конфигурации: event → matcher → handler.
|
||
- Важно: правила **enforced by Claude Code, not by the model** — инструкции в CLAUDE.md/prompt *не* меняют то, что разрешено.
|
||
- Deny с bare tool name удаляет инструмент из контекста модели; scoped deny (`Bash(rm *)`) оставляет инструмент, но блокирует вызов.
|
||
- Источник: https://code.claude.com/docs/en/permissions , https://code.claude.com/docs/en/hooks
|
||
|
||
## Подход 2. MCP Authorization Spec (OAuth 2.1) + Security Best Practices
|
||
**Зрелость: СРЕДНЕ-ВЫСОКАЯ (спек в draft/2025-06-18, OPTIONAL, ломающие ревизии)**
|
||
|
||
- Спецификация описывает **transport-level authorization** на основе OAuth 2.1 (RFC6750, RFC8414, RFC7591, RFC8707, RFC9728) только для HTTP-транспорта; STDIO — берёт креды из env, спек не применяет.
|
||
- Роли: MCP server = OAuth resource server, MCP client = OAuth client, плюс authorization server. Принцип least privilege через `scope` в `WWW-Authenticate`, поддерживается step-up authorization.
|
||
- Dynamic Client Registration **deprecated** (оставлен для обратной совместимости); вместо него Client ID Metadata Documents.
|
||
- Отдельный документ **Security Best Practices** покрывает confused deputy, token passthrough, per-client consent, обязательный валидатор `state`, `__Host-` cookies, точный redirect_uri match.
|
||
- Важное ограничение: авторизация **OPTIONAL** и НЕ покрывает *per-tool-call* политику (какие конкретно инструменты можно звать) — это оставляют приложениям/proxy.
|
||
- Источник: https://modelcontextprotocol.io/specification/draft/basic/authorization , https://modelcontextprotocol.io/specification/draft/basic/security_best_practices
|
||
|
||
## Подход 3. OPA (Open Policy Agent) как policy engine для tool calls
|
||
**Зрелость: ВЫСОКАЯ (CNCF graduated, но agent-интеграции — 2025+, молодые)**
|
||
|
||
- OPA развязывает **policy decision от enforcement**: клиент шлёт JSON input → OPA (Rego + data) → решение. `deny`/`allow`/`requires-approval`/`not-applicable`.
|
||
- Экспрессивность Rego (Datalog, Тьюринг-полный) позволяет multi-hop решения («может ли агент читать данные проекта из того же отдела»); p99 латентность < 1 ms in-process.
|
||
- Прямая agent-интеграция: **`@ai-sdk/policy-opa`** (Vercel AI SDK) через `toolApproval` callback — правила вынесены в `.rego`, тестируются `opa test` в CI, меняются без деплоя. Policy `input` несёт `messages` (история tool calls) → правила вида «approval после N записей», «deny второго необратимого действия», бюджет/токен-квоты.
|
||
- Эмпирическое правило вендора: если можно указать поле в `input` и написать точную проверку — это правильный инструмент; семантику («no toxic content») сюда класть нельзя.
|
||
- OPA MCP (npm `@orygn/opa-mcp`) даёт агенту 50+ инструментов для authoring/debug Rego.
|
||
- Источник: https://www.openpolicyagent.org/docs/latest/ , https://ai-sdk.dev/docs/agents/policy-tool-approvals , https://inferensys.com/differences/mcp-security-gateways-and-agent-tool-sandboxes/policy-as-code-engines-for-agents/open-policy-agent-opa-vs-cedar-agent-tool-authorization
|
||
|
||
## Подход 4. Cedar (AWS) как policy language
|
||
**Зрелость: СРЕДНЕ-ВЫСОКАЯ (Apache 2.0, AWS Verified Permissions; agent-специфика ранняя)**
|
||
|
||
- Purpose-built язык авторизации: четыре элемента — **principal / action / resource / context** + schema. Схема используется *только* для валидации политик, не при evaluation.
|
||
- Ключевое преимущество: **ограниченная выразительность намеренно** — делает автоматический анализ политик вычислимо возможным (напр. доказать, что политика никогда не даёт публичный доступ). Это критично для security-аудита.
|
||
- Интеграция с AWS IAM / Amazon Verified Permissions / Verified Access; p99 < 2 ms (managed). Практический предел ~1000 правил против 10000+ у OPA.
|
||
- Trade-off: менее выразителен, чем Rego (нет графовых обходов), AWS-центричен; standalone engine требует кастомной интеграции.
|
||
- MCP-нативной интеграции нет ни у OPA, ни у Cedar — нужен «custom adapter» (отсюда и весь рынок MCP gateway/proxy).
|
||
- Источник: https://docs.cedarpolicy.com/ , https://inferensys.com/differences/...
|
||
|
||
## Подход 5. MCP proxy / security gateway (сетевой привратник)
|
||
**Зрелость: ВЫСОКАЯ популярность, СРЕДНЯЯ зрелость (Invariant acquired by Snyk 2025; Lasso open-source)**
|
||
|
||
- **Invariant Labs: MCP-scan** — два режима: пассивный `scan` (статически ищет tool poisoning / prompt injection в описаниях инструментов) и активный `mcp-scan proxy` (фоновый динамический слой, мониторит и логирует весь MCP-трафик). Guardrails покрывают tool calls/responses, PII/secrets detection, tool restrictions, custom policies. **Tool Pinning** (хэширование) ловит rug-pull атаки; cross-origin escalation → tool shadowing.
|
||
- **Invariant Guardrails** работает **out-of-band**: ingests execution traces + MCP server definitions → static information-flow analysis над ними, поднимает policy violations (unsafe tool-call sequences). Т.е. контроль отдельным слоем над трейсом, а не в loop.
|
||
- **Lasso MCP Gateway** (MIT, open source, апр 2025): proxy-and-orchestrator между LLM и другими MCP; перехватывает request/response, mask secrets/PII, блокирует prompt injection и command injection/RCE. Плагины: `basic` (secrets masking), `presidio` (PII), `lasso` (custom policy + injection + harmful content). Унифицированный интерфейс `get_metadata` / `run_tool`.
|
||
- Паттерн де-факто: **MCP gateway = привратник на сетевом слое**, независимый от агента, применяет фильтры к обеим сторонам трафика.
|
||
- Источник: https://invariantlabs-ai.github.io/docs/mcp-scan/ , https://www.agentpatternscatalog.org/landing/compositions/invariant-labs/ , https://github.com/lasso-security/mcp-gateway
|
||
|
||
## Подход 6. Guardrail-фреймворки (ML-слой поверх tool calls)
|
||
**Зрелость: ВЫСОКАЯ (Meta/Microsoft/NVIDIA — production, но акцент на content/инъекции, не на per-tool authz)**
|
||
|
||
- **LlamaFirewall (Meta)** — «policy engine», оркеструет сканеры: PromptGuard 2 (BERT-классификатор prompt injection), **AlignmentCheck** (аудит chain-of-thought рассуждений агента в реальном времени — ловит goal hijacking / indirect injection), CodeShield (статический анализ LLM-кода, 8 языков), regex/custom. Возвращает `ScanResult {decision, reason, score}`. Поддерживает `scan_replay` по трассам. Реально open source (4.4k★).
|
||
- **NeMo Guardrails (NVIDIA)** — rails (input/retrieval/dialog/execution/output), Colang flows, YAML. Явно есть **agentic security**: tool call validation (валидирует входы/выходы инструмента до/после вызова), интеграция с LangGraph. Библиотека+микросервис, конфиг переносим.
|
||
- **Guardrails AI** — validation-фреймворк (Hub валидаторов); в 2026 команда ушла в Harvey (сайт-леденящий), самостоятельный продукт фактически заморожен.
|
||
- **Prompt Security** — теперь часть **SentinelOne**; предлагает AI Gateway + open-source (ClawSec — integrity/drift detection skills, ps-fuzz — fuzzing промптов). Это скорее enterprise AI gateway, чем tool-level привратник.
|
||
- Граница: guardrail-фреймворки сильны на *semantic* рисках (инъекции, токсичность, PII), но они **не заменяют** детерминированную авторизацию tool calls.
|
||
- Источник: https://github.com/meta-llama/PurpleLlama/tree/main/LlamaFirewall , https://docs.nvidia.com/nemo/guardrails/ , https://www.prompt.security/
|
||
|
||
## Подход 7. Interception в агентских фреймворках (callbacks / middleware)
|
||
**Зрелость: ВЫСОКАЯ (first-class API в трёх крупных SDK)**
|
||
|
||
- **OpenAI Agents SDK**: tool guardrails выполняются на **каждой** guarded function-tool invocation (input до, output после), включая локальные MCP-инструменты. Tripwire-механизм: `.tripwire_triggered` → `Input/OutputGuardrailTripwireTriggered`. Есть `run_in_parallel` (быстро, но агент может успеть выполнить tool до отмены) vs blocking (расход до tool execution). Отдельно — sanitized placeholder `"Output withheld by an output guardrail."`.
|
||
- **Google ADK**: 6 типов callbacks, включая **Before Tool / After Tool**. Return `None` = продолжать, return объект = **override и skip** дефолтного поведения (жёсткий interception). Важный совет вендора: для security guardrails использовать **ADK Plugins**, а не callbacks (модульность).
|
||
- **LangChain**: `HumanInTheLoopMiddleware` — интерцепт tool calls через `after_model` hook + LangGraph `interrupt()`. Pause-Decide-Resume; решения `approve` / `edit` / `reject` / `respond`; настраивается `interrupt_on` (True/False/config) и **`when` predicate** (условный interrupt, напр. только записи вне `/workspace/`). Требует checkpointer (Postgres/Mongo в проде).
|
||
- Все три — это «in-harness» привратник: контрольный слой в самом рантайме агента, а не внешний сервис.
|
||
- Источник: https://openai.github.io/openai-agents-python/guardrails/ , https://google.github.io/adk-docs/callbacks/ , https://docs.langchain.com/oss/python/langchain/human-in-the-loop
|
||
|
||
## Подход 8. Jev / TypeSafe System One — typed evaluation как гейт
|
||
**Зрелость: НИЗКО-СРЕДНЯЯ (нишевый, молодой; community-репо 9–18★; сайты-спутники — community)**
|
||
|
||
- **Jev — это НЕ LLM и НЕ drop-in замена модели агента.** «System One model»: принимает `state` + набор **typed questions**, возвращает структурированные ответы — `choice` (с вероятностями по опциям), `score` (по рубрике), `noul` (0–1 для true/false утверждения). Не генерирует текст и не вызывает инструменты.
|
||
- Паттерн tool-approval: между *намерением* агента и *side effect*. Вопросы: `risk` (score 0–3), `injection` (noul), `exfiltration` (noul). Затем **порог и действие — в ВАШЕМ коде**: `if (risk.score >= 1.5 || injection.noul >= 0.8) deny(); if (risk.score >= 0.5 || exfiltration >= 0.5) askUser(); return allow();`
|
||
- Ключевая идея: судить **действие, а не payload** — JSON schema валидирует форму (`send_email` с валидным списком адресов), а Jev судит intent/scope/proportionality («уместны ли 214 получателей для этой задачи»). Порог варьируют по «blast radius» (read_only / single_target / external_many).
|
||
- Позиционирование: «strict-typed decisions by construction», замена хрупкому «верни JSON» промпту. Латентность — сотни миллисекунд на каждый tool call (предупреждают о накоплении). Вендор говорит: **один слой defense-in-depth**, не замена sandboxing/least privilege.
|
||
- Community-реализации: `leepokai/jev-guard` (18★, deny/ask/allow на каждый tool call + injection flagging), `win4r/jev-security-scan` (ревью skills/MCP кода), `jev-mcp` / `typesafe-mcp`.
|
||
- Источник: https://typesafe-jev.com/en/use-cases/tool-approval/ , https://jevmodel.org/use-cases/tool-call-guardrails/ , https://docs.typesafe.ai/introduction/coding-agents
|
||
|
||
---
|
||
|
||
## Итоговая карта: кто что даёт
|
||
|
||
| Слой | Примеры | Сильная сторона | Слабость |
|
||
|---|---|---|---|
|
||
| In-harness hooks/callbacks | Claude Code PreToolUse, ADK, LangChain HITL, OpenAI SDK | Глубокая интеграция, доступ к полному контексту | Привязан к рантайму; «сам агент» часто и решает |
|
||
| Policy engine | OPA/Rego, Cedar/AVP | Детерминизм, аудируемость, CI-тесты, развязка policy/code | Не понимает семантику; нужен адаптер под MCP |
|
||
| MCP proxy/gateway | Invariant MCP-scan, Lasso Gateway | Независим от агента, перехват трафика в обе стороны | Доп. hop; статически не видит намерение |
|
||
| Guardrail/scan | LlamaFirewall, NeMo, Prompt Security | Ловит инъекции/утечки/токсичность | ML-вероятностность; не замена авторизации |
|
||
| Typed evaluation | Jev / TypeSafe | Судит intent и blast radius, калиброванные вероятности | Молодой, нишевый, добавляет латентность на каждый вызов |
|
||
|
||
**Рекомендуемая композиция «привратника»:** deterministic policy engine (OPA для гибкости / Cedar для аудируемости) на сетевом MCP-proxy слое, дополненный ML-сканером для семантических рисков и typed-оценкой (Jev-подобной) для intent/blast-radius — с логированием каждого решения (probabilities + triggering rule) для апелляций и итерации правил.
|