Using Hermes as a Python Library
استخدام Hermes كمكتبة Python
What this page is, and what it holds.
This page covers Using Hermes as a Python Library. It carries a source warning and takes about 7 minutes to read. An interface exposed on the network needs authentication, even on your own machine.
Embed AIAgent in your own Python scripts, web apps, or automation pipelines — no CLI required
Outcomes taken from this page, not a template.
- Understand what التشغيل البرمجي is and when you need it.
- Run
hermes uv syncand understand what happens next. - Read the table and take only the row that applies to you.
- Set
OPENROUTER_API_KEYin the right place.
Exactly as they appear in Hermes.
hermes uv sync
OPENROUTER_API_KEYOPENAI_API_KEYANTHROPIC_API_KEYYOUR_DISCORD_TOKEN
Jump to the part you need.
Nothing summarised away.
The documentation body below is reproduced from the official source so commands and identifiers stay exact. Each section carries a short note describing what it contains.
Hermes isn't just a CLI tool. You can import AIAgent directly and use it programmatically in your own Python scripts, web applications, or automation pipelines. This guide shows you how.
---
Installation
Ordered, practical steps. Run one and confirm it worked before moving on. Commands here: hermes uv sync.
Clone Hermes and create its supported editable development environment:
git clone https://github.com/NousResearch/hermes-agent.git
cd hermes-agent
uv syncRun your application with uv run python your_app.py from that checkout. Hermes does not publish a supported wheel or source distribution for requirements.txt installs.
---
Basic Usage
Carries a warning. Read it before running anything here. The upstream warning appears below.
The simplest way to use Hermes is the chat() method — pass a message, get a string back:
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() handles the full conversation loop internally — tool calls, retries, everything — and returns just the final text response.
---
Full Conversation Control
Explains the idea itself. Read it slowly; the later sections build on it.
For more control over the conversation, use run_conversation() directly. It returns a dictionary with the full response, message history, and metadata:
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— The agent's final text replymessages— The complete message history (system, user, assistant, tool calls)
(The task_id you pass in is stored on the agent instance for VM isolation but isn't echoed back in the return dict.)
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
Explains the idea itself. Read it slowly; the later sections build on it.
Control which toolsets the agent has access to using enabled_toolsets or 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,
)---
Multi-turn Conversations
Explains the idea itself. Read it slowly; the later sections build on it.
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 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."The conversation_history parameter accepts the messages list from a previous result. The agent copies it internally, so your original list is never mutated.
---
Saving Trajectories
Explains the idea itself. Read it slowly; the later sections build on it.
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 formatEach conversation is appended as a single JSONL line, making it easy to collect datasets from automated runs.
---
Custom System Prompts
Explains the idea itself. Read it slowly; the later sections build on it.
Use ephemeral_system_prompt to set a custom system prompt that guides the agent's behavior but is not saved to trajectory files (keeping your training data clean):
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
Carries a warning. Read it before running anything here. The upstream warning appears below.
For running many prompts in parallel, Hermes includes batch_runner.py. It manages concurrent AIAgent instances with proper resource isolation:
python batch_runner.py --input prompts.jsonl --output results.jsonlEach prompt gets its own task_id and isolated environment. If you need custom batch logic, you can build your own using AIAgent directly:
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")---
Integration Examples
Settings you configure once. Change one at a time so you can see what each does. Set YOUR_DISCORD_TOKEN in your environment, not in the chat.
FastAPI Endpoint
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 Bot
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 Pipeline Step
#!/usr/bin/env python3
"""CI step: auto-review a PR diff."""
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)---
Key Constructor Parameters
A lookup table. Do not read it all; find the row that applies to you.
| 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 | 500 | 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.) |
---
Important Notes
Carries a warning. Read it before running anything here. The upstream warning appears below.
4 questions answered by this page alone.
Every option is a real identifier from the Hermes documentation. The wrong ones are real too, just from other pages.