# Петля агента

Как Copilot CLI обрабатывает пользовательское сообщение от начала до конца: от запроса до session.idle.

<!-- markdownlint-disable GHD046 GHD005 -->

<!-- Suppressed: GHD046 (outdated release terminology), GHD005 (hardcoded data variable) -->

## Architecture

![Диаграмма: Диаграмма, показывающая описанный процесс.](/assets/images/help/copilot/copilot-sdk/features-agent-loop-diagram-0.png)

**SDK** — это транспортный слой: он отправляет ваш запрос в **Copilot CLI** по JSON-RPC и возвращает события обратно в приложение.
**CLI** — это оркестратор, который запускает цикл использования агентных инструментов, выполняя один или несколько вызовов LLM API до завершения задачи.

## Цикл использования инструментов

Когда вы вызываете `session.send({ prompt })`, CLI входит в цикл:

![Диаграмма: блок-схема, показывающая описанный процесс.](/assets/images/help/copilot/copilot-sdk/features-agent-loop-diagram-1.png)

Модель видит **полную историю разговоров** по каждому звонку — системный запрос, пользовательское сообщение и все предыдущие вызовы и результаты.

**Ключевые выводы:** Каждая итерация этого цикла — это ровно один вызов LLM API, видимый как одна `assistant.turn_start` / `assistant.turn_end` пара в журнале событий. Скрытых звонков нет.

## Повороты — что это такое

**Ход** — это один вызов LLM API и его последствия:

1. CLI отправляет историю разговоров в LLM
2. LLM отвечает (возможно, с помощью запросов инструментов)
3. Если инструменты запрашивались, CLI их выполняет
4. `assistant.turn_end` излучается

Одно сообщение пользователя обычно приводит к **нескольким ходам**. Например, вопрос вроде «как работает X в этой кодовой базе?» может привести к следующему:

| Повернуть            | Что делает модель                                    | toolRequests? |
| -------------------- | ---------------------------------------------------- | ------------- |
| 1                    | Вызовы `grep` и `glob` поиск по кодовой базе         |               |
| ✅ Да                 |                                                      |               |
| 2                    | Читает конкретные файлы на основе результатов поиска |               |
| ✅ Да                 |                                                      |               |
| 3                    | Читайте больше файлов для более глубокого контекста  |               |
| ✅ Да                 |                                                      |               |
| 4                    | Получает итоговый текстовый ответ                    |               |
| ❌ Нет → концов петли |                                                      |               |

Модель решает на каждом ходу, запрашивать ли дополнительные инструменты или давать окончательный ответ. Каждый звонок видит **полный накопленный контекст** (все предыдущие вызовы и результаты), чтобы принять обоснованное решение о том, достаточно ли у него информации.

## Поток событий для многоходового взаимодействия

![Диаграмма: блок-схема, показывающая описанный процесс.](/assets/images/help/copilot/copilot-sdk/features-agent-loop-diagram-2.png)

## Кто запускает каждый ход?

| Actor               | Ответственность                                                                                                  |
| ------------------- | ---------------------------------------------------------------------------------------------------------------- |
| **Ваше приложение** | Отправляет первоначальный запрос через `session.send()`                                                          |
| **Copilot CLI**     | Запускает цикл использования инструментов — выполняет инструменты и возвращает результаты в LLM на следующий ход |
| **LLM**             | Решает, запрашивать ли инструменты (продолжать цикл) или давать окончательный ответ (стоп)                       |
| **Пакет SDK**       | Передаёт события; не управляет циклом                                                                            |

CLI чисто механический: «модель запросила инструменты → выполнить → модель вызова снова».
**Модель** принимает решение, когда остановиться.

## `session.idle` и `session.task_complete`

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

### `session.idle`

* **Всегда излучается** , когда цикл использования инструмента заканчивается
* **Эфемерный**: не сохраняется на диске, не воспроизводит при возобновлении сессии
* Означает: «агент прекратил обработку и готов к следующему сообщению»
* **Используйте** это как надёжный сигнал «готово»

Метод SDK `sendAndWait()` ждёт этого события:

```typescript
// Blocks until session.idle fires
const response = await session.sendAndWait({ prompt: "Fix the bug" });
```

### `session.task_complete`

* **Опционально излучается**: требует, чтобы модель явно сигнализировала
* **Сохранено**: сохранено в журнал событий сессии на диске
* Означает: «агент считает выполненную общую задачу»
* Несёт дополнительное `summary` поле

```typescript
session.on("session.task_complete", (event) => {
    console.log("Task done:", event.data.summary);
});
```

### Режим автопилота: CLI подталкивает к `task_complete`

В **режиме автопилота** (безголовая/автономная работа) CLI активно отслеживает, вызывала `task_complete`ли модель . Если цикл использования инструмента заканчивается без него, CLI вводит синтетическое пользовательское сообщение, подталкивающее модель:

> *«Вы ещё не отметили задание как завершённое с помощью инструмента task\_complete. Если вы планировали, прекратите планирование и начните внедрять. Ты не закончишь, пока полностью не выполнишь задание.»*

Это фактически запускает цикл использования инструмента — модель воспринимает подталкивание как сообщение нового пользователя и продолжает работать. Подталкивание также инструктует модель **не** вызывать `task_complete` преждевременно:

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

Это создаёт **двухуровневый механизм завершения** в автопилоте:

1. Модель вызывает `task_complete` с резюме→ CLI `session.task_complete` излучает → выполнено
2. Модель останавливается, не вызывая её, → CLI подталкивает модель → продолжает или вызывает `task_complete`

### Почему `task_complete` бы не появиться

В **интерактивном режиме** (обычный чат) CLI не подталкивает к `task_complete`. Модель может полностью его пропустить. Распространенные причины:

* **Разговорные вопросы и ответы**: модель отвечает на вопрос и просто останавливается — нет отдельной «задачи» для выполнения
* **Дискреция модели**: модель генерирует итоговый текстовый ответ без вызова сигнала завершения задачи
* **Прерванные сессии**: сессия заканчивается до того, как модель достигает точки завершения

CLI всё равно излучает `session.idle` , потому что это механический сигнал (цикл завершился), а не семантический (модель считает, что всё сделано).

### Какой из них следует использовать?

| Сценарий использования                              | Сигнал |
| --------------------------------------------------- | ------ |
| «Жди, пока агент закончит обработку»                |        |
| `session.idle`                                      |        |
| ✅                                                   |        |
|                                                     |        |
| «Знать, когда выполнена задача по программированию» |        |
| `session.task_complete` (лучшее усилие)             |        |
| «Тайм-аут/обработка ошибок»                         |        |
| `session.idle`                                      |        |

*

`session.error`
✅
|

## Подсчёт вызовов LLM

Количество `assistant.turn_start` / `assistant.turn_end` пар в журнале событий равно общему числу LLM API вызовов. Нет скрытых требований к планированию, оценке или проверке завершения.

Чтобы проверить количество ходов за сессию:

```bash
# Count turns in a session's event log
grep -c "assistant.turn_start" ~/.copilot/session-state/<sessionId>/events.jsonl
```

## Дополнительные материалы

* [События потоковых сессий](/ru/copilot/how-tos/copilot-sdk/features/streaming-events): Полный справочник на уровне поля для каждого типа событий
* [АВТОТИТРЫ](/ru/copilot/how-tos/copilot-sdk/features/session-persistence): Как сохраняются и возобновляются сессии
* [Работа с крючками](/ru/copilot/how-tos/copilot-sdk/features/hooks): Перехват событий в цикле (разрешения, инструменты)