Skip to main content

Upstream differences

Async Hermes Agent is based on upstream Hermes Agent v2026.8.13 (Python package version 0.20.1). The table below records the deliberate differences in the retained library surface. It is a migration guide, not a claim that the removed upstream applications are still shipped.

AreaUpstream v2026.8.13Async Hermes Agent 0.20.1.2Integration impact
Public entry pointsRetained names and module pathsThe same retained names, arguments, defaults, and return shapes; I/O-bearing calls are coroutinesExisting library callers normally add await at the call site
Agent constructionSynchronous upstream lifecycleAIAgent.__init__() is state-only; provider, session, MCP, and plugin setup starts at an awaited boundaryUse async with AIAgent(...) or await agent.close()
Conversation lifecycleSynchronous turn executionawait agent.run_conversation(...) and await agent.chat(...); turns on one agent remain serializedKeep one agent per ordered conversation; separate agents can overlap
I/O modelSynchronous provider, MCP, subprocess, file, and SQLite boundariesNative coroutine transports and awaited public I/O; regular files use aiofiles, SQLite uses aiosqliteThe host event loop is not blocked by the public I/O paths; zero-thread file/SQLite I/O is not promised
Cancellation and cleanupSynchronous cleanup semanticsPartial state is persisted before external CancelledError is re-raised; owned clients, processes, and tasks are closed deterministicallyHost cancellation can safely propagate through a request or job
ConcurrencyUpstream application schedulingSame-agent turn lock, bounded batch workers, profile-scoped caches and clientsUnrelated conversations and batch items can run concurrently without sharing mutable state
Sessions and memoryUpstream persistence behaviorAsync SessionDB, FTS search, memory, checkpoint, export/import, and cold-process resumeawait the existing session methods; use a stable HERMES_HOME/session policy
PostgreSQL SessionDBUpstream ships its SQLite session storeAdditive hermes_state_postgres.SessionDB uses SQLAlchemy Core + asyncpg; hermes_state.SessionDB remains unchangedInstall postgres, inject one worker-owned store explicitly, and close it from the host lifespan; PostgreSQL ranking can differ from SQLite BM25
TrajectoriesUpstream reasoning/tool/observation formatSame ordering and retained JSON shape, with async persistence and compressionExisting trajectory consumers can read the same retained fields
Training-data runnerSynchronous runner boundariesMiniSWERunner and BatchRunner keep their upstream names while becoming coroutines; checkpoint, resume, shards, merged JSONL, and statistics remainawait runner.run_task(...) or await runner.run(...)
Profile isolationProcess-oriented environment and cache assumptionsTask-local secrets plus canonical HERMES_HOME state isolate concurrent profiles and symlink aliasesA/B profiles can run in one process without borrowing each other's credentials or files
Provider policySynchronous adapters, including SDK-specific bootstrap behaviorNative async adapters are used where available; unsupported or unsafe synchronous paths fail explicitly rather than moving to a hidden worker threadInstall the relevant extra and follow provider-specific limitations
FastAPI/service boundaryUpstream product applications may own service surfacesNo FastAPI server, CLI/TUI, messaging bridge, scheduler, dashboard, or desktop application is bundledThe host application owns HTTP lifecycle, auth, routing, quotas, and shutdown
MCP and skillsUpstream product-managed discoveryRetained stdio, Streamable HTTP, and SSE MCP clients plus filesystem/external skill discovery with async lifecycle cleanupConfigure them from the host's Hermes home and close the agent at shutdown
Optional providers and toolsUpstream distribution layoutProvider-specific extras remain opt-in (anthropic, vertex, azure-identity, bedrock, memory, web, media, and execution backends)Install only the extras used by the selected configuration
Python and package versionUpstream baseline 0.20.1Python >=3.11,<3.14; package 0.20.1.2 (async_revision=2)The first three version segments track upstream; the fourth tracks this async distribution

Intentional public-surface exception

The retained upstream callables preserve their public names and argument shapes. TrajectoryCompressor.close() is the one explicit lifecycle addition: the async port owns an async model client and needs a public cleanup boundary for it. It is not an aclose() alias or a synchronous compatibility wrapper.

What is not changed

The conversion does not redesign the model-tool schema, rename upstream modules, add arun_* aliases, or silently run synchronous provider code in a thread. Pure CPU transformations remain synchronous. Provider output, message-role alternation, tool-call ordering, trajectory ordering, checkpoint semantics, and retained return dictionaries are preserved and covered by behavior-level parity tests.

For the supported feature set and installation commands, see Installation. For host lifecycle examples, see Programmatic Integration.