OpenRouter MoA + Caching Strategy
Summary
Hermes Agent has a built-in MoA (Mixture of Agents) feature that runs reference models in parallel, then uses an aggregator to synthesize their output. When routed through OpenRouter, prompt caching behavior depends on whether OpenRouter routes consecutive requests to the same upstream provider node (sticky routing). This brief covers what works, what doesn’t, and when direct API calls are preferable.
Hermes MoA Architecture
MoA is a virtual model provider in Hermes. Each named preset appears as a selectable model under the moa provider. For example:
moa:
presets:
cross_analysis:
aggregator:
provider: openrouter
model: x-ai/grok-4.5
reference_models:
- provider: openrouter
model: moonshotai/kimi-k3
- provider: openrouter
model: deepseek/deepseek-v4-pro
reference_max_tokens: 600When a MoA preset is active, Hermes: 1. Resolves the preset by name 2. Runs reference models without tool schemas (text-only, cheap calls) 3. Appends reference outputs as private context for the aggregator 4. Calls the aggregator with full tool schema 5. Treats the aggregator’s response as the real model response
Invoked via /model mypreset --provider moa or /moa Analyze this....
OpenRouter Caching Mechanisms
OpenRouter offers three caching layers:
Response Caching
Identical full requests (same model, same messages, same parameters) are served from OpenRouter’s edge cache at zero cost. This is the simplest and most reliable cache – no configuration needed beyond:
openrouter:
response_cache: true
response_cache_ttl: 300Already enabled in current Hermes config.
Prompt Caching (Implicit)
Providers like DeepSeek, Google, and OpenAI cache common prompt prefixes automatically. Cache reads cost 0.1x to 0.5x of fresh input. OpenRouter passes through the reduced pricing.
Requires sticky routing: consecutive requests must hit the same upstream provider node. Without it, each request may land on a cold node and miss the cached prefix.
Prompt Caching (Explicit)
Anthropic requires explicit cache_control breakpoints in the request body. OpenRouter passes these through if your client sends them. Hermes currently does not set Anthropic cache breakpoints through the OpenRouter provider.
Session ID Sticky Routing
OpenRouter uses session_id (in request body) or x-session-id (HTTP header) to pin a session to a single upstream provider node.
The Git commit 4c64ff3 confirmed OpenRouter already had session_id passthrough for main model calls. The PR #70883 extended this to auxiliary and async call paths.
Table.1.StickyRoutingStatus
| Call type | Session ID sent? | Cache works? |
|---|---|---|
| Main model (OpenRouter provider) | Yes (built-in) | Yes |
| MoA reference calls | Inherits from session | Yes |
| MoA aggregator calls | Inherits from session | Yes |
| Auxiliary models (vision, compress) | After PR#70883 | Partial |
hermes chat -q one-shot |
No | No |
Current Hermes v0.16.0 sends session_id to OpenRouter for the main model call path. MoA reference and aggregator calls inherit this. The fix in PR #70883 (submitted Jul 24, 2026) extends coverage to auxiliary/async paths.
MoA and Caching Interaction
MoA creates multiple model calls per turn (one per reference model + one aggregator). Without sticky routing, each call could hit a different upstream node, each requiring a fresh cache write.
With sticky routing (currently active for main call path):
| Turn | Request | Cache status |
|---|---|---|
| 1 | Reference model A | Cold write |
| 1 | Reference model B | Cold write |
| 1 | Aggregator | Cold write |
| 2 | Reference model A | Warm read (0.5x cost) |
| 2 | Reference model B | Warm read (0.5x cost) |
| 2 | Aggregator | Warm read (0.5x cost) |
After the first turn, all subsequent turns benefit from cache reads.
Direct API vs OpenRouter: When Each Wins
Table.2.DirectVsOpenRouter
| Factor | Direct API | OpenRouter | Winner |
|---|---|---|---|
| Prompt caching | Native (no intermediary) | Pass-through + sticky routing | Direct |
| Response caching | Provider-specific | Global edge cache at zero cost | OpenRouter |
| Multi-provider fallback | No | Yes | OpenRouter |
| Provider markup | None | 5-15% on some models | Direct |
| Single API key | No (one per provider) | Yes (one key) | OpenRouter |
| Latency | Lowest | +50-200ms routing | Direct |
| DeepSeek V4 Flash price | $0.09/$0.18 (DeepInfra) | $0.09/$0.19 (same) | Tie |
For DeepSeek (already configured as direct provider), there is no benefit to routing through OpenRouter – same price, lower latency, native caching.
For x.ai (Grok) and Moonshot (Kimi), the trade-off is convenience vs marginal caching benefit. OpenRouter adds sticky routing and response caching at the cost of ~5-15% markup.
Recommendation
For the user’s three primary outputs (coding, comics, essays):
- DeepSeek: use direct API (already configured). Same price, native caching.
- Claude: use Claude Code via Pro subscription ($20/mo flat rate for Claude Sonnet 4.6+). No per-token billing.
- x.ai / Moonshot / other providers: route through OpenRouter for unified billing and response caching. The sticky routing provides adequate prompt caching for all uses except the most cache-sensitive workloads.
- MoA: use for deep research synthesis only (rare). Cost per call is higher due to multiple reference models. Not recommended for daily coding.
Compiled 2026-07-27 from Hermes Agent docs v0.16.0, OpenRouter API docs, and investigation of git commits 4c64ff3 and PR#70883.
[No columns defined in frontmatter]
Want to stay in touch? You can reach me in a variety of ways from my Contact page.