Hermes Architecture Reference
System topology
Profile registry
| CLI | hermes (default profile) |
|---|---|
| HERMES_HOME | ~/.hermes |
| Workspace | /Users/gkuruvilla/chief-of-staff |
| Purpose | Strategy, ops cadence, calendar/email triage, 1:1 prep, travel, talent, faith |
| Context files | soul.md, AGENTS.md, USER.md, MEMORY.md |
| RAG collection | jess_knowledge (shared with Jess) |
| Cron jobs | 10 |
| CLI | jess |
|---|---|
| HERMES_HOME | ~/.hermes/profiles/jess |
| Workspace | .../chief-of-staff/jess |
| Purpose | Competitive research, LinkedIn/blog drafts, deal hunter, breaking news |
| Scripts | deals_run.py, news_run.py (no_agent cron) |
| Engines | ~/.hermes/mcp-servers/deals.py, news.py |
| RAG | jess_knowledge (44 chunks) |
| Cron jobs | 4 |
| CLI | jackie |
|---|---|
| Workspace | .../chief-of-staff/jackie |
| Purpose | Personal financial advisor — net worth, 529, retirement, holdings (non-fiduciary) |
| Model | gpt-5.5 via openai-codex (main + auxiliary + cron, pinned) |
| Delivery | Slack C0BF91FFM1P + Telegram 5946547528 |
| RAG | jackie_knowledge |
| Cron jobs | 2 — daily portfolio (7 AM) + weekday news scan (9–4 CT every 2h) |
| CLI | amit |
|---|---|
| Workspace | .../chief-of-staff/amit |
| Purpose | College & pre-med counselor for Gabriella (Gaby), Class of 2029, Benet Academy |
| Targets | UChicago, Northwestern, Notre Dame, UIUC · top-25 · merit scholarships |
| RAG | amit_knowledge (20 chunks) |
| Cron | None yet |
Integrations matrix
| Capability | Tool | default | jess | jackie | amit | Rule |
|---|---|---|---|---|---|---|
| Calendar | gws calendar | yes | yes | yes | yes | Never Granola for schedule |
| Gmail | gws gmail | yes | yes | yes | yes | Never himalaya |
| Drive/Docs/Sheets | gws | yes | yes | yes | yes | — |
| Meeting notes | Granola MCP | yes | yes | yes | yes | Past meetings only |
| Web research | Firecrawl + web | yes | yes | yes | yes | Cite URLs |
| Semantic memory | Qdrant RAG | jess_kn | jess_kn | jackie_kn | amit_kn | Separate collections |
| Deal alerts | deals.py | no | yes | no | no | [SILENT] default |
| News alerts | news.py | no | yes | no | no | Dedup + recency |
| Telegram | Bot token | holds | lock | lock | varies | One holder per token |
| Slack | App token | holds | lock | holds | lock | One holder per token |
Model stack (hybrid)
| Profile | Primary LLM | Use case |
|---|---|---|
| default (CoS) | qwen3-coder:30b · Ollama | Volume cron — plans, triage, 1:1 prep |
| jess | qwen3-coder:30b · Ollama | Research digest, drafts, no_agent deal/news scripts |
| jackie | gpt-5.5 · openai-codex | Finance quality — holdings analysis, citations, cron pinned |
| amit | qwen3-coder:30b · Ollama | College counseling on demand |
| Embeddings | nomic-embed-text · Ollama | Local RAG without external API |
| Vector DB | Qdrant | localhost:6333 |
| Web scrape | Firecrawl + SearXNG | localhost:3002 / :8080 |
Scheduled tasks (16 total)
Chief of Staff — default (10)
| Schedule (CT) | Job | Integrations |
|---|---|---|
| 6:00 AM daily | Daily Action Plan (w1) | gws calendar, gmail, Granola, MEMORY |
| 6:00 AM daily | Birthday alerts | Document cache |
| 6:30 AM daily | Morning devotional (fa1) | Web |
| 7:00 AM daily | 1:1 agenda builder (p2) | gws calendar, Granola |
| 8:00 AM daily | Personal Gmail triage (f4) | gws gmail |
| 4:00 PM Fri | Sustainable schedule audit (h3) | gws calendar |
| 6:00 PM Sun | UT Austin AI PG bodyguard (k2) | gws calendar |
| 8:00 PM Sun | Tri-zone travel brief (t1) | gws calendar |
| 9:00 AM Sat | Personal research compounding (k3) | Web, knowledge-log |
| 8:00 AM 1st/month | Talent watchlist (p1) | Granola, MEMORY |
Jess (4)
| Schedule | Job | Type |
|---|---|---|
| 5:00 AM daily | Daily research digest | LLM agent → deliver all |
| 7:30 AM daily | Daily post drafts | LLM agent → deliver all |
| 0 */3 * * * | Deal hunter | no_agent → deals_run.py → deals.py |
| 0 * * * * | Company news watch | no_agent → news_run.py → news.py |
Jackie (2)
| Schedule (CT) | Job | Model / delivery |
|---|---|---|
| 7:00 AM daily | Daily portfolio & investment report | gpt-5.5 Codex → Slack + Telegram |
| 9, 11, 1, 3 PM weekdays | Holdings news alert scan | gpt-5.5 Codex → Slack + Telegram · [SILENT] default |
Deterministic alert pipelines (Jess)
Deal hunter
watchlist.json→
Slickdeals→
Firecrawl→
observations.json→
deals.py→
Alert|
[SILENT]
Policy: 20% off list · target/alert_below · new-low · 12h cooldown · 22 watchlist items
News watch
watchlist.json→
Google News RSS→
Domain filter→
observations.json→
news.py→
Alert once|
[SILENT]
RAG knowledge base
| Collection | Profile(s) | Chunks | Contents |
|---|---|---|---|
| jess_knowledge | default, jess | 44 | Research logs, competitive intel, George voice corpus |
| jackie_knowledge | jackie | 12 | Financial snapshots, planning context |
| amit_knowledge | amit | 20 | Counseling roadmap, school strategy, AGENTS |
Decision: CoS shares jess_knowledge so morning briefs can recall research without duplicate ingestion.
Architecture decision records
ADR-1: Multi-profile over monolith
Decision: Four isolated profiles.
Why: Context bleed between work, finance, family.
Trade-off: Slack/Telegram token contention across gateways.
Why: Context bleed between work, finance, family.
Trade-off: Slack/Telegram token contention across gateways.
ADR-2: gws canonical for Google
Decision: gws only; Granola for past notes only.
Why: Mixed sources produced wrong calendar answers.
Enforced in: Every AGENTS.md hard rules block.
Why: Mixed sources produced wrong calendar answers.
Enforced in: Every AGENTS.md hard rules block.
ADR-3: Deterministic alert engines
Decision: deals.py + news.py with [SILENT] contract.
Why: LLM hallucinated prices and re-sent duplicate news.
Pattern: no_agent cron → Python script → engine → stdout drives delivery.
Why: LLM hallucinated prices and re-sent duplicate news.
Pattern: no_agent cron → Python script → engine → stdout drives delivery.
ADR-4: SOUL + AGENTS separation
Decision: Persona in SOUL.md; playbook in AGENTS.md.
Why: Clone profiles (Jackie, Amit) without mixing voice and tool routing.
Why: Clone profiles (Jackie, Amit) without mixing voice and tool routing.
ADR-5: Local-first stack
Decision: Ollama + Qdrant + Firecrawl on Mac; Jackie on Codex GPT-5.5.
Why: Privacy and $0 marginal cost for 14 local cron jobs; finance quality needs cloud.
Trade-off: Host must stay on; Jackie depends on Codex OAuth.
Why: Privacy and $0 marginal cost for 14 local cron jobs; finance quality needs cloud.
Trade-off: Host must stay on; Jackie depends on Codex OAuth.
ADR-7: Jackie on Codex GPT-5.5
Decision: Pin gpt-5.5 / openai-codex on Jackie profile and both cron jobs.
Why: Holdings analysis needs citation discipline local 30B can't match.
Pattern: model + provider fields in cron jobs.json; OAuth via ChatGPT Codex.
Why: Holdings analysis needs citation discipline local 30B can't match.
Pattern: model + provider fields in cron jobs.json; OAuth via ChatGPT Codex.
ADR-8: Dual delivery (Slack + Telegram)
Decision: Jackie cron deliver array: slack:C0BF91FFM1P + telegram:5946547528.
Why: Portfolio report delivered to Slack but wasn't seen; redundancy reduces miss rate.
Pattern: Hermes multi-deliver JSON array on cron jobs.
Why: Portfolio report delivered to Slack but wasn't seen; redundancy reduces miss rate.
Pattern: Hermes multi-deliver JSON array on cron jobs.
ADR-6: Research compounding
Decision: knowledge_search before sweeps; ingest.py on logs nightly.
Why: Stop re-researching the same Wrike/competitor news weekly.
Why: Stop re-researching the same Wrike/competitor news weekly.
Directory map
~/.hermes/ # default (Chief of Staff)
├── config.yaml, cron/jobs.json # 10 CoS jobs
├── google_token.json # Shared OAuth
├── mcp-servers/
│ ├── deals.py, news.py # Deterministic engines
│ ├── rag_server.py, ingest.py
└── profiles/
├── jess/ # Research + alerts
│ ├── scripts/deals_run.py, news_run.py
│ └── cron/jobs.json # 4 jobs
├── jackie/ # Finance
└── amit/ # College counselor
/Users/gkuruvilla/chief-of-staff/ # CoS workspace
├── soul.md, AGENTS.md, USER.md, MEMORY.md
├── jess/deals/, jess/news/ # Watchlists + state
├── jackie/
└── amit/planning/
Gateway & messaging
| Profile | Gateway | LaunchAgent |
|---|---|---|
| default | Running | ai.hermes.gateway.plist |
| jess | Running | ai.hermes.gateway-jess.plist |
| jackie | Running | ai.hermes.gateway-jackie.plist |
| amit | Running | ai.hermes.gateway-amit.plist |
Mitigation for token locks: dedicated Slack/Telegram bots per profile, CLI chat (jess chat), or gateway.multiplex_profiles on default.