Назад в блог

Code Mode для MCP: как выполнять вызовы из кода и сохранять контроль доступа

Практическое руководство по Code Mode для MCP: поиск инструментов, обработка данных в sandbox, права на каждый вызов, аудит и план внедрения.

Иллюстрация к материалу: Code Mode для MCP: как выполнять вызовы из кода и сохранять контроль доступа

Code Mode для MCP — подход, при котором AI-агент пишет короткую программу, вызывающую доступные инструменты, вместо того чтобы отдельно обсуждать с моделью каждый промежуточный вызов. Программа может получить страницы данных, отфильтровать записи и вернуть компактный результат. MCP при этом остаётся способом взаимодействия с инструментами, а код становится способом собрать их в рабочую процедуру.

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

Разберём архитектуру на учебном сценарии подготовки сводки по задачам. Материал основан на первичных источниках, проверенных 6 октября 2026 года. Примеры API, лимиты и политика ниже иллюстративны: это не готовая конфигурация Codenik и не обещание одинаковой экономии для всех моделей и задач.

Что изменилось в работе с большим каталогом инструментов

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

Anthropic в материале Code execution with MCP описывает загрузку инструментов по необходимости и обработку промежуточных данных в среде исполнения. Cloudflare в статье Code Mode показывает вариант с поиском операций и выполнением кода против типизированного API. Это реализации общего принципа, а не единый обязательный режим протокола MCP.

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

Полезная постановка вопроса для команды: какие промежуточные данные действительно должны пройти через модель? Если агенту нужен итог по просроченным задачам, модель не обязана читать каждую завершённую задачу. Но если требуется смысловой анализ описаний, часть содержания всё равно придётся передать модели с подходящими ограничениями.

Чем Code Mode отличается от произвольного shell

Выполнение кода не обязано означать доступ к терминалу машины. Для корпоративного сценария удобнее среда с узкими возможностями: вычисления, временная память и разрешённые функции SDK. Файловая система, сеть и запуск процессов выдаются отдельно, если действительно нужны, а не появляются вместе с правом написать цикл.

Промпт «не читай секреты» не создаёт такой границы. Границу создаёт исполнитель, который не предоставляет секреты программе, и брокер вызовов, который не принимает запрещённые операции. Если код может напрямую обращаться в сеть, он способен обойти удобный SDK и его журнал. Поэтому модель возможностей среды нужно рассматривать отдельно от удобства синтаксиса.

Сравните два интерфейса. Первый получает JavaScript и исполняет его в процессе приложения с доступом к окружению. Второй получает программу в изолированном runtime, где доступны только вычисления и проксированные вызовы инструментов. У обоих на экране может быть одна кнопка «execute», но последствия и доказательства контроля существенно различаются.

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

Учебный сценарий: сводка по задачам без лишних данных

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

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

Важная деталь — полнота выборки. Если третья страница недоступна, нельзя вернуть уверенный итог «в проекте две просроченные задачи». Нужно обозначить частичный результат и границы просмотренного набора. Компактность ответа не должна скрывать пропущенные записи. Это особенно важно, когда сводка используется для управленческого решения.

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

const summary = { overdue: [], unassigned: [], scanned: 0 };
let cursor = undefined;
let complete = false;

for (let pageNumber = 0; pageNumber < limits.maxPages; pageNumber++) {
  const page = await tools.tasks.list({
    project: "approved-project",
    fields: ["id", "status", "dueAt", "owner"],
    cursor,
  });
  for (const task of page.items) {
    summary.scanned++;
    if (isOverdue(task, clock.now)) summary.overdue.push(task.id);
    if (!task.owner) summary.unassigned.push(task.id);
  }
  if (!page.nextCursor) {
    complete = true;
    break;
  }
  cursor = page.nextCursor;
}
return { ...summary, complete };

