{"meta":{"title":"Петля агента","intro":"Как Copilot CLI обрабатывает пользовательское сообщение от начала до конца: от запроса до session.idle.","product":"GitHub Copilot","breadcrumbs":[{"href":"/ru/copilot","title":"GitHub Copilot"},{"href":"/ru/copilot/how-tos","title":"Инструкции"},{"href":"/ru/copilot/how-tos/copilot-sdk","title":"Второй пилот SDK"},{"href":"/ru/copilot/how-tos/copilot-sdk/features","title":"Возможности"},{"href":"/ru/copilot/how-tos/copilot-sdk/features/agent-loop","title":"Петля агента"}],"documentType":"article"},"body":"# Петля агента\n\nКак Copilot CLI обрабатывает пользовательское сообщение от начала до конца: от запроса до session.idle.\n\n<!-- markdownlint-disable GHD046 GHD005 -->\n\n<!-- Suppressed: GHD046 (outdated release terminology), GHD005 (hardcoded data variable) -->\n\n## Architecture\n\n![Диаграмма: Диаграмма, показывающая описанный процесс.](/assets/images/help/copilot/copilot-sdk/features-agent-loop-diagram-0.png)\n\n**SDK** — это транспортный слой: он отправляет ваш запрос в **Copilot CLI** по JSON-RPC и возвращает события обратно в приложение.\n**CLI** — это оркестратор, который запускает цикл использования агентных инструментов, выполняя один или несколько вызовов LLM API до завершения задачи.\n\n## Цикл использования инструментов\n\nКогда вы вызываете `session.send({ prompt })`, CLI входит в цикл:\n\n![Диаграмма: блок-схема, показывающая описанный процесс.](/assets/images/help/copilot/copilot-sdk/features-agent-loop-diagram-1.png)\n\nМодель видит **полную историю разговоров** по каждому звонку — системный запрос, пользовательское сообщение и все предыдущие вызовы и результаты.\n\n**Ключевые выводы:** Каждая итерация этого цикла — это ровно один вызов LLM API, видимый как одна `assistant.turn_start` / `assistant.turn_end` пара в журнале событий. Скрытых звонков нет.\n\n## Повороты — что это такое\n\n**Ход** — это один вызов LLM API и его последствия:\n\n1. CLI отправляет историю разговоров в LLM\n2. LLM отвечает (возможно, с помощью запросов инструментов)\n3. Если инструменты запрашивались, CLI их выполняет\n4. `assistant.turn_end` излучается\n\nОдно сообщение пользователя обычно приводит к **нескольким ходам**. Например, вопрос вроде «как работает X в этой кодовой базе?» может привести к следующему:\n\n| Повернуть            | Что делает модель                                    | toolRequests? |\n| -------------------- | ---------------------------------------------------- | ------------- |\n| 1                    | Вызовы `grep` и `glob` поиск по кодовой базе         |               |\n| ✅ Да                 |                                                      |               |\n| 2                    | Читает конкретные файлы на основе результатов поиска |               |\n| ✅ Да                 |                                                      |               |\n| 3                    | Читайте больше файлов для более глубокого контекста  |               |\n| ✅ Да                 |                                                      |               |\n| 4                    | Получает итоговый текстовый ответ                    |               |\n| ❌ Нет → концов петли |                                                      |               |\n\nМодель решает на каждом ходу, запрашивать ли дополнительные инструменты или давать окончательный ответ. Каждый звонок видит **полный накопленный контекст** (все предыдущие вызовы и результаты), чтобы принять обоснованное решение о том, достаточно ли у него информации.\n\n## Поток событий для многоходового взаимодействия\n\n![Диаграмма: блок-схема, показывающая описанный процесс.](/assets/images/help/copilot/copilot-sdk/features-agent-loop-diagram-2.png)\n\n## Кто запускает каждый ход?\n\n| Actor               | Ответственность                                                                                                  |\n| ------------------- | ---------------------------------------------------------------------------------------------------------------- |\n| **Ваше приложение** | Отправляет первоначальный запрос через `session.send()`                                                          |\n| **Copilot CLI**     | Запускает цикл использования инструментов — выполняет инструменты и возвращает результаты в LLM на следующий ход |\n| **LLM**             | Решает, запрашивать ли инструменты (продолжать цикл) или давать окончательный ответ (стоп)                       |\n| **Пакет SDK**       | Передаёт события; не управляет циклом                                                                            |\n\nCLI чисто механический: «модель запросила инструменты → выполнить → модель вызова снова».\n**Модель** принимает решение, когда остановиться.\n\n## `session.idle` и `session.task_complete`\n\nЭто два разных сигнала завершения с очень разными гарантиями:\n\n### `session.idle`\n\n* **Всегда излучается** , когда цикл использования инструмента заканчивается\n* **Эфемерный**: не сохраняется на диске, не воспроизводит при возобновлении сессии\n* Означает: «агент прекратил обработку и готов к следующему сообщению»\n* **Используйте** это как надёжный сигнал «готово»\n\nМетод SDK `sendAndWait()` ждёт этого события:\n\n```typescript\n// Blocks until session.idle fires\nconst response = await session.sendAndWait({ prompt: \"Fix the bug\" });\n```\n\n### `session.task_complete`\n\n* **Опционально излучается**: требует, чтобы модель явно сигнализировала\n* **Сохранено**: сохранено в журнал событий сессии на диске\n* Означает: «агент считает выполненную общую задачу»\n* Несёт дополнительное `summary` поле\n\n```typescript\nsession.on(\"session.task_complete\", (event) => {\n    console.log(\"Task done:\", event.data.summary);\n});\n```\n\n### Режим автопилота: CLI подталкивает к `task_complete`\n\nВ **режиме автопилота** (безголовая/автономная работа) CLI активно отслеживает, вызывала `task_complete`ли модель . Если цикл использования инструмента заканчивается без него, CLI вводит синтетическое пользовательское сообщение, подталкивающее модель:\n\n> *«Вы ещё не отметили задание как завершённое с помощью инструмента task\\_complete. Если вы планировали, прекратите планирование и начните внедрять. Ты не закончишь, пока полностью не выполнишь задание.»*\n\nЭто фактически запускает цикл использования инструмента — модель воспринимает подталкивание как сообщение нового пользователя и продолжает работать. Подталкивание также инструктует модель **не** вызывать `task_complete` преждевременно:\n\n* Не звоните, если у вас есть открытые вопросы — принимайте решения и продолжайте работать.\n* Не вызывайте её, если нашли ошибку — попробуйте её исправить\n* Не называйте её, если остались шаги — сначала выполните их\n\nЭто создаёт **двухуровневый механизм завершения** в автопилоте:\n\n1. Модель вызывает `task_complete` с резюме→ CLI `session.task_complete` излучает → выполнено\n2. Модель останавливается, не вызывая её, → CLI подталкивает модель → продолжает или вызывает `task_complete`\n\n### Почему `task_complete` бы не появиться\n\nВ **интерактивном режиме** (обычный чат) CLI не подталкивает к `task_complete`. Модель может полностью его пропустить. Распространенные причины:\n\n* **Разговорные вопросы и ответы**: модель отвечает на вопрос и просто останавливается — нет отдельной «задачи» для выполнения\n* **Дискреция модели**: модель генерирует итоговый текстовый ответ без вызова сигнала завершения задачи\n* **Прерванные сессии**: сессия заканчивается до того, как модель достигает точки завершения\n\nCLI всё равно излучает `session.idle` , потому что это механический сигнал (цикл завершился), а не семантический (модель считает, что всё сделано).\n\n### Какой из них следует использовать?\n\n| Сценарий использования                              | Сигнал |\n| --------------------------------------------------- | ------ |\n| «Жди, пока агент закончит обработку»                |        |\n| `session.idle`                                      |        |\n| ✅                                                   |        |\n|                                                     |        |\n| «Знать, когда выполнена задача по программированию» |        |\n| `session.task_complete` (лучшее усилие)             |        |\n| «Тайм-аут/обработка ошибок»                         |        |\n| `session.idle`                                      |        |\n\n*\n\n`session.error`\n✅\n|\n\n## Подсчёт вызовов LLM\n\nКоличество `assistant.turn_start` / `assistant.turn_end` пар в журнале событий равно общему числу LLM API вызовов. Нет скрытых требований к планированию, оценке или проверке завершения.\n\nЧтобы проверить количество ходов за сессию:\n\n```bash\n# Count turns in a session's event log\ngrep -c \"assistant.turn_start\" ~/.copilot/session-state/<sessionId>/events.jsonl\n```\n\n## Дополнительные материалы\n\n* [События потоковых сессий](/ru/copilot/how-tos/copilot-sdk/features/streaming-events): Полный справочник на уровне поля для каждого типа событий\n* [АВТОТИТРЫ](/ru/copilot/how-tos/copilot-sdk/features/session-persistence): Как сохраняются и возобновляются сессии\n* [Работа с крючками](/ru/copilot/how-tos/copilot-sdk/features/hooks): Перехват событий в цикле (разрешения, инструменты)"}