Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/inference/switch-inference-providers.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
22 changes: 21 additions & 1 deletion src/lib/actions/inference-route-api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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", () => {
Expand Down
3 changes: 3 additions & 0 deletions src/lib/actions/inference-route-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
13 changes: 6 additions & 7 deletions src/lib/actions/inference-set-hermes-run.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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.
Expand All @@ -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",
});
});

Expand Down
Loading