sidebar_position: 3 title: "Agent Loop Internals" description: "Detailed walkthrough of AIAgent execution, API modes, tools, callbacks, and fallback behavior" lang: ru


Внутреннее устройство цикла агента

Основным механизмом оркестровки является класс AIAgent run_agent.py — примерно 13 700 строк, которые обрабатывают все: от быстрой сборки до отправки инструментов и переключения провайдера при сбое.

Основные обязанности

AIAgent несет ответственность за:

Две точки входа

# Simple interface — returns final response string
response = agent.chat("Fix the bug in main.py")

# Full interface — returns dict with messages, metadata, usage stats
result = agent.run_conversation(
    user_message="Fix the bug in main.py",
    system_message=None,           # auto-built if omitted
    conversation_history=None,      # auto-loaded from session if omitted
    task_id="task_abc123"
)

chat() — это тонкая оболочка run_conversation(), которая извлекает поле final_response из результирующего словаря.

Режимы API

Hermes поддерживает три режима выполнения API, определяемые выбором поставщика, явными аргументами и эвристикой базового URL-адреса:

Режим API Используется для Тип клиента
chat_completions Конечные точки, совместимые с OpenAI (OpenRouter, пользовательские, большинство поставщиков) openai.OpenAI
codex_responses Кодекс OpenAI/API ответов openai.OpenAI с форматом ответов
anthropic_messages API собственных антропных сообщений anthropic.Anthropic через адаптер

Режим определяет, как форматируются сообщения, как структурируются вызовы инструментов, как анализируются ответы и как работает кэширование/потоковая передача. Все три используют один и тот же внутренний формат сообщений (диктанты role/content/tool_calls в стиле OpenAI) до и после вызовов API.

Порядок разрешения режимов: 1. Явный аргумент конструктора api_mode (наивысший приоритет). 2. Обнаружение конкретного поставщика (например, поставщик anthropicanthropic_messages) 3. Базовая эвристика URL-адресов (например, api.anthropic.comanthropic_messages) 4. По умолчанию: chat_completions.

Повернуть жизненный цикл

Каждая итерация цикла агента следует следующей последовательности:

run_conversation()
  1. Generate task_id if not provided
  2. Append user message to conversation history
  3. Build or reuse cached system prompt (prompt_builder.py)
  4. Check if preflight compression is needed (>50% context)
  5. Build API messages from conversation history
     - chat_completions: OpenAI format as-is
     - codex_responses: convert to Responses API input items
     - anthropic_messages: convert via anthropic_adapter.py
  6. Inject ephemeral prompt layers (budget warnings, context pressure)
  7. Apply prompt caching markers if on Anthropic
  8. Make interruptible API call (_interruptible_api_call)
  9. Parse response:
     - If tool_calls: execute them, append results, loop back to step 5
     - If text response: persist session, flush memory if needed, return

Формат сообщения

Все сообщения используют внутренний формат, совместимый с OpenAI:

{"role": "system", "content": "..."}
{"role": "user", "content": "..."}
{"role": "assistant", "content": "...", "tool_calls": [...]}
{"role": "tool", "tool_call_id": "...", "content": "..."}

Содержимое рассуждений (из моделей, поддерживающих расширенное мышление) хранится в assistant_msg["reasoning"] и дополнительно отображается через reasoning_callback.

Правила чередования сообщений

Цикл агента обеспечивает строгое чередование ролей сообщений:

Поставщики проверяют эти последовательности и отклоняют искаженные истории.

Прерываемые вызовы API

Запросы API заключены в _interruptible_api_call(), который запускает фактический HTTP-вызов в фоновом потоке, одновременно отслеживая событие прерывания:

┌────────────────────────────────────────────────────┐
│  Main thread                  API thread           │
│                                                    │
│   wait on:                     HTTP POST           │
│    - response ready     ───▶   to provider         │
│    - interrupt event                               │
│    - timeout                                       │
└────────────────────────────────────────────────────┘

При прерывании (пользователь отправляет новое сообщение, команду /stop или сигнал): - Поток API заброшен (ответ отброшен). - Агент может обработать новый ввод или корректно завершить работу. - Частичный ответ не добавляется в историю разговоров.

