Typed async client for the Hermes Agent API Server
Project description
Hermes Agent API Client
Hermes Agent API Client is a typed async Python client for authenticated capability discovery and streaming Chat Completions from the Hermes Agent API Server. The package requires Python 3.13 or later.
Installation
Install the package from PyPI:
uv add hermes-agent-api-client
Usage
HermesAgentApiClient is a single-use async context manager. Without an
injected HTTP client, it creates and closes its own httpx.AsyncClient:
from hermes_agent_api_client import HermesAgentApiClient, TerminalEvent
async def ask_hermes(request: dict[str, object]) -> None:
async with HermesAgentApiClient(
"https://hermes.example",
"bearer-key",
) as client:
capabilities = await client.probe_capabilities()
assert capabilities.chat_completions_streaming
async for event in client.stream_chat_events(
request,
session_id="profile.chat-001",
session_key="home-assistant-instance-001",
):
if isinstance(event, TerminalEvent):
print(event.outcome)
The default verify=None uses httpx's verified TLS default. An owned client may
instead receive verify=False or an ssl.SSLContext. Disabling certificate
verification weakens transport security and should be limited to controlled
environments.
To share a caller-managed client, inject it explicitly:
import httpx
from hermes_agent_api_client import HermesAgentApiClient
async def probe_with_shared_transport() -> None:
async with httpx.AsyncClient(verify=True) as http_client:
async with HermesAgentApiClient(
"https://hermes.example",
"bearer-key",
http_client=http_client,
) as client:
await client.probe_capabilities()
The caller owns an injected client, so exiting HermesAgentApiClient does not
close it. TLS verification must be configured on the injected client; passing
both http_client and a non-None verify value is rejected.
Capability discovery can distinguish a non-Hermes endpoint from a Hermes Agent that lacks required Chat Completions support using package-root imports only:
from hermes_agent_api_client import (
HermesAgentApiClient,
HermesCapabilityError,
HermesIdentityError,
)
async def discover_hermes(base_url: str, bearer_key: str) -> str:
try:
async with HermesAgentApiClient(base_url, bearer_key) as client:
capabilities = await client.probe_capabilities()
except HermesIdentityError:
return "not a Hermes Agent endpoint"
except HermesCapabilityError:
return "Hermes Agent lacks Chat Completions support"
return capabilities.model
Supported contract
The package supports only these Hermes operations:
GET /v1/capabilitiesthroughprobe_capabilities().- Streaming
POST /v1/chat/completionsthroughstream_chat_events().
The exact OpenAI-compatible request document remains a caller-owned mapping; the client does not define additional request-model semantics.
Each stream accepts independent keyword-only session_id and session_key
values. Non-None values map only to X-Hermes-Session-Id and
X-Hermes-Session-Key; the client never derives identifiers or accepts an
arbitrary headers mapping. Values must be exact built-in strings containing
1 through 256 visible ASCII characters. Session IDs additionally reject path
shapes (.., /, \, or a leading drive-letter prefix). Invalid values fail
locally on the stream's first iteration as a non-retryable
HermesTransportError, before network dispatch.
A successful capability probe returns an immutable HermesCapabilities value
with this supported shape:
object: exactlyhermes.api_server.capabilities.platform: exactlyhermes-agent.model: the advertised API/profile name.auth_type: exactlybearer.auth_required: the literal booleanTrue.chat_completions: the literal booleanTrue.chat_completions_streaming: the literal booleanTrue.
At the immutable upstream compatibility target, model is resolved in order
from an explicit API-server model override, a non-default active profile, or
the hermes-agent fallback. The client preserves the advertised string exactly:
it does not trim, normalize, replace, or truncate leading, trailing, or internal
whitespace. Strict validation requires an actual string containing 1 through
255 Unicode code points and at least one non-whitespace code point; empty,
whitespace-only, non-string, and over-limit values are rejected.
The stream yields immutable AssistantDeltaEvent, ToolProgressEvent,
UsageEvent, KeepaliveEvent, and TerminalEvent values. Terminal outcomes
are success, length, or upstream_error. Tool progress exposes only a
bounded tool_call_id, tool_name, and the closed running/completed
status. Terminal events expose only outcome, partial, and the optional
closed failure reasons output_truncated, agent_error, or unknown;
additional metadata passed when constructing a public TerminalEvent is
rejected. Additive upstream wire fields remain ignored by the private decoder.
Public failures derive from HermesContractError and expose only safe
category, status_code, and retryable metadata. HermesIdentityError and
HermesCapabilityError both inherit HermesProtocolError, so existing callers
that catch HermesProtocolError or HermesContractError continue to catch
them. Both subclasses have protocol category, no status code, and
retryable=False, with no additional instance state.
Capability-probe classification is staged and deterministic:
| Wire condition | Public exception |
|---|---|
| Top-level document is not a mapping | HermesProtocolError |
Missing or non-exact object discriminator |
HermesIdentityError |
Missing or non-exact platform discriminator |
HermesIdentityError |
Valid identity, but features is missing or not a mapping |
HermesCapabilityError |
Valid identity, but features.chat_completions is missing, false, or not the literal boolean True |
HermesCapabilityError |
Invalid or missing model |
HermesProtocolError |
| Invalid or missing bearer authentication contract | HermesProtocolError |
Missing, false, or invalid chat_completions_streaming |
HermesProtocolError |
| Malformed JSON, oversized body, or another unrelated schema failure | HermesProtocolError |
| Existing authentication HTTP status | HermesAuthenticationError |
| Existing non-authentication HTTP status | HermesHttpStatusError |
| Existing request, timeout, read, or cleanup transport failure | HermesTransportError |
Identity failures take precedence over required-feature failures. Capability
failures are classified only after both identity discriminators are valid, and
all remaining wire failures use the generic HermesProtocolError fallback.
Authentication HTTP status, other HTTP status, and transport failures remain
HermesAuthenticationError, HermesHttpStatusError, and
HermesTransportError, respectively. Callers should not expect upstream
response bodies, bearer credentials, request payloads, URLs, or raw validation
details in public error text.
Compatibility targets the immutable Hermes Agent tag v2026.7.7.2 at commit
9de9c25f620ff7f1ce0fd5457d596052d5159596. Evidence is derived from a
capability fixture captured from that tagged handler and local
protocol/transport tests; it is not evidence from a live Hermes server or a
moving upstream branch.
Security: Hermes API access exposes the configured agent toolset. Protect the bearer key, restrict network access, and grant the Hermes agent only the tools appropriate for the calling application.
Development
Install the exact locked development environment and the commit hook:
uv sync --locked --all-groups
prek install
prek runs the complete quality gate automatically before every Git commit and
blocks the commit when any check fails.
License
Licensed under the Universal Permissive License 1.0 (UPL-1.0). See LICENSE.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hermes_agent_api_client-0.3.1.tar.gz.
File metadata
- Download URL: hermes_agent_api_client-0.3.1.tar.gz
- Upload date:
- Size: 56.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
882e919efd1ca0c8819acb34232832d2dbc982faadaeb5431ce24ec5b1a188f1
|
|
| MD5 |
3da8f80ddb4ca3eb336a34aa7fdede71
|
|
| BLAKE2b-256 |
b9c29dcc0cdaf10ce42a61b860e0e8e1c6534232f7f03606dda946a3058ae996
|
Provenance
The following attestation bundles were made for hermes_agent_api_client-0.3.1.tar.gz:
Publisher:
release.yml on Djelibeybi/hermes-agent-api-client
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hermes_agent_api_client-0.3.1.tar.gz -
Subject digest:
882e919efd1ca0c8819acb34232832d2dbc982faadaeb5431ce24ec5b1a188f1 - Sigstore transparency entry: 2189958580
- Sigstore integration time:
-
Permalink:
Djelibeybi/hermes-agent-api-client@8843cfc700b76c7e9dad6928008b4095ddffbb49 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Djelibeybi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8843cfc700b76c7e9dad6928008b4095ddffbb49 -
Trigger Event:
push
-
Statement type:
File details
Details for the file hermes_agent_api_client-0.3.1-py3-none-any.whl.
File metadata
- Download URL: hermes_agent_api_client-0.3.1-py3-none-any.whl
- Upload date:
- Size: 23.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c283811c744bc4da9b68dfbf5462bccc805dd6958b71d6f667faba489b692276
|
|
| MD5 |
d00fbc84a547c6c8dae6dc1a3628c89c
|
|
| BLAKE2b-256 |
fd1cffc79d9fb413a653247257b876e40fd270a13a04db644cde0c949bd81e37
|
Provenance
The following attestation bundles were made for hermes_agent_api_client-0.3.1-py3-none-any.whl:
Publisher:
release.yml on Djelibeybi/hermes-agent-api-client
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hermes_agent_api_client-0.3.1-py3-none-any.whl -
Subject digest:
c283811c744bc4da9b68dfbf5462bccc805dd6958b71d6f667faba489b692276 - Sigstore transparency entry: 2189958653
- Sigstore integration time:
-
Permalink:
Djelibeybi/hermes-agent-api-client@8843cfc700b76c7e9dad6928008b4095ddffbb49 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Djelibeybi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8843cfc700b76c7e9dad6928008b4095ddffbb49 -
Trigger Event:
push
-
Statement type: