Amiga
Оглавление курса · урок 2 из 24

Модуль 1 · Как устроен агент · урок 2 из 24

Агентный цикл Codex изнутри

Чтобы строить среду для агента, надо понимать, что происходит между вашим промптом и готовым диффом. В Codex это не магия, а довольно простой цикл, описанный самими инженерами OpenAI и открытый в исходниках. В уроке разберём его по шагам и выведем из устройства цикла конкретные требования к вашему harness.

Словарь: тред, ход, элемент

В статье Селии Чен «Unlocking the Codex harness» (OpenAI, 4 февраля 2026) три примитива App Server — протокола, на котором работают все поверхности Codex:

  • Item (элемент) — атомарная типизированная единица: сообщение пользователя, ответ агента, выполнение команды, правка файла, запрос одобрения, вызов MCP-инструмента. У каждого есть жизненный цикл «начат → дельты → завершён».
  • Turn (ход) — единица работы агента, которую запускает ввод пользователя.
  • Thread (тред) — долговечный контейнер сессии. Его можно возобновить, форкнуть, архивировать.

Тот же harness работает в CLI, IDE-расширении, ChatGPT desktop app и облаке. Практическое следствие: всё, что вы вложили во внешний harness (AGENTS.md, навыки, хуки, скрипты проверки), работает на любой поверхности, включая codex exec в CI.

Цикл по шагам

Майкл Болин в статье «Unrolling the Codex agent loop» (23 января 2026) описывает цикл так:

  1. Ввод пользователя превращается в промпт — как именно, разберём в следующем уроке.
  2. Инференс: модель либо даёт финальный ответ, либо просит вызвать инструмент.
  3. Harness выполняет вызов и дописывает вывод в промпт.
  4. Модель опрашивается снова — с полной историей.
  5. Ход заканчивается, только когда модель выдала сообщение ассистента.

За один ход могут пройти сотни вызовов инструментов. Контекстное окно учитывает и вход, и выход, поэтому управление контекстом — прямая обязанность harness, а не модели.

text
ввод → [промпт] → инференс ─┬─ сообщение ассистента → конец хода
                            └─ вызов инструмента → исполнение → вывод в промпт ─┐
                 ↑                                                              │
                 └──────────────────────────────────────────────────────────────┘

Инференс: stateless по замыслу

Codex CLI ходит в Responses API по HTTP. Эндпоинт зависит от входа: через ChatGPT, по API-ключу, локально через --oss или через облачного провайдера.

Ключевое решение, по Болину: Codex не использует previous_response_id, то есть не просит сервер помнить разговор. Каждый запрос несёт всю историю целиком. Так запросы остаются полностью stateless и совместимы с Zero Data Retention. Цена — объём JSON за разговор растёт квадратично. Компенсирует это кэш промптов: при попаданиях стоимость сэмплирования растёт линейно. Кэш работает только при точном совпадении префикса — отсюда целая дисциплина, о ней в уроке о сборке промпта.

Инструменты и граница песочницы

Модели передаётся список инструментов. По Болину, в нём shell-инструмент, встроенный инструмент плана update_plan, инструменты Responses API вроде веб-поиска и инструменты MCP-серверов с именами вида mcp__<server>__<tool>.

Самая недооценённая деталь: песочница Codex распространяется только на его shell-инструмент. MCP-инструменты Codex не изолирует, за свои ограничения они отвечают сами. Если вы подключили MCP-сервер с доступом к базе или GitLab API, права этого сервера и есть ваша граница безопасности, а не sandbox_mode.

Наш вывод. При проектировании harness считайте каждый MCP-сервер отдельной поверхностью атаки: токены с минимальными правами, read-only там, где хватает чтения, отдельные ключи для агента. Подробнее о модели безопасности — в курсе для техдиров, урок «Модель безопасности».

Вывод инструментов — это ваш контекст

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

