GPT-5 custom endpoints ignoring explicit api_mode setting
NousResearch/hermes-agent · cluster 5718 · agent
Data as of
Nothing open on GitHub. Fix merged in #10548. Check it covers your case.
The short answer
- Known?
- Yes. 5 related items grouped here, 3 issues already closed.
- Fix event
- A fix was merged to main in PR #10548. Check it covers your case. No release data is tracked.
- Tracker
- The maintainers' tracker marks this
partially resolved, deciding PRs #10548, #115738. That is separate from the fix event. - Still open
- Nothing open on GitHub.
Reports and fixes around custom GPT-5 provider endpoints not respecting an explicitly configured api_mode, defaulting to codex_responses instead of chat_completions. Includes proposed fixes and a salvage attempt for a related prior change.
Open issues0
Open PRs0
Fixes on record
-
#10548 fix: respect explicit api_mode for custom GPT-5 endpoints
files:
gateway/run.py,run_agent.py,tests/gateway/test_background_process_notifications.pyShow the diff
-
gateway/run.py@@ -486,9 +486,14 @@ def _parse_session_key(session_key: str) -> "dict | None": """Parse a session key into its component parts. Session keys follow the format - ``agent:main:{platform}:{chat_type}:{chat_id}[:{thread_id}[:{user_id}]]``. + ``agent:main:{platform}:{chat_type}:{chat_id}[:{extra}...]``. Returns a dict with ``platform``, ``chat_type``, ``chat_id``, and optionally ``thread_id`` keys, or None if the key doesn't match. + + The 6th element is only returned as ``thread_id`` for chat types where + it is unambiguous (``dm`` and ``thread``). For group/channel sessions + the suffix may be a user_id (per-user isolation) rather than a + thread_id, so we leave ``thread_id`` out to avoid mis-routing. """ parts = session_key.split(":") if len(parts) >= 5 and parts[0] == "agent" and parts[1] == "main": @@ -497,7 +502,7 @@ def _parse_session_key(session_key: str) -> "dict | None": "chat_type": parts[3], "chat_id": parts[4], } - if len(parts) > 5: + if len(parts) > 5 and parts[3] in ("dm", "thread"): result["thread_id"] = parts[5] return result return None -
run_agent.py@@ -721,8 +721,11 @@ def __init__( # Responses there. ACP runtimes are excluded: CopilotACPClient # handles its own routing and does not implement the Responses API # surface. + # When api_mode was explicitly provided, respect it — the user + # knows what their endpoint supports (#10473). if ( - self.api_mode == "chat_completions" + api_mode is None + and self.api_mode == "chat_completions" and self.provider != "copilot-acp" and not str(self.base_url or "").lower().startswith("acp://copilot") and not str(self.base_url or "").lower().startswith("acp+tcp://") -
tests/gateway/test_background_process_notifications.py@@ -383,15 +383,27 @@ def test_parse_session_key_valid(): def test_parse_session_key_with_extra_parts(): - """Thread ID (6th part) is extracted; further parts are ignored.""" + """6th part in a group key may be a user_id, not a thread_id — omit it.""" result = _parse_session_key("agent:main:discord:group:chan123:thread456") - assert result == {"platform": "discord", "chat_type": "group", "chat_id": "chan123", "thread_id": "thread456"} + assert result == {"platform": "discord", "chat_type": "group", "chat_id": "chan123"} def test_parse_session_key_with_user_id_part(): - """7th part (user_id) is ignored — only up to thread_id is extracted.""" - result = _parse_session_key("agent:main:telegram:group:chat1:thread42:user99") - assert result == {"platform": "telegram", "chat_type": "group", "chat_id": "chat1", "thread_id": "thread42"} + """Group keys with per-user isolation have user_id as 6th part — don't return as thread_id.""" + result = _parse_session_key("agent:main:telegram:group:chat1:user99") + assert result == {"platform": "telegram", "chat_type": "group", "chat_id": "chat1"} + + +def test_parse_session_key_dm_with_thread(): + """DM keys use parts[5] as thread_id unambiguously.""" + result = _parse_session_key("agent:main:telegram:dm:chat1:topic42") + assert result == {"platform": "telegram", "chat_type": "dm", "chat_id": "chat1", "thread_id": "topic42"} + + +def test_parse_session_key_thread_chat_type(): + """Thread-typed keys use parts[5] as thread_id unambiguously.""" + result = _parse_session_key("agent:main:discord:thread:chan1:thread99") + assert result == {"platform": "discord", "chat_type": "thread", "chat_id": "chan1", "thread_id": "thread99"} def test_parse_session_key_too_short():
-
-
#115738 fix(fallback): entries naming a providers block keep its declared transport on activation (#33062, #81932)
files:
agent/chat_completion_helpers.py,tests/agent/test_fallback_api_mode_preservation.py,website/docs/integrations/providers.md
Closed issues · 3
How this cluster was grouped
-
Link evidence (
partly structural links): some members are connected by structural evidence (shared changed files, or a closing/superseded reference); the rest are joined by an automated relevance judgement over their text. - Members outside that structural core may belong to a different underlying problem.
-
Pairwise link density
0.31: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36.1.00means every pair is linked.
Pick up a Lab task
Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.
Open the Lab