Overview
Hermes (hermes-plt, v0.2.14) is a foundational intelligence data platform for acquiring, validating, normalizing, storing and serving intelligence datasets. One consistent pipeline for APIs, CSVs, JSON, databases and public datasets.
>=3.11 (3.11/3.12/3.13) · build backend hatchling · Development Status 3 - Alpha · authored by Haider Ali · under the Hermes Non-Commercial License.Why Hermes
Every time a data team adds a new source, they rebuild the same plumbing: authentication, pagination, retries, schema mapping, unit conversion and validation. Hermes turns that repeated work into a single, reusable infrastructure layer. Here is what it tackles — skip ahead to the pipeline if you want the data flow.
| Problem | How Hermes solves it |
|---|---|
| Different APIs & auth schemes | Every connector behind one async fetch() contract |
| Inconsistent formats | A shared parse / normalize layer with one canonical schema |
| Messy identifiers & units | Entity helpers and canonical codes (ISO-3, ticker→CIK) |
| Missing or duplicated records | Validation rules + deduplicate() |
| Repetitive fetch boilerplate | RawCache with per-source TTLs and hit/miss stats |
| Untracked data provenance | Lineage and provenance recorded on every dataset |
Modern data work repeats the same engineering for every new source: dealing with different APIs, authentication, formats, schemas, naming conventions, missing values, types, timestamps, units, identifiers, duplicates and validation rules. Hermes turns that repeated work into reusable infrastructure:
import hermes as hr
data = hr.fetch("world_bank", dataset="gdp")
data = data.parse()
data = data.normalize()
data = data.validate()
print(data.profile())
df = data.to_polars()Hermes does not replace pandas, polars, duckdb or arrow — it is a pipeline layer that makes them easier to use together.
The data lifecycle
Every dataset travels through a single, repeatable pipeline. The same shape applies whether you're pulling GDP from the World Bank or filings from the SEC:
External Source
│ Connector (fetch / ingest)
▼
Raw Data
│ parse / normalize / validate / profile
▼
Hermes Dataset
│ transform / resolve / query / save / export
▼
Applications — ML, analytics, dashboards| Function | Purpose |
|---|---|
| fetch() | Retrieve data from an external source via a connector |
| ingest() | Bring an existing dataset (csv, json, parquet) into Hermes |
| parse() | Convert raw data into structured records |
| normalize() | Convert data into a consistent representation |
| validate() | Verify data satisfies defined rules |
| profile() / inspect() | Analyze structure, quality and metadata |
| transform() | Apply transformations to data |
| resolve() | Connect records to canonical entities |
| deduplicate() | Detect and handle duplicate records |
| query(), save(), load(), export() | Query, persist and ship datasets |
| snapshot(), diff() | Immutable versioning and comparison |
| lineage(), provenance() | Show how and where data was produced |
Design pillars
Five principles shape every API decision in Hermes. They keep the platform small, predictable and easy to reason about.
| Principle | What it means in practice |
|---|---|
| Composable | Datasets from different sources work together in one pipeline |
| Inspectable | profile() / inspect() before you build on data |
| Reproducible | The same pipeline repeats predictably, cache-aware |
| Traceable | lineage() and provenance() on every dataset |
| Interoperable | pandas, polars, arrow, duckdb, numpy and parquet out of the box |
Where Hermes fits
Hermes does not replace your DataFrame library or your database. It is the glue layer between live sources and your analysis stack:
Live APIs & public datasets
│ Hermes (acquire → validate → normalize)
▼
Canonical datasets (parquet-backed, cacheable)
│ query / transform / export
▼
pandas · polars · arrow · duckdb · numpy
│ features / ML / dashboards / apps
▼
Your applicationsBecause everything upstream shares one shape, the tools you already know keep working — Hermes just makes the messy part reliable.
What is implemented today (v0.2.14)
Rather than a complete-from-day-one platform, Hermes ships a fully working foundation and builds the rest out over time. Today the working, tested core is:
- The Hermes facade — wires up every connector, feature group and cache.
- 10 source connectors (World Bank, IMF, FRED, GDELT, Binance, Finnhub, yfinance, SEC EDGAR, OpenSanctions, bundled public datasets).
- The feature engine — a tiered, dependency-aware registry with lineage tracking.
- Country-risk features (economic, environmental, geopolitical, security, social).
- Financial features (technical, fundamental, crypto history, company filings).
- RawCache — per-source parquet-backed caching with TTLs and hit/miss stats.
- A cron/interval asyncio scheduler.
- Entity helpers — 249 ISO-3 countries and ticker→CIK company mapping.
parsing, normalization, validation, schemas, metadata, query, storage, api) exist as scaffolded packages and are built out progressively. The long-form public API (composable hr.fetch().parse().normalize()) is the target architecture; see the roadmap.The Hermes ecosystem
Hermes Core stays small and general. Specialized capability ships as separate packages (Finance, Defense, Healthcare, Trade, Energy, Climate, Geopolitics, Corporate, Entity, Features, Connectors) so a finance developer never installs defense infrastructure:
Hermes Core
├── Hermes Finance
├── Hermes Defense
├── Hermes Healthcare
├── Hermes Trade
├── Hermes Energy
├── Hermes Climate
├── Hermes Geopolitics
├── Hermes Corporate
├── Hermes Entity
├── Hermes Features
└── Hermes ConnectorsThe dependency rule is strict: Core must not depend on any domain package. Domain knowledge (resolvers, canonical schemas, features) is layered on top.
Package layout
hermes/
├── __init__.py # Hermes facade
├── constants.py # SYMBOLS, TICKERS, CANONICAL_FREQS, interval maps
├── acquisition/ # RawCache, Client
├── connectors/ # binance, finnhub, fred, gdelt, imf,
│ # opensanctions, public_data, sec, world_bank, yfinance
├── core/ # Dataset, scheduler, lineage/provenance/metadata stubs
├── entities/ # countries, companies
├── features/
│ ├── country_risk_features/ # economic, environmental, geopolitical, security, social
│ └── financial/ # technical, fundamental (crpto), filling, stocks
├── api|datasets|metadata|normalization|parsing|query|
│ schemas|storage|validation # (scaffolded, being built out)
└── export/ # export helpersWorks with your data stack
| Tool | Hermes integration |
|---|---|
| Pandas | DataFrame conversion |
| Polars | DataFrame conversion |
| PyArrow | Arrow data interchange |
| DuckDB | Analytical querying |
| NumPy | Numerical processing |
| Parquet | Dataset storage |
| SQL databases | Ingestion and export |
| ML frameworks | ML-ready datasets |
Philosophy
- Data should be composable — datasets from different sources work together.
- Data should be inspectable — know what you received before building on it.
- Data should be reproducible — the same pipeline repeats predictably.
- Data should be traceable — every dataset has a clear origin.
- Data should be interoperable — work with the ecosystem, not lock you in.
- Data infrastructure should be reusable — across domains.
Next: install and run
pip install hermes-pltFollow the Quickstart for a full walkthrough of the facade, fetching and computing features.