sidebar_position: 8 title: "Code Execution" description: "Programmatic Python execution with RPC tool access — collapse multi-step workflows into a single turn" lang: ru


Выполнение кода (программный вызов инструмента)

Инструмент execute_code позволяет агенту писать сценарии Python, которые программно вызывают инструменты Hermes, сводя многоэтапные рабочие процессы в один цикл LLM. Сценарий выполняется в дочернем процессе на хосте агента, взаимодействуя с Hermes через RPC сокета домена Unix.

Как это работает

  1. Агент пишет скрипт Python, используя from hermes_tools import ....
  2. Hermes генерирует модуль-заглушку hermes_tools.py с функциями RPC.
  3. Гермес открывает сокет домена Unix и запускает поток прослушивателя RPC.
  4. Скрипт выполняется в дочернем процессе — вызовы инструментов передаются через сокет обратно в Hermes.
  5. В LLM возвращается только вывод сценария print(); промежуточные результаты инструмента никогда не попадают в контекстное окно
# The agent can write scripts like:
from hermes_tools import web_search, web_extract

results = web_search("Python 3.13 features", limit=5)
for r in results["data"]["web"]:
    content = web_extract([r["url"]])
    # ... filter and process ...
print(summary)

Доступные инструменты внутри скриптов: web_search, web_extract, read_file, write_file, search_files, patch, terminal (только на переднем плане).

Когда агент использует это

Агент использует execute_code, когда есть:

Ключевое преимущество: промежуточные результаты инструмента никогда не попадают в контекстное окно — возвращается только окончательный вывод print(), что значительно сокращает использование токенов.

Практические примеры

Конвейер обработки данных

from hermes_tools import search_files, read_file
import json

# Find all config files and extract database settings
matches = search_files("database", path=".", file_glob="*.yaml", limit=20)
configs = []
for match in matches.get("matches", []):
    content = read_file(match["path"])
    configs.append({"file": match["path"], "preview": content["content"][:200]})

print(json.dumps(configs, indent=2))

Многоэтапное веб-исследование

from hermes_tools import web_search, web_extract
import json

# Search, extract, and summarize in one turn
results = web_search("Rust async runtime comparison 2025", limit=5)
summaries = []
for r in results["data"]["web"]:
    page = web_extract([r["url"]])
    for p in page.get("results", []):
        if p.get("content"):
            summaries.append({
                "title": r["title"],
                "url": r["url"],
                "excerpt": p["content"][:500]
            })

print(json.dumps(summaries, indent=2))

Массовый рефакторинг файлов

from hermes_tools import search_files, read_file, patch

# Find all Python files using deprecated API and fix them
matches = search_files("old_api_call", path="src/", file_glob="*.py")
fixed = 0
for match in matches.get("matches", []):
    result = patch(
        path=match["path"],
        old_string="old_api_call(",
        new_string="new_api_call(",
        replace_all=True
    )
    if "error" not in str(result):
        fixed += 1

print(f"Fixed {fixed} files out of {len(matches.get('matches', []))} matches")

Сборка и тестирование конвейера

from hermes_tools import terminal, read_file
import json

# Run tests, parse results, and report
result = terminal("cd /project && python -m pytest --tb=short -q 2>&1", timeout=120)
output = result.get("output", "")

# Parse test output
passed = output.count(" passed")
failed = output.count(" failed")
errors = output.count(" error")

report = {
    "passed": passed,
    "failed": failed,
    "errors": errors,
    "exit_code": result.get("exit_code", -1),
    "summary": output[-500:] if len(output) > 500 else output
}

print(json.dumps(report, indent=2))

Режим выполнения

execute_code имеет два режима выполнения, управляемые code_execution.mode в ~/.hermes/config.yaml:

Режим Рабочий каталог Интерпретатор Python
project (по умолчанию) Рабочий каталог сеанса (тот же, что terminal()) Активный VIRTUAL_ENV / CONDA_PREFIX питон, возврат к собственному питону Гермеса
strict Временный промежуточный каталог, изолированный от проекта пользователя sys.executable (собственный питон Гермеса)

Когда оставить project: вы хотите, чтобы import pandas, from my_project import foo или относительные пути, такие как open(".env"), работали так же, как в terminal(). Это почти всегда то, что вы хотите.

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

