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

Глава 9. Песочница выполнения и MCP как интеграционный контракт

Как читать эту главу

Здесь полезно держать в голове один конкретный переход:

  • агент уже выбрал возможность;
  • агент уже собирается пойти во внешний инструмент или адаптер;
  • платформа должна решить, через какой транспорт это вообще может быть исполнено и в каких границах.

Если этот переход не оформлен явно, песочница и MCP быстро превращаются в набор слов, а не в рабочую дисциплину выполнения.

1. Почему слой выполнения без песочницы быстро становится слишком доверчивым

В нашем сквозном кейсе поддержки это выглядит очень приземленно: агент уже решил проверить статус заявки или создать тикет через внешнюю систему. С этого момента вопрос стоит уже не “какой следующий умный шаг”, а “через какую границу система вообще разрешит этот шаг выполнить”.

Когда у агента появляется доступ к инструментам, следующая опасность почти всегда одна и та же: системная граница начинает размываться.

Агент уже умеет:

  • читать данные;
  • запускать операции;
  • обращаться к внешним сервисам;
  • получать ответы из непредсказуемой среды.

Если все это исполняется “как есть”, без изоляции и контрактов, платформа очень быстро получает проблемы:

  • инструмент может вернуть недоверенную полезную нагрузку в неожиданном формате;
  • интеграция может зависнуть или выйти за пределы ресурса;
  • побочный эффект может произойти вне ожидаемого пути политики;
  • один плохо спроектированный адаптер может утащить за собой весь рантайм.

Именно поэтому слой выполнения почти всегда нужен не только как маршрутизатор, но и как граница песочницы.

2. Песочница это не обязательно контейнер, а прежде всего режим ограничений

Когда говорят “песочница”, многие сразу думают о Docker, VM или отдельном процессе. Это возможные реализации, но архитектурно важнее другое: песочница задает пределы того, что может сделать возможность.

Хорошая песочница обычно ограничивает:

  • доступ к сети;
  • доступ к файловой системе;
  • доступ к секретам;
  • бюджет CPU и памяти;
  • разрешенные системные вызовы или режим выполнения;
  • время жизни операции.

То есть песочница отвечает на вопрос: “Что произойдет, если инструмент или адаптер поведет себя хуже, чем мы ожидали?”

Это не только безопасность. Это еще и контроль радиуса поражения.

2.1. Полезно различать уровни изоляции

На практике слово sandbox часто скрывает сразу несколько разных уровней.

  • logical isolation: проверки политик, контракты возможностей, списки разрешений;
  • process isolation: отдельный процесс, тайм-аут, лимиты ресурсов;
  • runtime isolation: отдельное исполняемое окружение, урезанная файловая система, ограниченный исходящий сетевой доступ, секреты по минимуму.

Это важно, потому что многие команды считают, что у них “есть песочница”, хотя на деле у них есть только первый уровень. Для операций чтения с низким риском этого иногда хватает, но для выполнения с высоким риском почти всегда нужна более жесткая граница исполнения.3

Хороший практический вопрос здесь такой: если возможность начнет вести себя хуже нормы, что именно ее остановит: логика, процесс или сама среда исполнения?

3. Нельзя считать внешнюю интеграцию просто функцией

Обычная ошибка выглядит так: внешний сервис оборачивается в функцию, и дальше агент видит его как обычный вызов.

Но реальная интеграция почти всегда:

  • нестабильнее локального кода;
  • хуже типизирована;
  • зависит от прав доступа и окружения;
  • может вернуть частичный или опасный результат;
  • имеет собственные задержки и лимиты запросов.

Поэтому полезнее относиться к интеграциям как к эндпоинтам возможностей с контрактом, а не как к “удобным вспомогательным методам”.

4. MCP полезен именно как контрактный слой

MCP удобен не потому, что это модное слово, а потому что он помогает явно описать границу между агентом и внешней возможностью.

В хорошем дизайне MCP дает несколько полезных вещей:

  • стандартизированный способ описывать инструменты и ресурсы;
  • отдельную серверную границу;
  • более явный жизненный цикл для подключения возможности;
  • возможность держать адаптеры вне основного рантайма агента;
  • понятную точку для проверок политик, логирования и изоляции.

Это особенно полезно, когда у тебя не один рантайм агента и не одна интеграция, а набор возможностей, которые хочется подключать системно, а не хаотично.

4.1. Полезно не путать MCP host, client и server

Вокруг MCP часто возникает лишняя путаница, потому что слова кажутся знакомыми, а роли у них довольно конкретные.