Лимит страниц защищает от бесконечного обхода, а поле complete не даёт принять ограниченный обход за полный. Для реального проекта добавьте ограничения размера результата и обработку ошибок. Текущую дату задаёт доверенная среда, иначе результаты сравнения сроков трудно воспроизводить.

Для отчёта руководителю полезно заранее решить, как показывать частичный результат. Например, сводка содержит количество прочитанных задач и отметку, что оставшиеся страницы не обработаны из-за отказа API. Не выдавайте число найденных просрочек за число просрочек во всём проекте. Если дальнейшее чтение невозможно, сохраните курсор и версию входной выборки либо начните новую выборку по явным правилам. Сам курсор не гарантирует неизменность данных между запросами: это свойство нужно проверить у конкретного API. Такой контракт делает короткий ответ честным и позволяет оператору решить, стоит ли продолжить обработку позже.

Поиск инструментов и проверка схем

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

Поиск по каталогу тоже ограничивается правами. Нет смысла показывать агенту полный административный API, если задача разрешает только чтение одного проекта. Скрытие схем уменьшает ненужный контекст, однако само по себе не является контролем доступа. Запрет должен срабатывать и при прямом вызове операции, название которой агент угадал.

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

В процессе разработки полезен режим, где программа может читать схемы и строить план без права вызвать рабочие операции. Затем план проверяется на учебных данных. Это даёт возможность увидеть ошибочные предположения до выдачи доступа. Такой режим нужно реализовать технически: просьба к модели «пока только планируй» не запрещает доступный вызов.

Где проверять права на вложенные вызовы

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

Например, пользователь разрешил чтение задач проекта A. Скрипт передал проект B. Брокер должен отклонить запрос, даже если схема аргументов валидна и пользователь в принципе состоит в обеих командах. Для конкретной задачи может быть задана более узкая область работы, чем все полномочия пользователя.

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

Также продумайте поведение при отказе. Программа не должна автоматически искать альтернативный инструмент, чтобы добиться того же запрещённого результата. Возвращайте структурированную причину и завершайте соответствующую ветку. Агент может объяснить ограничение пользователю, но изменение полномочий остаётся отдельным управляемым действием.

Sandbox, секреты и границы вывода

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

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

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

Локальная обработка данных может сократить объём, который получает модель, но не отменяет обязательств по хранению и доступу внутри исполнителя. Если программа видела персональные данные, нужно понимать, где они находились, сколько жили и кто мог посмотреть отладочный снимок. Уменьшение контекста и защита данных — связанные, но разные результаты.

Лимиты вычислений и вызовов инструментов

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

Параллельное чтение может ускорить процедуру, но не должно перегружать корпоративные API. Ограничение внутри скрипта недостаточно: ошибочный код способен его обойти. Брокер контролирует число одновременных операций и общий бюджет задания. Для нескольких пользователей нужен также общий лимит подключения, чтобы их программы не конкурировали без ограничений.

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

При достижении лимита возвращайте доступный результат с признаком неполноты, если такой ответ разрешён сценарием. Для действий с побочными эффектами дополнительно запишите, что точно было выполнено, что не начиналось и что требует сверки. Слово «timeout» без этой информации не помогает безопасно продолжить работу.

Изменения данных, подтверждение и идемпотентность

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

Подтверждение полезно связывать с конкретной версией плана. Если после согласия программа расширила выборку или поменяла значения, прежнее подтверждение уже не описывает действие. Проверку такого соответствия должен выполнять доверенный компонент. Текст «пользователь согласен» внутри сгенерированного кода не является подтверждением.

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

Массовая операция не становится транзакцией только потому, что находится в одном execute. Первый API-вызов мог завершиться, второй — отказать. Пользователь должен видеть фактический частичный результат и предусмотренный способ восстановления. Для этой темы полезно отдельное руководство по идемпотентности инструментов агентов.

Аудит: видеть программу и её реальные действия

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

