The Hermes SDK turns a full autonomous agent into a single call. Give it a goal in plain language — it writes and runs code, browses the web, reads images, creates files and charts, and hands back clean results with downloadable artifacts. No orchestration to wire up.
Writes and executes Python & shell, captures output, and returns any files it produces.
Searches and reads live pages, then answers grounded in what it found.
Controls a real Chromium — navigate, click, fill forms, screenshot.
Analyzes and describes images you attach, and reasons over their contents.
Turns data into plots via code (matplotlib & co.) — returned as downloadable artifacts.
Reads, writes, patches and searches files within an isolated working directory.
Spawns sub-agents to split large jobs into parallel, focused tasks.
Per-user memory + full-text search over past conversations.
Task planning for multi-step work, plus any installed skills it can invoke.
One class, Hermes. A general run() for any goal, stream() for live agentic UIs, plus capability-shaped shortcuts. Every call returns the same Result.
agent = Hermes( model = None, # default model; None → server default permission = "allow", # "allow" | "deny" | callable(tool) → decision user = None, # default identity for memory + isolation timeout = 600, # seconds per call retries = 2, # auto-retry transient model errors (safe — no dup side effects) )
from hermes_sdk import Hermes agent = Hermes() res = agent.run( "plot a gaussian histogram" " and save it as hist.png", user="alice", ) print(res.text) # → "Done — 10,000 samples, 50 bins…" for a in res.artifacts: open(a.name, "wb").write(a.bytes()) # → hist.png (downloadable)
# watch the agent work, live for ev in agent.stream( "research EV sales in 2025, chart them"): if ev.kind == "text": ui.append(ev.text) # streaming elif ev.kind == "tool": ui.step(ev.title) # web_search… elif ev.kind == "done": ui.show(ev.result) # final + files # vision: attach an image agent.see("chart.png", "what trend is this?") # continue the conversation agent.resume(res.session_id, "now use 100 bins")
Real output, not a mock — captured from agent.visualize(...) against a live Hermes. The PNG above is the file in res.artifacts[0].
Result .text str # the final answer (clean — no tool noise) .artifacts list[Artifact] # files the agent produced .tool_calls list[ToolCall] # what it did, in order .reasoning str # its thinking (optional) .session_id str # pass to resume() to continue .stop_reason str # end_turn | max_turns | refusal .elapsed float # seconds .usage Usage # token counts Artifact .name str .mime str .size int .bytes() → bytes .url str? ToolCall .tool str .title str .status "running" | "done" | "error" Attachment Attachment.image(src) Attachment.file(path) Attachment.bytes(data, mime) Capability .id str .name str .summary str