hermes - 💡(How to fix) Fix [bug] api_mode: gemini providers route through OpenAI SDK; URL trailing-slash breaks :generateContent (HTTP 404)

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Vertex AI providers with api_mode: gemini and base_url ending in :generateContent silently fall through to the OpenAI SDK path in conversation_loop.py. The OpenAI SDK normalizes any base_url to end with /, mangling the Vertex endpoint URL and producing HTTP 404 on every call. User experience: every Gemini request triggers the fallback cascade with no clear root cause in the error log.

Error Message

Vertex AI providers with api_mode: gemini and base_url ending in :generateContent silently fall through to the OpenAI SDK path in conversation_loop.py. The OpenAI SDK normalizes any base_url to end with /, mangling the Vertex endpoint URL and producing HTTP 404 on every call. User experience: every Gemini request triggers the fallback cascade with no clear root cause in the error log. base_url=https://.../gemini-3.1-pro-preview-customtools:generateContent/ model=gemini-3.1-pro-preview-customtools error=HTTP 404

Root Cause

  1. agent/conversation_loop.py (lines ~1149, 1325, 1361) only has special branches for api_mode in {anthropic_messages, codex_responses, bedrock_converse, codex_app_server}. No branch for api_mode == 'gemini'.
  2. Default path uses OpenAI SDK (AsyncOpenAI(base_url=...)).
  3. OpenAI SDK _base_url setter always normalizes to trailing /.
  4. Vertex :generateContent endpoint returns HTTP 404 when called with trailing slash.

Verified live (Hermes v0.14.0):

from openai import AsyncOpenAI
url = "https://aiplatform.googleapis.com/.../gemini-3.1-pro-preview-customtools:generateContent"
c = AsyncOpenAI(api_key="dummy", base_url=url)
print(c._base_url)
# URL('https://aiplatform.googleapis.com/.../gemini-3.1-pro-preview-customtools:generateContent/')
#                                                                                           ^ added silently

Fix Action

Fix / Workaround

Workaround (verified working 2026-05-22)

Code Example

providers:
  vertex-gemini-pro-customtools:
    api_mode: gemini
    api_key: vertex-adc-bearer
    base_url: https://aiplatform.googleapis.com/v1/projects/<PROJECT>/locations/global/publishers/google/models/gemini-3.1-pro-preview-customtools:generateContent

---

base_url=https://.../gemini-3.1-pro-preview-customtools:generateContent/ model=gemini-3.1-pro-preview-customtools error=HTTP 404

---

from openai import AsyncOpenAI
url = "https://aiplatform.googleapis.com/.../gemini-3.1-pro-preview-customtools:generateContent"
c = AsyncOpenAI(api_key="dummy", base_url=url)
print(c._base_url)
# URL('https://aiplatform.googleapis.com/.../gemini-3.1-pro-preview-customtools:generateContent/')
#                                                                                           ^ added silently

---

vertex-gemini-pro-customtools:
  api_mode: openai
  api_key: vertex-adc-bearer
  base_url: https://aiplatform.googleapis.com/v1/projects/<PROJECT>/locations/global/endpoints/openapi
  model: google/gemini-3.1-pro-preview-customtools

---

🔄 Primary model failed — switching to fallback: claude-opus-4-7 via vertex-claude-opus-47
🔄 Primary model failed — switching to fallback: claude-sonnet-4-6 via vertex-claude-sonnet-46
RAW_BUFFERClick to expand / collapse

[bug] api_mode: gemini providers silently route through OpenAI SDK; URL trailing-slash breaks :generateContent (HTTP 404)

Summary

Vertex AI providers with api_mode: gemini and base_url ending in :generateContent silently fall through to the OpenAI SDK path in conversation_loop.py. The OpenAI SDK normalizes any base_url to end with /, mangling the Vertex endpoint URL and producing HTTP 404 on every call. User experience: every Gemini request triggers the fallback cascade with no clear root cause in the error log.

Repro

providers:
  vertex-gemini-pro-customtools:
    api_mode: gemini
    api_key: vertex-adc-bearer
    base_url: https://aiplatform.googleapis.com/v1/projects/<PROJECT>/locations/global/publishers/google/models/gemini-3.1-pro-preview-customtools:generateContent

Logs show:

base_url=https://.../gemini-3.1-pro-preview-customtools:generateContent/ model=gemini-3.1-pro-preview-customtools error=HTTP 404

Note the trailing / after :generateContent.

Root cause

  1. agent/conversation_loop.py (lines ~1149, 1325, 1361) only has special branches for api_mode in {anthropic_messages, codex_responses, bedrock_converse, codex_app_server}. No branch for api_mode == 'gemini'.
  2. Default path uses OpenAI SDK (AsyncOpenAI(base_url=...)).
  3. OpenAI SDK _base_url setter always normalizes to trailing /.
  4. Vertex :generateContent endpoint returns HTTP 404 when called with trailing slash.

Verified live (Hermes v0.14.0):

from openai import AsyncOpenAI
url = "https://aiplatform.googleapis.com/.../gemini-3.1-pro-preview-customtools:generateContent"
c = AsyncOpenAI(api_key="dummy", base_url=url)
print(c._base_url)
# URL('https://aiplatform.googleapis.com/.../gemini-3.1-pro-preview-customtools:generateContent/')
#                                                                                           ^ added silently

Workaround (verified working 2026-05-22)

Switch api_mode from gemini to openai AND switch base_url to Vertex's openai-compat endpoint:

vertex-gemini-pro-customtools:
  api_mode: openai
  api_key: vertex-adc-bearer
  base_url: https://aiplatform.googleapis.com/v1/projects/<PROJECT>/locations/global/endpoints/openapi
  model: google/gemini-3.1-pro-preview-customtools

Returns HTTP 200 in 1.2s. Standard OpenAI chat-completion shape.

Proposed fix

Add a gemini branch in agent/conversation_loop.py that routes through agent.gemini_native_adapter.GeminiNativeClient (which already exists at agent/gemini_native_adapter.py:72 and correctly handles :generateContent URL construction without OpenAI SDK normalization).

Alternative: update Hermes setup wizard to write Gemini text providers as api_mode: openai with the openai-compat URL by default.

Impact

Anyone using Hermes with Vertex AI Gemini providers in :generateContent form is silently broken for text generation. Image/TTS variants are unaffected because they have separate response-handling paths.

User-visible symptom:

🔄 Primary model failed — switching to fallback: claude-opus-4-7 via vertex-claude-opus-47
🔄 Primary model failed — switching to fallback: claude-sonnet-4-6 via vertex-claude-sonnet-46

— with no indication of root cause unless you journalctl -u hermes-gateway and notice the trailing slash.

Environment

  • Hermes Agent v0.14.0 (2026.5.16)
  • Python 3.11.15
  • openai SDK 2.24.0
  • Host: GCE Ubuntu 24.04 x86_64, anolasco-gemini project, us-central1-c

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - 💡(How to fix) Fix [bug] api_mode: gemini providers route through OpenAI SDK; URL trailing-slash breaks :generateContent (HTTP 404)