From a971562f0038edce8a6d349d9ae082a15323fef1 Mon Sep 17 00:00:00 2001 From: Chengjie Wang Date: Mon, 6 Jul 2026 13:38:09 +0800 Subject: [PATCH 1/2] fix(hermes): avoid Anthropic SSE for compatible endpoints Signed-off-by: Chengjie Wang --- src/lib/actions/inference-route-api.test.ts | 22 ++++++++++++++++++- src/lib/actions/inference-route-api.ts | 3 +++ .../actions/inference-set-hermes-run.test.ts | 13 +++++------ 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/lib/actions/inference-route-api.test.ts b/src/lib/actions/inference-route-api.test.ts index 8ecc3e3f0e0..97e9590309f 100644 --- a/src/lib/actions/inference-route-api.test.ts +++ b/src/lib/actions/inference-route-api.test.ts @@ -192,10 +192,30 @@ describe("resolveRuntimeInferenceApi", () => { expect( resolve( { model: { api_mode: "anthropic_messages" } }, - { agentName: "hermes", session: null }, + { + agentName: "hermes", + currentProvider: "anthropic-prod", + provider: "anthropic-prod", + session: null, + }, ), ).toBe("anthropic-messages"); }); + + it("keeps Hermes compatible Anthropic endpoint switches off Anthropic SSE streaming (#6289)", () => { + expect( + resolve( + { model: { api_mode: "anthropic_messages" } }, + { + agentName: "hermes", + session: session({ + agent: "hermes", + preferredInferenceApi: "anthropic-messages", + }), + }, + ), + ).toBe("openai-completions"); + }); }); describe("hermesApiMode", () => { diff --git a/src/lib/actions/inference-route-api.ts b/src/lib/actions/inference-route-api.ts index cf10464175c..f65752362a5 100644 --- a/src/lib/actions/inference-route-api.ts +++ b/src/lib/actions/inference-route-api.ts @@ -109,6 +109,9 @@ export function resolveRuntimeInferenceApi(options: { }): InferenceApi | null { const { agentName, config, currentProvider, provider, sandboxName, session } = options; if (provider === "anthropic-prod") return "anthropic-messages"; + if (agentName === "hermes" && provider === "compatible-anthropic-endpoint") { + return "openai-completions"; + } const sameProvider = currentProvider === provider; const sessionApi = sameProvider ? sessionRouteApi(session, sandboxName, provider) : null; diff --git a/src/lib/actions/inference-set-hermes-run.test.ts b/src/lib/actions/inference-set-hermes-run.test.ts index 8afd64e028b..77216329900 100644 --- a/src/lib/actions/inference-set-hermes-run.test.ts +++ b/src/lib/actions/inference-set-hermes-run.test.ts @@ -104,7 +104,7 @@ describe("runInferenceSet Hermes routing", () => { }); }); - it("syncs Hermes compatible Anthropic switches to Anthropic Messages when changing provider families", async () => { + it("keeps Hermes compatible Anthropic switches on the managed OpenAI-compatible route (#6289)", async () => { const config: ConfigObject = { model: { default: "openai/gpt-5.4-mini", @@ -146,9 +146,8 @@ describe("runInferenceSet Hermes routing", () => { expect(config.model).toEqual({ default: "claude-sonnet-proxy", provider: "custom", - base_url: "https://inference.local", + base_url: "https://inference.local/v1", api_key: HERMES_PROXY_API_KEY_PLACEHOLDER, - api_mode: "anthropic_messages", }); // The upstream annotation must track the selected provider together with // the API-family field, so the two cannot drift apart on later switches. @@ -163,17 +162,17 @@ describe("runInferenceSet Hermes routing", () => { model: "claude-sonnet-proxy", endpointUrl: "https://anthropic-compatible.example/v1", credentialEnv: "COMPATIBLE_ANTHROPIC_API_KEY", - preferredInferenceApi: "anthropic-messages", + preferredInferenceApi: "openai-completions", }), ]); expect(deps.getSession()).toMatchObject({ provider: "compatible-anthropic-endpoint", model: "claude-sonnet-proxy", - preferredInferenceApi: "anthropic-messages", + preferredInferenceApi: "openai-completions", }); expect(result).toMatchObject({ - providerKey: "anthropic", - primaryModelRef: "anthropic/claude-sonnet-proxy", + providerKey: "inference", + primaryModelRef: "inference/claude-sonnet-proxy", }); }); From f7555b39772574d8fa04e61406cd37f83afeeb2a Mon Sep 17 00:00:00 2001 From: Chengjie Wang Date: Mon, 6 Jul 2026 13:43:33 +0800 Subject: [PATCH 2/2] docs(inference): clarify Hermes compatible Anthropic routing Signed-off-by: Chengjie Wang --- docs/inference/switch-inference-providers.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/inference/switch-inference-providers.mdx b/docs/inference/switch-inference-providers.mdx index 4019fcb7313..148acf15aa6 100644 --- a/docs/inference/switch-inference-providers.mdx +++ b/docs/inference/switch-inference-providers.mdx @@ -111,8 +111,8 @@ For OpenClaw, `inference set` syncs the provider API family and primary model re For Hermes, `inference set` writes `model.api_mode: anthropic_messages` for Anthropic Messages routes, `model.api_mode: codex_responses` for OpenAI Responses routes, and removes `api_mode` for OpenAI-style chat-completions routes. Hermes also keeps `model.api_key` on the OpenShell proxy placeholder so dashboard and API sessions continue to authenticate through the gateway after a route change. -Amazon Bedrock Runtime routes created through `compatible-anthropic-endpoint` are the exception. -When you switch within the same Bedrock Runtime compatible provider, NemoClaw keeps the route OpenAI-compatible and does not set Hermes to Anthropic Messages mode. +Hermes only uses Anthropic Messages mode for routes that NemoClaw resolves as true Anthropic Messages providers, such as `anthropic-prod`. +For `compatible-anthropic-endpoint`, NemoClaw keeps the Hermes route OpenAI-compatible through the managed `/v1` proxy and does not set Hermes to Anthropic Messages mode. #### Switching from Responses API to Chat Completions