Hermes Financial
An open-source framework for building AI investment research systems.
Hermes is the reusable Python framework a developer reaches for when building professional AI investment-research applications. It ships pre-built financial data tools, document ingestion pipelines, output generation (Excel models, Word/PDF reports, charts), composable agents, and the infrastructure you need to make those agents reliable, observable, and extensible.
Hermes does not answer "what should I buy?" — that question belongs to your application, your strategy, and your judgment. What it answers:
"How do I give AI agents the tools, data, workflows, provenance, and output infrastructure needed to perform serious investment research?"
A downstream application can use Hermes as its research substrate without modifying Hermes itself — registering custom agents, workflows, tools, storage adapters, and event sinks.
Quick Start
pip install hermes-financial
import asyncio
from hermes import Hermes, configure
configure(
llm_provider="anthropic",
sec_user_agent="MyApp/1.0 (me@company.com)", # required by SEC
)
h = Hermes()
result = h.invoke("Research Apple's latest quarter")
print(result["response"])
The default invoke() returns a dict; for richer output use
await h.run_structured(...) to receive a ResearchResult (see
Structured outputs).
What's Included
Data Tools (free, no proprietary keys required for the basics)
| Module | What you get | Source |
|---|---|---|
| SEC EDGAR | Company facts (XBRL), filing search, submissions, filing URLs, structured financial tables, labeled text sections (MD&A, Risk Factors, …), insider transactions, institutional holdings | edgartools + efts.sec.gov |
| FRED | Economic time series, series search, metadata | api.stlouisfed.org (free key) |
| Market Data | Quotes, historical OHLCV, batch quotes | Yahoo Finance |
| News | Company news, general financial news | RSS feeds |
| Excel | Create, write, read, format, formulas, charts, save .xlsx |
openpyxl |
| Documents | Create, headings, paragraphs, tables, images, save .docx, export PDF |
python-docx |
| Charts | Line, bar, waterfall, scatter, heatmap → PNG | matplotlib |
Specialist Agents (7 built-in)
| Agent | Type | Role |
|---|---|---|
SecFilingsAgent |
FunctionAgent | SEC filing retrieval & analysis |
MacroAgent |
FunctionAgent | FRED macroeconomic data |
MarketDataAgent |
FunctionAgent | Quotes and historical prices |
NewsAgent |
FunctionAgent | News/sentiment |
ModelingAgent |
ReActAgent | Excel financial model construction |
ReportAgent |
ReActAgent | Word/PDF report generation |
ResearchOrchestrator |
FunctionAgent | Multi-agent coordination |
Architecture (since 0.2.0)
hermes/
├── agents/ # Specialist agents (built-in + custom HermesAgent subclasses)
├── workflows/ # ResearchWorkflow / EquityResearchWorkflow + HermesWorkflow protocol
├── tools/ # Data + output tools, each exposes create_tools()
├── schemas/ # Source, Evidence, ResearchArtifact, ResearchRun, ResearchResult,
│ # CompanyProfile, FinancialAnalysis, ValuationAnalysis, CompanyResearch
├── provenance/ # ProvenanceCollector + current_collector() contextvar
├── storage/ # ResearchStore / ArtifactStore protocols + in-memory + local impls
├── ingestion/ # Optional: filing / transcript parsers + ChromaDB RAG (rag extra)
├── infra/ # Cache, rate limiter, retry, streaming events
├── config.py # Pydantic HermesConfig (HERMES_ env prefix)
├── llm_providers.py # Provider registry (10 built-in + openai_compatible + openrouter)
├── registry.py # Tool/agent/workflow registry (per Hermes instance)
└── core.py # The Hermes facade
Configuration
All settings are accepted as kwargs to configure() or via environment
variables with the HERMES_ prefix:
from hermes import Hermes, configure
configure(
llm_provider="anthropic", # or openai, google, ollama, ...
llm_model="claude-sonnet-4-6",
sec_user_agent="MyApp/1.0 (me@company.com)",
fred_api_key="...",
verbose=True,
)
OpenAI-compatible endpoints (OpenRouter, vLLM, self-hosted)
Hermes ships a generic openai_compatible provider and a preconfigured
openrouter convenience. Set the base URL and key via config:
configure(
llm_provider="openai_compatible",
llm_model="my-model",
llm_api_base="https://internal.example.com/v1",
llm_api_key="...",
llm_context_window=32000, # optional
llm_is_function_calling_model=True, # optional
)
Or for OpenRouter:
configure(
llm_provider="openrouter",
llm_model="anthropic/claude-sonnet-4-5",
llm_api_key="...", # OpenRouter API key
)
Add your own providers at runtime:
from hermes.llm_providers import ProviderSpec, register_provider
register_provider(
ProviderSpec(
name="my_internal",
import_module="llama_index.llms.openai_like",
class_name="OpenAILike",
extra_kwargs={"api_base": "https://internal.example/v1"},
)
)
Extending Hermes
Custom agent
from hermes.agents.base import HermesAgent
from hermes import Hermes
class SupplyChainAgent(HermesAgent):
name = "supply_chain"
description = "Analyzes supplier concentration and logistics risks."
system_prompt = "You are a supply chain analyst..."
agent_type = "function"
def get_tools(self):
return [...]
h = Hermes()
h.register_agent("supply_chain", SupplyChainAgent)
Custom workflow
A workflow composes a root agent with a set of specialists and decides
how they hand off. Built-in EquityResearchWorkflow is the default;
you can compose your own with ResearchWorkflow (or any class
implementing the HermesWorkflow protocol):
from hermes import Hermes
from hermes.workflows import ResearchWorkflow
workflow = ResearchWorkflow(
root_agent="orchestrator",
agents=[
"sec_filings",
"market_data",
SupplyChainAgent(),
],
)
h = Hermes()
result = await h.run("Research NVDA", workflow=workflow)
See examples/custom_workflow.py.
Per-agent LLM overrides (cost / latency / quality)
from hermes.workflows import ResearchWorkflow
workflow = ResearchWorkflow(
agent_llms={
"sec_filings": cheap_llm, # fast/cheap model for data extraction
"modeling": strong_llm, # strongest model for the model agent
"report": writing_llm, # different model for prose
},
)
Structured outputs
run_structured() returns a ResearchResult with a full ResearchRun
record: participating agents, provider/model, status, timestamps,
sources, and artifacts. Failures don't raise — they return
ResearchResult with run.status = failed and run.error set.
result = await h.run_structured("Research AMBA")
print(result.response)
print(result.run.agents)
print(result.run.sources)
See examples/structured_results.py.
Event sinks
Hermes(event_sinks=[...]) fans every event (workflow started,
agent output, tool call, artifact created, …) out to every callable
sink. Async sinks are scheduled; sync sinks block. Sink exceptions are
logged but don't abort the run.
def my_sink(event):
print(f"[{event.run_id}] {event.type}: {event.text or event.metadata}")
h = Hermes(event_sinks=[my_sink])
Storage
By default runs live in memory. Replace with a local-disk or remote implementation:
from hermes import Hermes
from hermes.storage import LocalResearchStore
h = Hermes(research_store=LocalResearchStore("~/.hermes/runs"))
Implement the ResearchStore / ArtifactStore protocols to plug in
your own backend (D1, R2, S3, Postgres, …).
See examples/storage_adapter.py.
Custom tools (registry-based)
from llama_index.core.tools import FunctionTool
from hermes import Hermes
tool = FunctionTool.from_defaults(fn=my_lookup, name="my_lookup")
h = Hermes()
h.register_tool("my_lookup", tool, tags=["custom"])
Custom agents can pull registered tools by name via the
HermesAgent.tool_names class attribute — no need to import the
module that created them.
Using Tools Directly
You don't need agents to use the tools. Every tool module exposes async functions that work standalone:
from hermes.tools.sec_edgar import (
get_company_facts,
get_filing_urls,
get_filing_financial_tables,
get_filing_text,
)
from hermes.tools.fred import get_series
from hermes.tools.excel import excel_create_workbook, excel_write_cells, excel_save
facts = await get_company_facts("AAPL")
filings = await get_filing_urls("AAPL", filing_types="10-K,10-Q", limit=10)
tables = await get_filing_financial_tables("AAPL", filings[0]["accessionNumber"])
text = await get_filing_text(filings[0]["url"])
gdp = await get_series("GDP", start_date="2020-01-01")
Optional Extras
| Extra | What it adds | Install |
|---|---|---|
rag |
ChromaDB-backed semantic search over filings/transcripts/user documents | pip install hermes-financial[rag] |
google, mistral, groq, ollama, huggingface, cohere, deepseek, xai |
Corresponding LLM provider | pip install hermes-financial[google] (etc.) |
llamaparse |
LlamaParse for parsing PDFs | pip install hermes-financial[llamaparse] |
web |
Web page readers | pip install hermes-financial[web] |
pandas |
Pandas-shaped returns | pip install hermes-financial[pandas] |
dev |
Test/lint/type tooling | pip install hermes-financial[dev] |
all |
Everything above | pip install hermes-financial[all] |
Documentation
docs/providers.md— provider configuration, custom providers, OpenRouterdocs/workflows.md— composing custom workflowsdocs/agents.md— custom agents andtool_namesdocs/storage.md— custom ResearchStore / ArtifactStoredocs/events.md— event vocabulary and sinksdocs/provenance.md— source/evidence provenancedocs/schemas.md— structured outputs
Development
git clone https://github.com/hermes-financial/hermes-financial.git
cd hermes-financial
uv sync --all-extras
uv run pytest # 340+ tests
uv run ruff check hermes/ tests/
uv run mypy hermes/
Requirements
- Python >= 3.10
- An LLM API key (Anthropic, OpenAI, OpenRouter, …) for agent functionality
- SEC EDGAR requires a
User-Agentstring identifying your application - FRED requires a free API key from fred.stlouisfed.org
License
MIT — see LICENSE.
Hermes is the research framework. Downstream applications are the investors.
Metadata
Release files for hermes-financial 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| hermes_financial-0.2.0.tar.gz | 585.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| hermes_financial-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 708.1 kB
Release files / hermes_financial-0.2.0.tar.gz
| Download URL | hermes_financial-0.2.0.tar.gz |
|---|---|
| Size | 585.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1a3d8cd7a93fa178207b0dca53a77be2241d1c29c28a9ddbf0073f79c3e36836
|
|
BLAKE2b-256 checksum How to use checksums |
3f6aacd655b8c40bd9aeb877f92ab4d1ee7ce0d045a71f219839569d54addd89
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.14 {"installer":{"name":"uv","version":"0.9.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / hermes_financial-0.2.0-py3-none-any.whl
| Download URL | hermes_financial-0.2.0-py3-none-any.whl |
|---|---|
| Size | 122.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
71e1292f61105aeb7ebf8155ef21a4e42962acc72b3d1e192732d67260152ed9
|
|
BLAKE2b-256 checksum How to use checksums |
3d2d0947b560d482a3fec2a30182fdcd37550d6156dd0384b095f243f0a82395
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.14 {"installer":{"name":"uv","version":"0.9.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|