Agent harness
Hermes Agent
Give Hermes Agent memory that survives the session. Declare the Korely MCP server in your profile with a static API-key header, no OAuth dance, no package to install, just your key.
Hermes Agent (Nous Research) keeps its own memory files, loaded at the start of each session. Connect Korely's MCP server and, before answering, Hermes can also pull the active typed facts and relevant memories it has stored, and write new ones as it learns. The intelligence, entity and typed-fact extraction, contradiction resolution, bi-temporal validity, runs server-side. Hermes just calls the tools.
Prerequisites
- A Korely API key (
kor_live_...). The hobby tier is free. - Hermes Agent installed (run
hermes setupto configure it).
Add the Korely MCP server
Korely's agent memory is a remote MCP server at
https://api.korely.ai/agent/mcp over Streamable HTTP, authenticated
with your key in a header, no browser login. Add it with the CLI:
hermes mcp add korely --url https://api.korely.ai/agent/mcp --auth header
The --url flag tells Hermes this is a remote HTTP server (vs
--command for stdio), and --auth header selects
static-header auth instead of OAuth. The command asks whether the server
needs authentication and for your key, saves the key in the profile's
.env as MCP_KORELY_API_KEY, writes
Authorization: "Bearer ${MCP_KORELY_API_KEY}" into the
profile's config.yaml, connects, and asks which tools to enable.
Or edit your profile's config.yaml directly, remote servers live under mcp_servers:, keyed by name:
mcp_servers: korely: url: "https://api.korely.ai/agent/mcp" headers: Authorization: "Bearer ${KORELY_API_KEY}"
A url field (rather than command) marks this as a
remote Streamable-HTTP server; the static bearer token is supplied via the
headers: mapping. Keep the key out of the file by storing it as a
placeholder and putting the real value in the profile's .env,
alongside config.yaml:
# <profile dir>/.env (~/.hermes/.env for the default profile)KORELY_API_KEY=kor_live_...
Hermes resolves ${KORELY_API_KEY} from the profile's
.env at connection time. You can also inline the literal key in
config.yaml if you prefer:
Authorization: "Bearer kor_live_...". The default profile's
directory is ~/.hermes/; a named profile's is
~/.hermes/profiles/<name>/. Run hermes profile list
to see which profile is active (it is marked with *).
What Hermes Agent can do
Once connected, Hermes Agent has four memory tools:
| Tool | What it does |
|---|---|
korely_get_context | The recall path: assembles the active typed facts plus the most relevant memories into a prompt-ready block. Pure retrieval: the query is embedded once for the vector search, and no generative model runs on the read path. |
korely_add | Store a memory. Typed (subject, predicate, object) facts are extracted server-side, and a model judge closes the earlier fact, with its end date, when it decides a new one replaces it. |
korely_search | Semantic search over stored memories, ranked. |
korely_get_facts | The typed bi-temporal facts known about a user, with point-in-time queries: as_of (what was true then) and known_as_of (what the store knew then). |
Use it
Now Hermes reaches for memory on its own. Tell it something durable and it
calls korely_add; ask it something personal and it calls
korely_get_context first:
You › Remember that this repo deploys to Hetzner, not Render. → korely_add("This repo deploys to Hetzner, not Render")
# next session, days laterYou › How do we deploy this? → korely_get_context("deploy") → "This repo deploys to Hetzner..."Hermes › This repo deploys to Hetzner (you told me earlier), not Render. ...Scoping
Every tool accepts an optional user_id so one key can serve many
end users: a read that names "user-b" never returns a memory
written for "user-a". It's a tool argument the agent passes at
call time, not a config field, so no config.yaml change is
needed. Omit it on a write and the memory belongs to no end user (a key
confined to one end user writes to that one). Omit it on a read and the
read covers every end user the key can see.
Why this is more than a notepad. Korely keeps each memory's
text as written and also extracts typed facts with
bi-temporal validity from it. When something changes ("this repo now deploys to Hetzner, not Render"), the judge closes the old
fact with its end date instead of overwriting it, so korely_get_context returns
what's true now, and as_of can still replay what was
true before. EU-hosted.
Related
- Korely MCP, the full MCP surface and other clients.
- Get context, the call behind
korely_get_context. - Memory as a tool, the same pattern when you build the agent loop yourself.