Программу полезно сохранять как артефакт с хешем. Так можно отличить два запуска с похожим названием, но разным поведением. Для sensitive данных продумайте, какие константы могли попасть в код: иногда модель вставляет полученный текст прямо в исходник. Хранение артефакта тоже требует правил доступа и срока удаления.

В журнале результата отделяйте вычисленный итог от доказательств обращения к системе. Скрипт может вернуть строку «все задачи обновлены», хотя ни один API-вызов не состоялся. Достоверность изменения определяется ответами инструментов и проверкой состояния, а не завершающим текстом программы.

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

Как измерить пользу без рекламных процентов

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

Измеряйте токены входа и выхода, время до результата, число API-вызовов, размер промежуточных данных и частоту ошибок. Не забудьте стоимость исполнения sandbox и сопровождения SDK. Если каталог часто меняется, генерация и проверка схем могут стать существенной частью общей стоимости решения.

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

Публикуйте собственные измерения с условиями, а не переносите цифры поставщика на свою инфраструктуру. Даже если в демонстрации каталог помещается в небольшой контекст, результат зависит от содержимого схем, числа нужных операций и объёма данных. До собственного теста корректная формулировка — «подход может уменьшить передачу промежуточных данных».

План внедрения и контрольные испытания

Начните с одного читающего сценария и одного подключения. Для сводки по задачам ограничьте проект, поля и время жизни данных. Постройте SDK только для выбранных операций. Это позволяет проверить модель доступа на понятном объёме, не превращая первый пилот в перенос всего корпоративного API.

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

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

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

Где в архитектуре нужен Codenik

Codenik рассматривается как управляемый слой доступа к корпоративным системам для AI-агентов. В обсуждении Code Mode важно сохранить разделение: исполнитель отвечает за вычисления, а слой доступа — за полномочия на вызовы, работу с подключениями, секретами и аудитом. Эти роли могут принадлежать разным компонентам.

Перед интеграцией с Codenik сформулируйте проверяемые требования к конкретной поставке: каждый вложенный вызов получает актуальное решение политики, секрет не передаётся программе, результат связан с заданием, запрещённая область не становится доступной через универсальный execute. Поддержку выбранного runtime и схем подтверждения нужно проверять отдельно.

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

Критерий хорошей архитектуры — возможность показать конкретный путь отказа и конкретный путь разрешённого действия. Общее обещание «код работает в sandbox» описывает только часть системы. Для общей картины полезно сравнить этот подход с архитектурой MCP-шлюза.

FAQ: когда выбирать Code Mode

Нужен ли Code Mode для каждого инструмента? Нет. Простая адресная операция часто удобнее как отдельный вызов с небольшой схемой. Code Mode полезно рассматривать для процедур, где есть последовательность, фильтрация, пагинация или вычисления над промежуточными ответами. Выбор проверяется на собственном наборе задач.

Будет ли код всегда дешевле прямых вызовов? Нет. Генерация программы, ошибки, повторные попытки и стоимость runtime могут изменить итог. Измеряйте весь путь до правильного результата. Универсальную цифру экономии нельзя вывести из размера определения execute или из чужого демонстрационного примера.

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

Заменяет ли sandbox управление правами? Нет. Изоляция ограничивает возможности исполнителя, а политика доступа определяет разрешённые действия в корпоративных системах. Нужны оба слоя. Сначала проверьте читающий сценарий, затем отдельно спроектируйте запись, подтверждения и восстановление после неизвестного результата.

Рабочая цель внедрения — сократить ненужные промежуточные данные и сделать процедуру воспроизводимой. Сохраните эту цель в приёмке: программа должна дать проверяемый итог, не расширить область доступа и не скрыть частичный сбой за красивым финальным ответом.

Источники

Дата проверки: 6 октября 2026 года. Учебный SDK, сценарии тестирования и архитектурные требования сформулированы автором. Они не являются интерфейсом конкретной реализации или обещанием функций Codenik.