Полезно держать в голове такую картину:

  • host - это приложение или рантайм, который управляет сессией и решает, к каким возможностям вообще подключаться;
  • client - это протокольный компонент, который host создает для связи с конкретным MCP-сервером;
  • server - это граница, которая публикует инструменты, ресурсы и другие поверхности возможностей, а затем возвращает структурированный результат.

Из этого следуют две очень практичные вещи:

  • один host может одновременно держать несколько клиентов;
  • один рантайм агента может работать сразу с несколькими MCP-серверы, не смешивая их в один неразличимый комок интеграций.

Это кажется терминологической мелочью, но она полезна. MCP client — это не пользовательский интерфейс и не "сам агент". Это транспортный и контрактный слой между host и конкретной серверной границей.

MCP удобен как слой контракта между рантаймом и внешними возможностями

flowchart LR
    A["Рантайм агента"] --> B["Слой выполнения"]
    B --> C["Политика и валидация"]
    C --> D["MCP-клиент"]
    D --> E["MCP-сервер"]
    E --> F["Типизированный адаптер"]
    F --> G["Внешний API / система"]
    G --> F
    F --> E
    E --> D
    D --> B

5. Зачем выносить адаптеры из ядра рантайма

Как только MCP перестает быть одной-двумя вручную подключенными интеграциями, возникает следующий вопрос: кто вообще управляет MCP-поверхностью как частью платформы, а не как набором локальных удобств разработчиков? Здесь полезен недавний материал Cloudflare, потому что он смещает акцент с “умеет ли агент говорить по MCP” на “как команда открывает, утверждает, маршрутизирует и аудирует MCP-эндпоинты в масштабе”.1

Обычно это довольно быстро ведет к явному контуру управления MCP:

  • локальные экспериментальные MCP-серверы для экспериментов;
  • управляемые удаленные MCP-серверы для общих эксплуатационных возможностей;
  • слой обнаружения или портал для одобренных серверов;
  • контроль идентичности на границе доступа;
  • аудит и DLP-контроли вокруг самого пути MCP.

Это дает сразу несколько выгод:

  • сбои в интеграции меньше влияют на центральный рантайм;
  • проще ограничить сеть, секреты и файловую систему для каждой возможности;
  • легче обновлять или заменять адаптер без переписывания слоя оркестрации;
  • контракты становятся более явными;
  • проще тестировать возможность отдельно от логики агента.

Это особенно ценно, когда одни инструменты работают только на чтение, другие пишут во внешние системы, а третьи вообще выполняют код или shell-команды.

5.1. Корпоративный MCP почти всегда требует контура управления, а не только протокола

Именно здесь многие команды повторяют одну и ту же ошибку зрелости. Они стандартизируют протокол, но продолжают подключать MCP-серверы неформально: кто-то кидает эндпоинт в чат, кто-то копирует его в локальный конфиг, и очень быстро уже нельзя ответить, какие MCP-серверы вообще одобрены, какие только экспериментальные, а какие тихо обходят нормальный ревью-процесс.

Более зрелая модель относится к удаленному MCP как к части контура управления платформы:

  • платформа публикует одобренные MCP-эндпоинты через реестр или портал;
  • владелец каждой возможности обозначен явно;
  • аутентификация проходит через общий слой идентичности, а не прячется внутри каждого настольного клиента;
  • проверки политик и DLP могут наблюдать MCP-трафик как управляемую поверхность;
  • вывод MCP-эндпоинта из эксплуатации оформляется как обычное событие жизненного цикла.

Как только идентичность становится центральной частью этой модели, появляется еще один важный вопрос: кто именно авторизует действие MCP и в чьем контексте пользователя это происходит? Управляемая OAuth-граница полезна здесь тем, что не дает каждому MCP-серверу придумывать свою отдельную историю учетных данных.

Обычно это означает следующее:

  • делегирование пользователя выдается через управляемый слой идентичности;
  • токены короткоживущие и привязаны к конкретному субъекту;
  • MCP-сервер получает ограниченный доступ вместо широких постоянных секретов;
  • платформа может отозвать или ротировать доступ без переписывания каждого адаптера.

Эта же модель помогает понять, где локальный MCP все еще уместен: прототипирование, изолированные эксперименты или очень узкие локальные для команды рабочие процессы. Но вариант по умолчанию для общих бизнес-возможностей обычно должен быть таким: удаленный, управляемый, обнаруживаемый и аудируемый.

5.2. Теневой MCP — это новая версия проблемы теневых API

