Hermes как Python-библиотека

Hermes — это не только CLI. Вы можете импортировать AIAgent напрямую и использовать его программно в своих Python-скриптах, веб-приложениях или пайплайнах автоматизации. Этот гайд показывает, как.


Установка

Установите Hermes прямо из репозитория:

pip install git+https://github.com/NousResearch/hermes-agent.git

Или через uv:

uv pip install git+https://github.com/NousResearch/hermes-agent.git

Можно зафиксировать версию в requirements.txt:

hermes-agent @ git+https://github.com/NousResearch/hermes-agent.git
совет

При использовании Hermes как библиотеки нужны те же переменные окружения, что и для CLI. Минимально — OPENROUTER_API_KEY (или OPENAI_API_KEY / ANTHROPIC_API_KEY при прямом доступе к провайдеру).


Базовое использование

Самый простой способ — метод chat(): передайте сообщение, получите строку в ответ:

from run_agent import AIAgent

agent = AIAgent(
    model="anthropic/claude-sonnet-4.6",
    quiet_mode=True,
)
response = agent.chat("What is the capital of France?")
print(response)

chat() самостоятельно ведёт весь цикл разговора — вызовы инструментов, повторные попытки, всё остальное — и возвращает только финальный текстовый ответ.

внимание

Всегда задавайте quiet_mode=True при встраивании Hermes в свой код. Без этого агент будет печатать спиннеры CLI, индикаторы прогресса и другой вывод для терминала, который засорит вывод вашего приложения.


Полный контроль над разговором

Для более тонкого управления используйте run_conversation() напрямую. Метод возвращает словарь с полным ответом, историей сообщений и метаданными:

agent = AIAgent(
    model="anthropic/claude-sonnet-4.6",
    quiet_mode=True,
)

result = agent.run_conversation(
    user_message="Search for recent Python 3.13 features",
    task_id="my-task-1",
)

print(result["final_response"])
print(f"Messages exchanged: {len(result['messages'])}")

Возвращаемый словарь содержит:

  • final_response — финальный текстовый ответ агента
  • messages — полная история сообщений (system, user, assistant, вызовы инструментов)

(task_id, который вы передаёте, сохраняется в экземпляре агента для изоляции VM, но не возвращается в словаре результата.)

Можно также передать пользовательский системный промпт, который переопределит эфемерный системный промпт для этого вызова:

result = agent.run_conversation(
    user_message="Explain quicksort",
    system_message="You are a computer science tutor. Use simple analogies.",
)

Настройка инструментов

Управляйте тем, какие наборы инструментов доступны агенту, через enabled_toolsets или disabled_toolsets:

# Only enable web tools (browsing, search)
agent = AIAgent(
    model="anthropic/claude-sonnet-4.6",
    enabled_toolsets=["web"],
    quiet_mode=True,
)

# Enable everything except terminal access
agent = AIAgent(
    model="anthropic/claude-sonnet-4.6",
    disabled_toolsets=["terminal"],
    quiet_mode=True,
)
совет

Используйте enabled_toolsets, когда хотите минимального агента с жёстким ограничением (например, только веб-поиск для исследовательского бота). Используйте disabled_toolsets, когда хотите оставить большинство возможностей, но заблокировать конкретные (например, без доступа к терминалу в общей среде).


Многоходовые разговоры

Сохраняйте состояние разговора между ходами, передавая историю сообщений обратно:

agent = AIAgent(
    model="anthropic/claude-sonnet-4.6",
    quiet_mode=True,
)

# First turn
result1 = agent.run_conversation("My name is Alice")
history = result1["messages"]

# Second turn — agent remembers the context
result2 = agent.run_conversation(
    "What's my name?",
    conversation_history=history,
)
print(result2["final_response"])  # "Your name is Alice."

Параметр conversation_history принимает список messages из предыдущего результата. Агент копирует его внутри, поэтому ваш исходный список никогда не изменяется.


Сохранение траекторий

Включите сохранение траекторий, чтобы фиксировать разговоры в формате ShareGPT — удобно для генерации обучающих данных или отладки:

agent = AIAgent(
    model="anthropic/claude-sonnet-4.6",
    save_trajectories=True,
    quiet_mode=True,
)

agent.chat("Write a Python function to sort a list")
# Saves to trajectory_samples.jsonl in ShareGPT format

Каждый разговор добавляется как одна строка JSONL — легко собирать датасеты из автоматизированных запусков.


Пользовательские системные промпты

Используйте ephemeral_system_prompt, чтобы задать системный промпт, который направляет поведение агента, но не сохраняется в файлы траекторий (обучающие данные остаются чистыми):

agent = AIAgent(
    model="anthropic/claude-sonnet-4",
    ephemeral_system_prompt="You are a SQL expert. Only answer database questions.",
    quiet_mode=True,
)

response = agent.chat("How do I write a JOIN query?")
print(response)

Отлично подходит для создания специализированных агентов — ревьюер кода, технический писатель, SQL-ассистент — на одном базовом инструментарии.


