hermes-agent/website/docs/reference/model-catalog.md
Teknium 75ca29fb21
feat(models): add moonshotai/kimi-k3 to Nous Portal and OpenRouter curated lists, retire kimi-k2.x (#65913)
Replaces moonshotai/kimi-k2.6 (recommended) and moonshotai/kimi-k2.7-code
with moonshotai/kimi-k3 in both curated lists, regenerates the published
model-catalog.json manifest, and updates the docs example manifest (en+zh).

kimi-k3 verified live on both endpoints (Nous Portal /v1/models and
OpenRouter /api/v1/models; 1M context, $3/$15 per Mtok). Family-prefix
matching already covers k3 in moonshot_schema, cache policy, and context
heuristics — no code changes needed there.
2026-07-16 13:08:48 -07:00

106 lines
4.6 KiB
Markdown

---
sidebar_position: 11
title: Model Catalog
description: Remotely-hosted manifest driving curated model picker lists for OpenRouter and Nous Portal.
---
# Model Catalog
Hermes fetches curated model lists for **OpenRouter** and **Nous Portal** from a JSON manifest hosted alongside the docs site. This lets maintainers update picker lists without shipping a new `hermes-agent` release.
When the manifest is unreachable (offline, network blocked, hosting failure), Hermes silently falls back to the in-repo snapshot that ships with the CLI. The manifest never breaks the picker — worst case you see whatever list was bundled with your installed version.
## Live manifest URL
```
https://hermes-agent.nousresearch.com/docs/api/model-catalog.json
```
Published on every merge to `main` via the existing `deploy-site.yml` GitHub Pages pipeline. The source of truth lives in the repo at `website/static/api/model-catalog.json`.
## Schema
```json
{
"version": 1,
"updated_at": "2026-04-25T22:00:00Z",
"metadata": {},
"providers": {
"openrouter": {
"metadata": {},
"models": [
{"id": "z-ai/glm-5.2", "description": "default", "default": true},
{"id": "moonshotai/kimi-k3", "description": "recommended", "metadata": {}},
{"id": "openai/gpt-5.4", "description": ""}
]
},
"nous": {
"metadata": {},
"models": [
{"id": "z-ai/glm-5.2", "default": true},
{"id": "anthropic/claude-opus-4.7"},
{"id": "moonshotai/kimi-k3"}
]
}
}
}
```
Field notes:
- **`version`** — integer schema version. Future schemas bump this; Hermes refuses manifests with versions it doesn't understand and falls back to the hardcoded snapshot.
- **`metadata`** — free-form dict at the manifest, provider, and model level. Any keys. Hermes ignores unknown fields, so you can annotate entries (`"tier": "paid"`, `"tags": [...]`, etc.) without coordinating a schema change.
- **`description`** — OpenRouter-only. Drives picker badge text (`"recommended"`, `"free"`, `"default"`, or empty). Nous Portal doesn't use this — free-tier gating is determined live from the Portal's pricing endpoint.
- **`default`** — exactly one entry per provider may carry `"default": true`. That model is the **silent default**: what Hermes lands on when the user never selected a model (GUI onboarding confirm card, `provider` configured with no `model`, empty `model.default`). Read cache-only at runtime (`get_default_model_from_cache`) so hot resolution paths never hit the network; when no cached manifest exists, Hermes falls back to the in-repo `PREFERRED_SILENT_DEFAULT_MODEL` constant, which must match the labeled entry. This lets maintainers rotate the silent default without shipping a release. It is deliberately a capable low-cost model, never the priciest flagship.
- **Pricing and context length** are NOT in the manifest. Those come from live provider APIs (`/v1/models` endpoints, models.dev) at fetch time.
## Fetch behavior
| When | What happens |
|---|---|
| `/model` or `hermes model` | Fetches if disk cache is stale, else uses cache |
| Disk cache fresh (< TTL) | No network hit |
| Network failure with cache | Silent fallback to cache, one log line |
| Network failure, no cache | Silent fallback to in-repo snapshot |
| Manifest fails schema validation | Treated as unreachable |
Cache location: `~/.hermes/cache/model_catalog.json`.
## Config
```yaml
model_catalog:
enabled: true
url: https://hermes-agent.nousresearch.com/docs/api/model-catalog.json
ttl_hours: 1
providers: {}
```
Set `enabled: false` to disable remote fetch entirely and always use the in-repo snapshot.
### Per-provider override URLs
Third parties can self-host their own curation list using the same schema. Point a provider at a custom URL:
```yaml
model_catalog:
providers:
openrouter:
url: https://example.com/my-openrouter-curation.json
```
The overriding manifest only needs to populate the provider block(s) it cares about. Other providers continue to resolve against the master URL.
## Updating the manifest
Maintainers:
```bash
# Re-generate from the in-repo hardcoded lists (keeps manifest in sync after
# editing OPENROUTER_MODELS or _PROVIDER_MODELS["nous"] in hermes_cli/models.py).
python scripts/build_model_catalog.py
```
Then PR the resulting change to `website/static/api/model-catalog.json` to `main`. The docs site auto-deploys on merge and the new manifest is live within a few minutes.
You can also hand-edit the JSON directly for fine-grained metadata changes that don't belong in the in-repo snapshot the generator script is a convenience, not the single source of truth.