Когда MCP становится слишком легко подключать, у команды появляется новый вариант теневого IT: неучтенные MCP-серверы, через которые уже проходят реальные бизнес-действия, но владение, ревью и модель управления у них остаются неоформленными.1

У этого антипаттерна обычно быстро видны характерные признаки:

  • возможность потребляется из приватного фрагмента конфига, а не из одобренного каталога;
  • никто не может назвать владельца MCP-сервера;
  • авторизация живет в долгоживущих локальных секретах;
  • нет общего журнала аудита, показывающего, какой агент использовал какой MCP-эндпоинт;
  • платформенная команда узнает о сервере уже после инцидента.

Полезный платформенный чеклист здесь очень простой:

  • Этот MCP-сервер есть в одобренном реестре?
  • Кто отвечает за его жизненный цикл и реагирование на инциденты?
  • Какая граница идентичности защищает доступ?
  • Какой набор политик управляет операциями записи и подтверждениями?
  • Какая телеметрия доказывает, какой агент вызывал эндпоинт и в каком контексте решения?

Если на эти вопросы нет ответа, проблема уже не в том, что “интеграция плохо документирована”. Проблема в том, что платформа создала теневой путь возможностей вне собственной модели управления.

Следующий хороший вопрос здесь такой: может ли платформа восстановить цепочку авторизации для этого действия MCP? В зрелой модели оператор должен уметь восстановить:

  • какой пользователь или сервисный субъект делегировал доступ;
  • какой слой идентичности выпустил или проброкерил токен;
  • какой MCP-сервер принял эту делегированную область доступа;
  • какой запуск агента использовал эту авторизацию для выполнения действия.

Если эта цепочка не восстанавливается, аудируемость у платформы слабее, чем кажется по одной поверхности протокола.

5.3. Эфемерные песочницы лучше постоянных сред почти во всем

Еще одна полезная мысль из Google: для рискованных возможностей очень выгодно проектировать краткоживущие среды выполнения.3

Почему это обычно лучше:

  • меньше шансов, что состояние протечет между запусками;
  • проще ограничивать время жизни секретов и временных файлов;
  • легче объяснить очистку после выполнения;
  • ниже риск, что один грязный адаптер испортит следующую задачу.

Постоянные воркеры иногда выигрывают по задержке, но почти всегда проигрывают по изоляции и объяснимости. Поэтому позиция по умолчанию для выполнения с высоким риском обычно должна быть такой: сначала эфемерность, постоянство только по явной необходимости.

6. Stateful MCP меняет то, что рантайм вообще обязан отслеживать

Еще один полезный свежий сигнал дает AWS: как только MCP-клиенты и серверы начинают поддерживать паттерны взаимодействия с состоянием, MCP перестает быть просто stateless-конвертом инструмента и начинает вести себя как сессионный протокол рантайма.2

Это меняет контракт выполнения сразу в нескольких практических местах:

  • рантайм уже может хранить не только пользовательский запуск, но и отдельный session_id для MCP-взаимодействия;
  • возможность может присылать уведомления о прогрессе до финального результата;
  • сервер может запросить elicitation или дополнительный пользовательский ввод посередине потока;
  • истечение срока и повторная инициализация становятся нормальной частью жизненного цикла, а не редким крайним случаем;
  • телеметрия должна уметь объяснить не только, какой инструмент был вызван, но и какой экземпляр MCP-сессии несла этот шаг.

Если платформа продолжает считать MCP полностью stateless и после появления таких паттернов, то логика паузы и возобновления, маршрутизация подтверждения и реконструкция трассы быстро становятся намного сложнее, чем должны быть.

6.1. Stateless MCP и Stateful MCP требуют разных контрактов

Полезное различие здесь очень простое:

  • stateless MCP: один запрос, один ответ, почти без непрерывности сессии;
  • stateful MCP: ограниченная сессия взаимодействия с прогрессом, промежуточными запросами и возможностью возобновления или повторной инициализации.

Вторая модель почти всегда требует от платформы большего:

  • владения жизненным циклом сессии;
  • правил обработки истечения срока;
  • правил возобновления;
  • телеметрии для прогресса и событий elicitation;
  • полей политики, которые фиксируют, можно ли возобновленной сессии продолжать автоматически или нужно повторное подтверждение.

Это не делает stateless MCP устаревшим. Это лишь означает, что платформа не должна притворяться, будто оба режима эксплуатационно одинаковы.

6.2. Progress, elicitation и истечение срока — это события рантайма, а не транспортные мелочи