Выполнение инструмента

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

Когда модель возвращает вызовы инструментов:

Поток выполнения

for each tool_call in response.tool_calls:
    1. Resolve handler from tools/registry.py
    2. Fire pre_tool_call plugin hook
    3. Check if dangerous command (tools/approval.py)
       - If dangerous: invoke approval_callback, wait for user
    4. Execute handler with args + task_id
    5. Fire post_tool_call plugin hook
    6. Append {"role": "tool", "content": result} to history

Инструменты уровня агента

Некоторые инструменты перехватываются run_agent.py до достижения handle_function_call():

Инструмент Почему перехвачен
todo Чтение/запись состояния локальной задачи агента
memory Записывает в файлы постоянной памяти с ограничениями по количеству символов
session_search Запрашивает историю сессий через БД сессий агента
delegate_task Создает субагент(ы) с изолированным контекстом

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

Поверхности обратного вызова

AIAgent поддерживает обратные вызовы для конкретной платформы, которые обеспечивают прогресс в интеграции CLI, шлюза и ACP в режиме реального времени:

Обратный звонок При увольнении Используется
tool_progress_callback До/после каждого применения инструмента Счетчик CLI, сообщения о ходе работы шлюза
thinking_callback Когда модель начинает/перестает думать Индикатор CLI «думаю...»
reasoning_callback Когда модель возвращает содержание рассуждений Отображение рассуждений CLI, блоки рассуждений шлюза
clarify_callback При вызове инструмента clarify Приглашение ввода CLI, интерактивное сообщение шлюза
step_callback После каждого полного хода агента Отслеживание шагов шлюза, прогресс ACP
stream_delta_callback Каждый токен потоковой передачи (если включен) Потоковое отображение CLI
tool_gen_callback Когда вызов инструмента анализируется из потока Предварительный просмотр инструмента CLI в Spinner
status_callback Изменения состояния (мышление, выполнение и т.д.) Обновления статуса ACP

Бюджет и резервное поведение

Бюджет итерации

Агент отслеживает итерации через IterationBudget:

Резервная модель

При сбое основной модели (ограничение скорости 429, ошибка сервера 5xx, ошибка аутентификации 401/403):

  1. Проверьте список fallback_providers в конфигурации.
  2. Попробуйте каждый вариант по порядку
  3. В случае успеха продолжайте разговор с новым провайдером.
  4. В 401/403 попытайтесь обновить учетные данные перед аварийным переключением.

Резервная система также независимо выполняет вспомогательные задачи — просмотр, сжатие, веб-извлечение и поиск сеансов имеют собственную резервную цепочку, настраиваемую через раздел конфигурации auxiliary.*.

Сжатие и сохранение

Когда срабатывает сжатие

Что происходит во время сжатия

  1. Сначала память сбрасывается на диск (предотвращает потерю данных).
  2. Средние повороты разговора сводятся в компактное резюме.
  3. Последние N сообщений сохраняются нетронутыми (compression.protect_last_n, по умолчанию: 20)
  4. Пары «вызов инструмента/сообщение о результате» хранятся вместе (никогда не разделяются).
  5. Генерируется новый идентификатор линии сеанса (сжатие создает «дочерний» сеанс).

Сохранение сеанса

После каждого хода: - Сообщения сохраняются в хранилище сеансов (SQLite через hermes_state.py) - Изменения памяти сбрасываются в MEMORY.md / USER.md. - Сеанс можно возобновить позже через /resume или hermes chat --resume.

Ключевые исходные файлы

Файл Цель
run_agent.py Класс AIAgent — полный цикл агента (~13 700 строк)
agent/prompt_builder.py Сборка системных подсказок по памяти, навыки, контекстные файлы, личность
agent/context_engine.py ContextEngine ABC — подключаемое управление контекстом
agent/context_compressor.py Механизм по умолчанию — алгоритм суммирования с потерями
agent/prompt_caching.py Антропные маркеры оперативного кэширования и метрики кэширования
agent/auxiliary_client.py Вспомогательный LLM-клиент для побочных задач (видение, обобщение)
model_tools.py Коллекция схем инструментов, отправка handle_function_call()

Сопутствующие документы