Skip to content

feat(api-server): X-Hermes-Session-Key header for long-term memory scoping#20199

Merged
teknium1 merged 2 commits into
mainfrom
hermes/hermes-b261eed9
May 5, 2026
Merged

feat(api-server): X-Hermes-Session-Key header for long-term memory scoping#20199
teknium1 merged 2 commits into
mainfrom
hermes/hermes-b261eed9

Conversation

@teknium1

@teknium1 teknium1 commented May 5, 2026

Copy link
Copy Markdown
Contributor

API Server integrations (Open WebUI, third-party web UIs) can now pass a stable per-channel identifier via X-Hermes-Session-Key that scopes long-term memory (Honcho, etc.) independently of the transcript-scoped X-Hermes-Session-Id. One stable key per assistant channel, many transcripts that rotate on /new — matching the native gateway's session_key / session_id split.

Closes #20060.

Changes

  • _create_agent / _run_agent: new gateway_session_key kwarg threaded into AIAgent(gateway_session_key=...), which was already honored by the Honcho memory provider (plugins/memory/honcho/client.py::resolve_session_name). No other plumbing needed — the receiving end was complete.
  • _parse_session_key_header: shared helper with the same API-key gate, \r\n\x00 rejection, and a 256-char length cap as the existing session-id header.
  • _handle_chat_completions, _handle_responses, _handle_runs: all three agent endpoints honor the header.
  • JSON + SSE responses echo X-Hermes-Session-Key back.
  • /v1/capabilities advertises session_key_header so clients can feature-detect.

Validation

Before After
X-Hermes-Session-Key reaches AIAgent(gateway_session_key=...) dropped threaded through
Honcho scope stable when session_id rotates (/new) no yes
/v1/capabilities advertises session-key header "session_key_header": "X-Hermes-Session-Key"
  • 9 new tests in TestSessionKeyHeader (passed + echoed, independent of session-id, absent-yields-none, rejected without API key, control-char sanitization, length cap, threads through _create_agent, /v1/responses accepts it, capabilities advertises).
  • Full tests/gateway/test_api_server.py + test_proxy_mode.py suite: 157 passed.
  • E2E verified with real imports + isolated HERMES_HOME: HTTP X-Hermes-Session-Key: agent:main:webui:dm:user-42AIAgent(gateway_session_key=...)HonchoClientConfig.resolve_session_name() returns the same stable agent-main-webui-dm-user-42 scope regardless of whether session_id is transcript-alpha or transcript-BETA. Without the key, Honcho's per-session strategy correctly produces two different scopes for the two ids — confirming the key is doing the stabilization, not something else.

Client usage

POST /v1/chat/completions
Authorization: Bearer $API_SERVER_KEY
X-Hermes-Session-Key: agent:main:webui:dm:user-42   # stable per-channel → Honcho scope
X-Hermes-Session-Id: transcript-alpha                # rotates on /new → transcript

Credit to @manateelazycat for the diagnosis and the clean feature request in #20060.

teknium1 and others added 2 commits May 5, 2026 05:02
…oping

API Server integrations (Open WebUI, custom web UIs) can now pass a stable
per-channel identifier via X-Hermes-Session-Key that scopes long-term memory
(Honcho, etc.) independently of the transcript-scoped X-Hermes-Session-Id.
This matches the native gateway's session_key / session_id split: one stable
key per assistant channel, many independent transcripts that rotate on /new.

- _create_agent and _run_agent accept gateway_session_key and pass it to
  AIAgent(gateway_session_key=...), which is already honored by the Honcho
  memory provider (plugins/memory/honcho/client.py resolve_session_name).
- New shared helper _parse_session_key_header applies the same API-key
  gate, control-character sanitization, and a 256-char length cap as the
  existing session-id header.
- All three agent endpoints honor the header: /v1/chat/completions,
  /v1/responses, /v1/runs. JSON and SSE responses echo it back.
- /v1/capabilities advertises session_key_header so clients can
  feature-detect.

Closes #20060.