Значит, качество датчиков определяется не только тем, что они проверяют, но и тем, как они это сообщают:

  • PHPUnit или Playwright с подробным репортером выдаёт тысячи строк, из которых важны три. Ошибка может оказаться ровно в вырезанной середине.
  • Линтер, который пишет «нарушение правила 47», заставляет агента искать правило. Линтер, который пишет «вынесите запрос в репозиторий модели, см. docs/architecture.md», сразу даёт исправление. Этот приём подробно разобран в уроке об инвариантах.

Практичный шаблон — отдельные «тихие» команды для агента в Makefile или composer-скриптах: короткий вывод, но честный код выхода. Обрезать вывод через простой | tail нельзя: код выхода станет кодом tail, и падение тестов превратится в успех.

makefile · Makefile
# Команды для агента: короткий вывод, код выхода сохраняется
test-agent:
	@vendor/bin/phpunit --no-progress --colors=never > .agent-test.log 2>&1; s=$$?; tail -n 60 .agent-test.log; exit $$s

e2e-agent:
	@npx playwright test --reporter=line > .agent-e2e.log 2>&1; s=$$?; tail -n 80 .agent-e2e.log; exit $$s

Где человек и harness вмешиваются в цикл

Цикл не закрытый. Точки вмешательства:

  • Одобрения. Протокол App Server двунаправленный: сервер сам отправляет клиенту запрос на одобрение и ставит ход на паузу до ответа.
  • Steer и queue. В CLI Enter во время работы добавляет указание в текущий ход, Tab ставит сообщение в очередь на следующий.
  • Хуки. События PreToolUse, PostToolUse, Stop, PreCompact и другие позволяют детерминированно проверить или заблокировать действие. Это программная часть harness, которая не зависит от того, «послушалась» ли модель. Настройка — в уроке о хуках.

Что из этого следует для внешнего harness

Наши выводы из устройства цикла:

  1. Ход заканчивает модель. Нет внешнего критерия — агент остановится, когда сочтёт работу сделанной. Поэтому «готово» надо определять явно и проверяемо: команда, которая должна пройти, поведение, которое должно наблюдаться.
  2. Каждый шаг стоит контекста. Шумный инструмент обходится дороже, чем кажется: он ухудшает все следующие шаги хода.
  3. Граница безопасности — shell. Всё, что подключено мимо shell, нужно ограничивать отдельно.
  4. Инвестиции переносимы. Один harness на все поверхности: то, что настроено для CLI, работает в облаке и в CI.

Попробуйте сами

10–15 мин на рабочем месте
  1. Посмотрите на цикл глазами программы. В своём репозитории выполните и посчитайте, каких элементов больше всего:
bash
codex exec --json "Найди, где в проекте настраивается подключение к базе, и кратко опиши" \
  | jq -r 'select(.type=="item.completed") | .item.type' | sort | uniq -c
  1. Найдите в выводе (codex exec --json ... > run.jsonl) самую длинную команду по объёму вывода. Подумайте, нужна ли агенту «тихая» версия этой команды, и добавьте её в Makefile или composer.json.
  2. Перечислите подключённые MCP-серверы (codex mcp list или /mcp в TUI) и для каждого запишите, какие права у его токена. Это и есть ваша граница безопасности за пределами песочницы.

Коротко

  • Тред → ходы → элементы; ход заканчивается сообщением ассистента.
  • Codex stateless: каждый запрос несёт всю историю, выручает кэш префикса.
  • Песочница покрывает только shell; MCP-серверы ограничивайте сами.
  • Вывод инструментов — главный потребитель контекста; датчики должны говорить коротко и по делу.
  • «Готово» определяет модель, если вы не определили его проверяемо.
Отметка хранится только в вашем браузере
Хотите связаться с владельцем
компании напрямую?
Дмитрий Тарасов
Дмитрий Тарасов
СЕО

НАПИСАТЬ

Написать в MAX