Пакетная обработка

Для параллельного выполнения множества промптов в Hermes есть batch_runner.py. Он управляет параллельными экземплярами AIAgent с правильной изоляцией ресурсов:

python batch_runner.py --input prompts.jsonl --output results.jsonl

Каждый промпт получает свой task_id и изолированную среду. Если нужна кастомная логика пакетной обработки, можно построить её самостоятельно на базе AIAgent:

import concurrent.futures
from run_agent import AIAgent

prompts = [
    "Explain recursion",
    "What is a hash table?",
    "How does garbage collection work?",
]

def process_prompt(prompt):
    # Create a fresh agent per task for thread safety
    agent = AIAgent(
        model="anthropic/claude-sonnet-4",
        quiet_mode=True,
        skip_memory=True,
    )
    return agent.chat(prompt)

with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
    results = list(executor.map(process_prompt, prompts))

for prompt, result in zip(prompts, results):
    print(f"Q: {prompt}\nA: {result}\n")
внимание

Всегда создавайте новый экземпляр AIAgent для каждого потока или задачи. Агент хранит внутреннее состояние (историю разговора, сессии инструментов, счётчики итераций), которое небезопасно делить между параллельными вызовами.


Примеры интеграций

Эндпоинт FastAPI

from fastapi import FastAPI
from pydantic import BaseModel
from run_agent import AIAgent

app = FastAPI()

class ChatRequest(BaseModel):
    message: str
    model: str = "anthropic/claude-sonnet-4"

@app.post("/chat")
async def chat(request: ChatRequest):
    agent = AIAgent(
        model=request.model,
        quiet_mode=True,
        skip_context_files=True,
        skip_memory=True,
    )
    response = agent.chat(request.message)
    return {"response": response}

Discord-бот

import discord
from run_agent import AIAgent

client = discord.Client(intents=discord.Intents.default())

@client.event
async def on_message(message):
    if message.author == client.user:
        return
    if message.content.startswith("!hermes "):
        query = message.content[8:]
        agent = AIAgent(
            model="anthropic/claude-sonnet-4",
            quiet_mode=True,
            skip_context_files=True,
            skip_memory=True,
            platform="discord",
        )
        response = agent.chat(query)
        await message.channel.send(response[:2000])

client.run("YOUR_DISCORD_TOKEN")

Шаг CI/CD-пайплайна

#!/usr/bin/env python3
"""CI step: auto-review a PR diff."""
import subprocess
from run_agent import AIAgent

diff = subprocess.check_output(["git", "diff", "main...HEAD"]).decode()

agent = AIAgent(
    model="anthropic/claude-sonnet-4",
    quiet_mode=True,
    skip_context_files=True,
    skip_memory=True,
    disabled_toolsets=["terminal", "browser"],
)

review = agent.chat(
    f"Review this PR diff for bugs, security issues, and style problems:\n\n{diff}"
)
print(review)

Основные параметры конструктора

ПараметрТипПо умолчаниюОписание
modelstr""Модель в формате OpenRouter (по умолчанию пусто; определяется из конфига hermes во время выполнения)
quiet_modeboolFalseПодавить вывод CLI
enabled_toolsetsList[str]NoneБелый список наборов инструментов
disabled_toolsetsList[str]NoneЧёрный список наборов инструментов
save_trajectoriesboolFalseСохранять разговоры в JSONL
ephemeral_system_promptstrNoneПользовательский системный промпт (не сохраняется в траектории)
max_iterationsint90Максимум итераций вызовов инструментов за разговор
skip_context_filesboolFalseНе загружать файлы AGENTS.md
skip_memoryboolFalseОтключить чтение/запись постоянной памяти
api_keystrNoneAPI-ключ (если не задан, берётся из переменных окружения)
base_urlstrNoneURL кастомного API-эндпоинта
platformstrNoneПодсказка о платформе ("discord", "telegram" и т.д.)

Важные замечания

совет
  • Задайте skip_context_files=True, если не хотите, чтобы файлы AGENTS.md из рабочего каталога загружались в системный промпт.
  • Задайте skip_memory=True, чтобы агент не читал и не записывал постоянную память — рекомендуется для stateless API-эндпоинтов.
  • Параметр platform (например, "discord", "telegram") добавляет в промпт подсказки по форматированию, специфичные для платформы, — агент адаптирует стиль вывода.
внимание
  • Потокобезопасность: создавайте один экземпляр AIAgent на поток или задачу. Никогда не делитесь экземпляром между параллельными вызовами.
  • Очистка ресурсов: агент автоматически освобождает ресурсы (сессии терминала, экземпляры браузера) по завершении разговора. В долгоживущем процессе убедитесь, что каждый разговор завершается нормально.
  • Лимиты итераций: значение по умолчанию max_iterations=90 достаточно щедрое. Для простых сценариев вопрос–ответ подумайте о его снижении (например, max_iterations=10), чтобы предотвратить бесконечные циклы вызовов инструментов и контролировать расходы.
ESC