Using Hermes as a Python Library

Hermes isn’t just a CLI tool. You can importAIAgentdirectly and use it programmatically in your own Python scripts, web applications, or automation pipelines. This guide shows you how.

AIAgent

Installation​

Install Hermes directly from the repository:

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

Or withuv:

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

You can also pin it in yourrequirements.txt:

requirements.txt

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

The same environment variables used by the CLI are required when using Hermes as a library. At minimum, setOPENROUTER_API_KEY(orOPENAI_API_KEY/ANTHROPIC_API_KEYif using direct provider access).

OPENROUTER_API_KEY OPENAI_API_KEY ANTHROPIC_API_KEY

Basic Usage​

The simplest way to use Hermes is thechat()method — pass a message, get a string back:

chat()

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

chat()handles the full conversation loop internally — tool calls, retries, everything — and returns just the final text response.

chat()

Always setquiet_mode=Truewhen embedding Hermes in your own code. Without it, the agent prints CLI spinners, progress indicators, and other terminal output that will clutter your application’s output.

quiet_mode=True

Full Conversation Control​

For more control over the conversation, userun_conversation()directly. It returns a dictionary with the full response, message history, and metadata:

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'])}")

The returned dictionary contains:

final_response messages

(Thetask_idyou pass in is stored on the agent instance for VM isolation but isn’t echoed back in the return dict.)

task_id

You can also pass a custom system message that overrides the ephemeral system prompt for that call:

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

Configuring Tools​

Control which toolsets the agent has access to usingenabled_toolsetsordisabled_toolsets:

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 accessagent = AIAgent(    model="anthropic/claude-sonnet-4.6",    disabled_toolsets=["terminal"],    quiet_mode=True,)

Useenabled_toolsetswhen you want a minimal, locked-down agent (e.g., only web search for a research bot). Usedisabled_toolsetswhen you want most capabilities but need to restrict specific ones (e.g., no terminal access in a shared environment).

enabled_toolsets disabled_toolsets

Multi-turn Conversations​

Maintain conversation state across multiple turns by passing the message history back in:

agent = AIAgent(    model="anthropic/claude-sonnet-4.6",    quiet_mode=True,)# First turnresult1 = agent.run_conversation("My name is Alice")history = result1["messages"]# Second turn — agent remembers the contextresult2 = agent.run_conversation(    "What's my name?",    conversation_history=history,)print(result2["final_response"])  # "Your name is Alice."

Theconversation_historyparameter accepts themessageslist from a previous result. The agent copies it internally, so your original list is never mutated.

conversation_history messages

Saving Trajectories​

Enable trajectory saving to capture conversations in ShareGPT format — useful for generating training data or debugging:

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

Each conversation is appended as a single JSONL line, making it easy to collect datasets from automated runs.

Custom System Prompts​

Useephemeral_system_promptto set a custom system prompt that guides the agent’s behavior but isnotsaved to trajectory files (keeping your training data clean):

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)

This is ideal for building specialized agents — a code reviewer, a documentation writer, a SQL assistant — all using the same underlying tooling.

Batch Processing​

For running many prompts in parallel, Hermes includesbatch_runner.py. It manages concurrentAIAgentinstances with proper resource isolation:

batch_runner.py AIAgent

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

Each prompt gets its owntask_idand isolated environment. If you need custom batch logic, you can build your own usingAIAgentdirectly:

task_id AIAgent

import concurrent.futuresfrom run_agent import AIAgentprompts = [    "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")

Always create anewAIAgentinstance per thread or task. The agent maintains internal state (conversation history, tool sessions, iteration counters) that is not thread-safe to share.

AIAgent

Integration Examples​

FastAPI Endpoint​

from fastapi import FastAPIfrom pydantic import BaseModelfrom run_agent import AIAgentapp = 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 Bot​

import discordfrom run_agent import AIAgentclient = discord.Client(intents=discord.Intents.default())@client.eventasync 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 Pipeline Step​

#!/usr/bin/env python3"""CI step: auto-review a PR diff."""import subprocessfrom run_agent import AIAgentdiff = 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)

Key Constructor Parameters​

Parameter Type Default Description
model str ”” Model in OpenRouter format (defaults to empty; resolved from your hermes config at runtime)
quiet_mode bool False Suppress CLI output
enabled_toolsets List[str] None Whitelist specific toolsets
disabled_toolsets List[str] None Blacklist specific toolsets
save_trajectories bool False Save conversations to JSONL
ephemeral_system_prompt str None Custom system prompt (not saved to trajectories)
max_iterations int 90 Max tool-calling iterations per conversation
skip_context_files bool False Skip loading AGENTS.md files
skip_memory bool False Disable persistent memory read/write
api_key str None API key (falls back to env vars)
base_url str None Custom API endpoint URL
platform str None Platform hint (“discord”,”telegram”, etc.)

model str "" quiet_mode bool False enabled_toolsets List[str] None disabled_toolsets List[str] None save_trajectories bool False ephemeral_system_prompt str None max_iterations int 90 skip_context_files bool False skip_memory bool False api_key str None base_url str None platform str None "discord" "telegram"

Important Notes​

skip_context_files=True AGENTS.md skip_memory=True platform "discord" "telegram"

AIAgent max_iterations=90 max_iterations=10