Skip to content

Scope Responses API conversation names by session key - #47294

Open
necoweb3 wants to merge 1 commit into
NousResearch:mainfrom
necoweb3:fix/responses-conversation-session-key-scope
Open

Scope Responses API conversation names by session key#47294
necoweb3 wants to merge 1 commit into
NousResearch:mainfrom
necoweb3:fix/responses-conversation-session-key-scope

Conversation

@necoweb3

Copy link
Copy Markdown
Contributor

Summary

This scopes Responses API conversation chaining to X-Hermes-Session-Key when the header is present. Previously, conversation names were global, so two different clients using the same conversation name could chain into each other's stored response history.

Why

X-Hermes-Session-Key is the long-term memory boundary. If two clients use the same conversation name under different keys, the server should keep those chains isolated instead of reusing the latest response ID from another key.

Changes

  • Namespace the stored conversation lookup key with the active session key when present.
  • Preserve the existing global behavior for callers that do not send a session key.
  • Add a regression test proving the same conversation name stays isolated across two different session keys.

Tests

python -m pytest tests/gateway/test_api_server.py -k "conversation_names_are_scoped_by_session_key or separate_conversations_are_isolated or conversation_chains_automatically" -q
3 passed, 155 deselected, 3 warnings in 2.49s

@alt-glitch alt-glitch added type/bug Something isn't working comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists labels Jun 16, 2026
@necoweb3 necoweb3 closed this Jun 28, 2026
@necoweb3
necoweb3 deleted the fix/responses-conversation-session-key-scope branch June 28, 2026 10:45
@necoweb3
necoweb3 restored the fix/responses-conversation-session-key-scope branch July 1, 2026 00:00
@necoweb3 necoweb3 reopened this Jul 1, 2026

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for identifying the Responses API isolation gap. The API premise is confirmed on current main: named conversations are looked up globally at gateway/platforms/api_server.py:3277 and persisted globally at gateway/platforms/api_server.py:3520; the streaming snapshot path has the same behavior at gateway/platforms/api_server.py:2767.

Problems

  • The bundled webhook retry cleanup cannot observe real agent-run failures. Its callback watches the task that awaits handle_message (gateway/platforms/webhook.py:675 in this PR), but current handle_message is fire-and-forget (gateway/platforms/base.py:4608-4615). Actual processing failures are reported through on_processing_complete (gateway/platforms/base.py:5174-5180, 5226-5235). The added test mocks handle_message itself (tests/gateway/test_webhook_adapter.py:642), so it does not exercise that lifecycle.

Suggested changes

  • Please split or remove the unrelated webhook commits from this API-scoping PR.
  • For a separate webhook fix, clear failed delivery IDs from on_processing_complete based on its failure outcome and test the real background pipeline.

Automated hermes-sweeper review.

Comment thread gateway/platforms/webhook.py Outdated
task = asyncio.create_task(self.handle_message(event))
self._background_tasks.add(task)
task.add_done_callback(self._background_tasks.discard)
def _forget_failed_delivery(done_task: "asyncio.Task") -> None:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handle_message() is fire-and-forget: it schedules _process_message_background and returns, so this task normally succeeds even when the actual agent run later fails. Release this ID from the existing on_processing_complete lifecycle hook using its failure outcome; the current test hides the issue by mocking handle_message itself.

@necoweb3
necoweb3 force-pushed the fix/responses-conversation-session-key-scope branch from 8dbd9cc to 305da95 Compare July 14, 2026 17:36
@teknium1 teknium1 added sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform area/sessions Session lifecycle, resume, persistence, history labels Jul 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/sessions Session lifecycle, resume, persistence, history comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants