Skip to main content

Upstream differences

Async Hermes Agent is based on upstream Hermes Agent v2026.8.18 (Python package version 0.20.4). 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.18Async Hermes Agent 0.20.4.1Integration 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 + psycopg; 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
Async delegation persistenceUpstream delegation records use the retained SQLite state pathAn explicitly injected PostgreSQL SessionDB also stores durable delegation records and serves session_search(db=...); default SQLite delegation and plugin stores remain unchangedInject the existing store; no automatic profile-to-DSN routing or new public API is added
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 boundaries and python batch_runner.py --... entrypointMiniSWERunner and BatchRunner keep their upstream names while becoming coroutines; the upstream CLI syntax is retained at a process boundary, while checkpoint, resume, shards, merged JSONL, and statistics remainUse the CLI unchanged, await runner.run_task(...)/await runner.run(...) in a library, and await the same methods from a web host
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 or interactive Hermes CLI/TUI, messaging bridge, scheduler, dashboard, or desktop application is bundled; the upstream BatchRunner script entrypoint is retainedThe host application owns HTTP lifecycle, auth, routing, quotas, and shutdown; web code awaits BatchRunner directly
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.4Python >=3.11,<3.14; package 0.20.4.1 (async_revision=1)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.