# ~/.hermes/config.yaml
code_execution:
  mode: project   # or "strict"

Резервное поведение в режиме project: если VIRTUAL_ENV / CONDA_PREFIX не установлено, сломано или указывает на Python старше 3.8, преобразователь полностью возвращается к sys.executable — он никогда не оставляет агента без работающего интерпретатора.

Критически важные для безопасности инварианты идентичны в обоих режимах:

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

Ограничения ресурсов

Ресурс Лимит Заметки
Тайм-аут 5 минут (300 с) Скрипт завершается с помощью SIGTERM, затем SIGKILL через 5 секунд
Стандартный 50 КБ Вывод усечен с уведомлением [output truncated at 50KB]
Стдерр 10 КБ Включено в вывод при ненулевом выходе для отладки
Вызовы инструментов 50 за исполнение Ошибка возвращается при достижении лимита

Все ограничения настраиваются через config.yaml:

# In ~/.hermes/config.yaml
code_execution:
  mode: project      # project (default) | strict
  timeout: 300       # Max seconds per script (default: 300)
  max_tool_calls: 50 # Max tool calls per execution (default: 50)

Как вызовы инструментов работают внутри скриптов

Когда ваш скрипт вызывает функцию типа web_search("query"):

  1. Вызов сериализуется в JSON и отправляется через сокет домена Unix родительскому процессу.
  2. Родительский объект отправляет через стандартный обработчик handle_function_call.
  3. Результат отправляется обратно через сокет.
  4. Функция возвращает разобранный результат

Это означает, что вызовы инструментов внутри скриптов ведут себя идентично обычным вызовам инструментов — те же ограничения скорости, та же обработка ошибок, те же возможности. Единственное ограничение состоит в том, что terminal() используется только на переднем плане (без параметров background или pty).

Обработка ошибок

При сбое сценария агент получает структурированную информацию об ошибке:

Ответ всегда включает status (успех/ошибка/время ожидания/прерывание), output, tool_calls_made и duration_seconds.

Безопасность

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

Переменные среды, содержащие KEY, TOKEN, SECRET, PASSWORD, CREDENTIAL, PASSWD или AUTH в своих именах, исключаются. Передаются только безопасные системные переменные (PATH, HOME, LANG, SHELL, PYTHONPATH, VIRTUAL_ENV и т. д.).

Передача переменной среды навыка

Когда навык объявляет required_environment_variables во вступительной части, эти переменные автоматически передаются в дочерние процессы execute_code и terminal после загрузки навыка. Это позволяет специалистам использовать заявленные ключи API, не ослабляя при этом уровень безопасности произвольного кода.

Для случаев использования, не требующих навыков, вы можете явно внести переменные в список разрешенных в config.yaml:

terminal:
  env_passthrough:
    - MY_CUSTOM_KEY
    - ANOTHER_TOKEN

Подробную информацию см. в Руководстве по безопасности.

Hermes всегда записывает сценарий и автоматически созданную заглушку hermes_tools.py RPC во временный промежуточный каталог, который очищается после выполнения. В режиме strict скрипт также запускается там; в режиме project он запускается в рабочем каталоге сеанса (промежуточный каталог остается PYTHONPATH, поэтому импорт по-прежнему разрешается). Дочерний процесс выполняется в отдельной группе процессов, поэтому его можно полностью завершить при таймауте или прерывании.

execute_code против терминала

Вариант использования код_выполнения терминал
Многоэтапные рабочие процессы с вызовами инструментов между
Простая команда оболочки
Фильтрация/обработка больших выходных данных инструмента
Запуск набора сборки или тестирования
Перебор результатов поиска
Интерактивные/фоновые процессы
Требуются ключи API в среде ⚠️ Только через passthrough ✅ (большинство проходит)

Практическое правило: Используйте execute_code, когда вам нужно вызывать инструменты Hermes программно с логикой между вызовами. Используйте terminal для запуска команд оболочки, сборок и процессов.

Поддержка платформы

Для выполнения кода требуются сокеты домена Unix и доступно только в Linux и macOS. В Windows он автоматически отключается — агент возвращается к обычным последовательным вызовам инструментов.