Co-authored-by: Andy Stewart <lazycat.manatee@gmail.com>
@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/gateway Gateway runner, session dispatch, delivery labels May 5, 2026
@teknium1 teknium1 merged commit fe8560f into main May 5, 2026
10 of 11 checks passed
@teknium1 teknium1 deleted the hermes/hermes-b261eed9 branch May 5, 2026 12:34
nickdlkk pushed a commit to nickdlkk/hermes-agent that referenced this pull request May 11, 2026
…oping (NousResearch#20199)

* feat(api-server): X-Hermes-Session-Key header for long-term memory scoping

API Server integrations (Open WebUI, custom web UIs) can now pass a stable
per-channel identifier via X-Hermes-Session-Key that scopes long-term memory
(Honcho, etc.) independently of the transcript-scoped X-Hermes-Session-Id.
This matches the native gateway's session_key / session_id split: one stable
key per assistant channel, many independent transcripts that rotate on /new.

- _create_agent and _run_agent accept gateway_session_key and pass it to
  AIAgent(gateway_session_key=...), which is already honored by the Honcho
  memory provider (plugins/memory/honcho/client.py resolve_session_name).
- New shared helper _parse_session_key_header applies the same API-key
  gate, control-character sanitization, and a 256-char length cap as the
  existing session-id header.
- All three agent endpoints honor the header: /v1/chat/completions,
  /v1/responses, /v1/runs. JSON and SSE responses echo it back.
- /v1/capabilities advertises session_key_header so clients can
  feature-detect.

Closes NousResearch#20060.

Co-authored-by: Andy Stewart <lazycat.manatee@gmail.com>

* chore: AUTHOR_MAP entry for manateelazycat

---------

Co-authored-by: Andy Stewart <lazycat.manatee@gmail.com>
rmulligan pushed a commit to rmulligan/hermes-agent that referenced this pull request May 11, 2026
…oping (NousResearch#20199)

* feat(api-server): X-Hermes-Session-Key header for long-term memory scoping

API Server integrations (Open WebUI, custom web UIs) can now pass a stable
per-channel identifier via X-Hermes-Session-Key that scopes long-term memory
(Honcho, etc.) independently of the transcript-scoped X-Hermes-Session-Id.
This matches the native gateway's session_key / session_id split: one stable
key per assistant channel, many independent transcripts that rotate on /new.

- _create_agent and _run_agent accept gateway_session_key and pass it to
  AIAgent(gateway_session_key=...), which is already honored by the Honcho
  memory provider (plugins/memory/honcho/client.py resolve_session_name).
- New shared helper _parse_session_key_header applies the same API-key
  gate, control-character sanitization, and a 256-char length cap as the
  existing session-id header.
- All three agent endpoints honor the header: /v1/chat/completions,
  /v1/responses, /v1/runs. JSON and SSE responses echo it back.
- /v1/capabilities advertises session_key_header so clients can
  feature-detect.

Closes NousResearch#20060.

Co-authored-by: Andy Stewart <lazycat.manatee@gmail.com>

* chore: AUTHOR_MAP entry for manateelazycat

---------

Co-authored-by: Andy Stewart <lazycat.manatee@gmail.com>
JinyuID pushed a commit to JinyuID/hermes-agent that referenced this pull request May 11, 2026
…oping (NousResearch#20199)

* feat(api-server): X-Hermes-Session-Key header for long-term memory scoping

API Server integrations (Open WebUI, custom web UIs) can now pass a stable
per-channel identifier via X-Hermes-Session-Key that scopes long-term memory
(Honcho, etc.) independently of the transcript-scoped X-Hermes-Session-Id.
This matches the native gateway's session_key / session_id split: one stable
key per assistant channel, many independent transcripts that rotate on /new.

- _create_agent and _run_agent accept gateway_session_key and pass it to
  AIAgent(gateway_session_key=...), which is already honored by the Honcho
  memory provider (plugins/memory/honcho/client.py resolve_session_name).
- New shared helper _parse_session_key_header applies the same API-key
  gate, control-character sanitization, and a 256-char length cap as the
  existing session-id header.
- All three agent endpoints honor the header: /v1/chat/completions,
  /v1/responses, /v1/runs. JSON and SSE responses echo it back.
- /v1/capabilities advertises session_key_header so clients can
  feature-detect.

Closes NousResearch#20060.

Co-authored-by: Andy Stewart <lazycat.manatee@gmail.com>

* chore: AUTHOR_MAP entry for manateelazycat

---------

Co-authored-by: Andy Stewart <lazycat.manatee@gmail.com>
02356abc pushed a commit to 02356abc/hermes-agent that referenced this pull request May 14, 2026
…oping (NousResearch#20199)

* feat(api-server): X-Hermes-Session-Key header for long-term memory scoping

API Server integrations (Open WebUI, custom web UIs) can now pass a stable
per-channel identifier via X-Hermes-Session-Key that scopes long-term memory
(Honcho, etc.) independently of the transcript-scoped X-Hermes-Session-Id.
This matches the native gateway's session_key / session_id split: one stable
key per assistant channel, many independent transcripts that rotate on /new.

- _create_agent and _run_agent accept gateway_session_key and pass it to
  AIAgent(gateway_session_key=...), which is already honored by the Honcho
  memory provider (plugins/memory/honcho/client.py resolve_session_name).
- New shared helper _parse_session_key_header applies the same API-key
  gate, control-character sanitization, and a 256-char length cap as the
  existing session-id header.
- All three agent endpoints honor the header: /v1/chat/completions,
  /v1/responses, /v1/runs. JSON and SSE responses echo it back.
- /v1/capabilities advertises session_key_header so clients can
  feature-detect.

Closes NousResearch#20060.

Co-authored-by: Andy Stewart <lazycat.manatee@gmail.com>

* chore: AUTHOR_MAP entry for manateelazycat

---------

Co-authored-by: Andy Stewart <lazycat.manatee@gmail.com>
jsboige pushed a commit to jsboige/hermes-agent that referenced this pull request May 14, 2026
…oping (NousResearch#20199)

* feat(api-server): X-Hermes-Session-Key header for long-term memory scoping

API Server integrations (Open WebUI, custom web UIs) can now pass a stable
per-channel identifier via X-Hermes-Session-Key that scopes long-term memory
(Honcho, etc.) independently of the transcript-scoped X-Hermes-Session-Id.
This matches the native gateway's session_key / session_id split: one stable
key per assistant channel, many independent transcripts that rotate on /new.

- _create_agent and _run_agent accept gateway_session_key and pass it to
  AIAgent(gateway_session_key=...), which is already honored by the Honcho
  memory provider (plugins/memory/honcho/client.py resolve_session_name).
- New shared helper _parse_session_key_header applies the same API-key
  gate, control-character sanitization, and a 256-char length cap as the
  existing session-id header.
- All three agent endpoints honor the header: /v1/chat/completions,
  /v1/responses, /v1/runs. JSON and SSE responses echo it back.
- /v1/capabilities advertises session_key_header so clients can
  feature-detect.

Closes NousResearch#20060.

Co-authored-by: Andy Stewart <lazycat.manatee@gmail.com>

* chore: AUTHOR_MAP entry for manateelazycat

---------

Co-authored-by: Andy Stewart <lazycat.manatee@gmail.com>
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
…oping (NousResearch#20199)

* feat(api-server): X-Hermes-Session-Key header for long-term memory scoping

API Server integrations (Open WebUI, custom web UIs) can now pass a stable
per-channel identifier via X-Hermes-Session-Key that scopes long-term memory
(Honcho, etc.) independently of the transcript-scoped X-Hermes-Session-Id.
This matches the native gateway's session_key / session_id split: one stable
key per assistant channel, many independent transcripts that rotate on /new.

- _create_agent and _run_agent accept gateway_session_key and pass it to
  AIAgent(gateway_session_key=...), which is already honored by the Honcho
  memory provider (plugins/memory/honcho/client.py resolve_session_name).
- New shared helper _parse_session_key_header applies the same API-key
  gate, control-character sanitization, and a 256-char length cap as the
  existing session-id header.
- All three agent endpoints honor the header: /v1/chat/completions,
  /v1/responses, /v1/runs. JSON and SSE responses echo it back.
- /v1/capabilities advertises session_key_header so clients can
  feature-detect.

Closes NousResearch#20060.

Co-authored-by: Andy Stewart <lazycat.manatee@gmail.com>

* chore: AUTHOR_MAP entry for manateelazycat

---------

Co-authored-by: Andy Stewart <lazycat.manatee@gmail.com>
gsskk added a commit to gsskk/hermes-agent that referenced this pull request Jun 4, 2026
…ntity

Add six optional headers on /v1/chat/completions, /v1/responses, /v1/runs
mirroring AIAgent.__init__'s existing identity kwargs:

  X-Hermes-User-Id    → user_id
  X-Hermes-User-Name  → user_name
  X-Hermes-Chat-Id    → chat_id
  X-Hermes-Chat-Name  → chat_name
  X-Hermes-Chat-Type  → chat_type
  X-Hermes-Thread-Id  → thread_id

These kwargs already flow through AIAgent (run_agent.py:1098-1103) and
are threaded by native adapters via GatewayRunner._run_agent_task
(gateway/run.py:14881-14888); they drive Honcho's runtime_user_peer_name
resolution, per-user memory directories, session DB attribution, etc.
api_server was the odd adapter out — this PR makes it symmetrical so a
single Hermes process can serve multiple identified end-users (Open
WebUI / LobeChat / LibreChat multi-user, chat-bot bridges via the
OpenAI protocol, multi-tenant SaaS deployments).

Also accepts OpenAI's standard top-level `user` body field as a fallback
for X-Hermes-User-Id (header takes precedence) so vanilla OpenAI SDK
clients work without custom-header config.

Mirrors fe8560f (NousResearch#20199, X-Hermes-Session-Key) — additive, opt-in,
no breaking changes; unpatched clients see no difference. Same auth gate
as the session-key header (silently ignored without API_SERVER_KEY,
matching X-Hermes-Session-Key posture).

All 6 headers + the body-fallback flag are advertised at
/v1/capabilities.features so clients can feature-detect, and echoed in
the response so clients can confirm what the server saw.

Refs: NousResearch#22714 (the outgoing-side counterpart, in active discussion),
Egavasyug pushed a commit to Egavasyug/hermes-agent that referenced this pull request Jun 10, 2026
…oping (NousResearch#20199)

* feat(api-server): X-Hermes-Session-Key header for long-term memory scoping

API Server integrations (Open WebUI, custom web UIs) can now pass a stable
per-channel identifier via X-Hermes-Session-Key that scopes long-term memory
(Honcho, etc.) independently of the transcript-scoped X-Hermes-Session-Id.
This matches the native gateway's session_key / session_id split: one stable
key per assistant channel, many independent transcripts that rotate on /new.

- _create_agent and _run_agent accept gateway_session_key and pass it to
  AIAgent(gateway_session_key=...), which is already honored by the Honcho
  memory provider (plugins/memory/honcho/client.py resolve_session_name).
- New shared helper _parse_session_key_header applies the same API-key
  gate, control-character sanitization, and a 256-char length cap as the
  existing session-id header.
- All three agent endpoints honor the header: /v1/chat/completions,
  /v1/responses, /v1/runs. JSON and SSE responses echo it back.
- /v1/capabilities advertises session_key_header so clients can
  feature-detect.

Closes NousResearch#20060.

Co-authored-by: Andy Stewart <lazycat.manatee@gmail.com>

* chore: AUTHOR_MAP entry for manateelazycat

---------

Co-authored-by: Andy Stewart <lazycat.manatee@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery P3 Low — cosmetic, nice to have type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: API Server lacks a session key interface for long-term memory scoping

2 participants