Полезный эксплуатационный урок из AWS направления stateful MCP состоит в том, что сложность не заканчивается на хранении дескриптора сессии.2 Более трудный вопрос в том, как рантайм должен реагировать, когда возможность шлет progress, запрашивает дополнительный ввод или истекает до завершения работы.

Это почти всегда заставляет платформу явно определить поведение хотя бы для четырех случаев:

  • progress_update: возможность все еще работает, и рантайм должен показать liveness, не считая вызов зависшим;
  • elicitation_requested: возможность не может продолжить, пока пользователь или оператор не даст дополнительный ввод;
  • session_expired: прежнюю сессию возможности уже нельзя безопасно возобновить;
  • reinitialized_session: рантайм осознанно поднял новую сессию возможности, но связал ее с тем же видимым пользователю запуском.

Это не мелкие транспортные детали. Именно они формируют, как дальше ведут себя подтверждение, телеметрия и реакция оператора.

6.3. Хороший MCP-контракт должен объяснять, что происходит после прерывания

Если stateful-возможность ставится на паузу посередине потока, платформа не должна импровизировать логику восстановления на месте.

Полезно явно зафиксировать хотя бы такие правила:

  • может ли та же сессия возможности продолжиться после подтверждения человеком;
  • приводит ли истечение срока к отмене запуска или повторной инициализации;
  • требует ли следующий шаг новой оценки политики;
  • сохраняет ли рантайм тот же видимый пользователю запуск, если сессия на стороне возможности была заменена;
  • как телеметрия связывает старую и новую сессии возможности при расследовании.

Без этих ответов команда может формально поддерживать stateful MCP, но все равно не сумеет объяснить, что реально произошло после прерывания.

7. Не все возможности требуют одинаковый уровень изоляции

Удобно разделить интеграции хотя бы на три класса:

  • возможности чтения с низким риском;
  • бизнес-действия со средним риском;
  • возможности выполнения с высоким риском.

Примеры:

  • read_kb или search_docs можно исполнять мягче;
  • create_ticket или update_crm_record требуют более строгих политик и аудита;
  • run_shell, exec_sql, deploy_job требуют самой жесткой песочницы и подтверждения.

Если ко всем инструментам применить одинаково мягкий профиль выполнения, платформа будет либо небезопасной, либо очень быстро столкнется с инцидентами по побочным эффектам.

8. Контракт возможности должен включать не только вход/выход

Часто схема инструмента описана неплохо, а вот эксплуатационный контракт нигде не зафиксирован. Но именно он часто критичен.

Полезно явно задавать:

  • режим аутентификации;
  • принадлежит ли доступ платформе или делегирован пользователем;
  • время жизни токена и правила обновления;
  • границы области доступа для каждой возможности;
  • что именно логируется про делегированную авторизацию;
  • что происходит, если делегированный доступ отзывают посередине сессии.

  • характер чтения или записи;

  • сетевая политика;
  • область секретов;
  • разрешенные среды;
  • бюджет тайм-аута;
  • политика повторов;
  • требование подтверждения;
  • правила логирования и редактирования.

Ниже пример такого профиля:

capabilities:
  search_docs:
    transport: mcp
    mode: read
    network: internal_only
    secrets: none
    timeout_seconds: 8
    approval: none
  create_ticket:
    transport: mcp
    mode: write
    network: internal_only
    secrets: service_account_helpdesk
    timeout_seconds: 15
    approval: manager_for_high_priority
    session_mode: stateful
    progress_events: true
    elicitation: manager_or_requester
    on_session_expiry: reinitialize_or_cancel
  run_shell:
    transport: sandboxed_exec
    mode: high_risk
    network: denied
    filesystem: workspace_only
    secrets: none
    timeout_seconds: 10
    approval: always

Это уже не просто описание функции. Это описание поведенческого контракта возможности.

9. Выполнение в песочнице должно возвращать не только вывод, но и факты выполнения

Если песочница возвращает только stdout или полезную нагрузку, ты теряешь половину ценности слоя изоляции.

Для расследования и управления полезно возвращать:

  • код завершения;
  • флаг тайм-аута;
  • сводку использования ресурсов;
  • неопределенность побочного эффекта;
  • отредактированные логи;
  • идентификатор решения политики.

Тогда слой выполнения может объяснить не просто “команда не сработала”, а более взрослое: “операция была прервана по тайм-ауту после 8 секунд, сеть была запрещена, побочный эффект не подтвержден”.

9.1. Исходящий сетевой доступ заслуживает собственного набора правил

Очень много инцидентов происходит не потому, что возможность “сломалась”, а потому, что она смогла уйти в неожиданное место.

Поэтому исходящий сетевой доступ полезно описывать не как частность песочницы, а как отдельную поверхность контракта:

  • denied;
  • internal_only;
  • allowlisted_external;
  • brokered_via_gateway.

Если это не зафиксировано явно, потом почти невозможно объяснить, почему конкретный инструмент внезапно сходил наружу, хотя формально “ничего не нарушал”.

Для платформы эксплуатационного уровня хороший вариант по умолчанию обычно такой:

  • внутренние инструменты только для чтения: internal_only;
  • адаптеры внешних API: allowlisted_external;
  • выполнение кода и shell-подобные инструменты: denied по умолчанию.

9.2. Манифест песочницы как контракт исполнения

Свежие документы OpenAI по Sandbox Agents добавляют к этой картине полезную практическую форму: песочницу стоит описывать не только словами “контейнер” или “изолированная среда”, а через явный Manifest, capabilities, permissions, записи workspace, snapshot и session state.4

Это хорошо ложится на контракты выполнения из этой главы. Для платформы важны как минимум четыре вопроса:

  • какие файлы, репозитории, mounts и environment попадают в стартовый workspace;
  • какие нативные возможности песочницы доступны: filesystem, shell, memory, skills, compaction;
  • какие permissions и run_as действуют для команд, правок и чтения файлов;
  • что происходит при продолжении: используется live sandbox_session, serialized session_state или fresh session из snapshot.

Такой манифест не заменяет слой политик. Он делает границу исполнения проверяемой: ревью может увидеть, что именно материализуется в workspace, какие права получает агент и можно ли безопасно возобновить или snapshot эту работу.

10. Простой кодовый пример диспетчеризации возможностей

Ниже каркас, который показывает саму идею: транспорт и профиль выполнения выбираются по контракту возможности, а не определяются логикой модели на лету.

from dataclasses import dataclass


@dataclass
class CapabilitySpec:
    name: str
    transport: str
    mode: str
    timeout_seconds: int


def dispatch_capability(spec: CapabilitySpec, args: dict) -> dict:
    if spec.transport == "mcp":
        return {"status": "success", "transport": "mcp", "capability": spec.name}
    if spec.transport == "sandboxed_exec" and spec.mode == "high_risk":
        return {"status": "approval_required", "capability": spec.name}
    return {"status": "validation_failure", "reason": "unsupported capability profile"}

Это простой пример, но он закрепляет правильную мысль: способ исполнения задается платформой, а не придумывается моделью каждый раз заново.

11. Частые ошибки

Теперь типовые проблемы повторяются уже на двух уровнях: на уровне отдельного адаптера и на уровне всего ландшафта MCP.

Типовые проблемы очень повторяемы:

  • возможность получает больше сетевого доступа, чем нужно;
  • секреты доступны слишком широкому набору адаптеров;
  • результат инструмента тащит сырые внешние полезные нагрузки в prompt;
  • тайм-аут есть, но неопределенность побочного эффекта не моделируется;
  • MCP-сервер добавили, но политики и аудит туда не дотянули;
  • песочница есть формально, но не ограничивает ничего важного.

Именно поэтому песочница не должна быть галочкой в чеклисте. Она должна быть частью модели выполнения.

12. Что сделать сразу

Сначала пройди по короткому списку и отдельно отметь все ответы «нет»:

  • Отделены ли адаптеры от ядра рантайма?
  • Есть ли профиль выполнения для каждой возможности?
  • Ограничены ли сеть, файловая система и секреты?
  • Ясно ли, какой уровень изоляции используется: логический, процессный или рантайм?
  • Явно ли описан транспорт: direct, MCP, sandboxed exec?
  • Понимает ли система, когда результат заслуживает доверия, а когда только частично доверенный?
  • Есть ли факты выполнения помимо бизнес-полезной нагрузки?
  • Используются ли эфемерные песочницы там, где есть выполнение с высоким риском?
  • Можно ли объяснить, почему возможность была разрешена именно в этом запуске?

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

13. Что делать дальше

Сначала зафиксируй профиль выполнения и границы изоляции, а потом переходи к повторам, лимитам запросов и границам отката.

Следующая естественная тема в этой части: идемпотентность, повторы, лимиты запросов и границы отката. После песочницы и контрактов возможностей именно она превращает модель выполнения в слой эксплуатационного уровня.