fix(agents): normalize prefixed Anthropic fallback model ids (#88560)#88587
Conversation
|
Codex review: needs maintainer review before merge. Reviewed May 31, 2026, 6:52 AM ET / 10:52 UTC. Summary PR surface: Source +5, Tests +112. Total +117 across 5 files. Reproducibility: yes. Source inspection on current main shows native Anthropic-prefixed ids are returned unchanged while the bundled Anthropic static catalog stores unprefixed ids, and the linked issue supplies production fallback logs showing doubled/leaked prefixes. Review metrics: 1 noteworthy metric.
Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land the shared normalization fix after maintainers accept the scoped Anthropic provider-routing compatibility risk; keep broader provider alias policy outside this PR. Do we have a high-confidence way to reproduce the issue? Yes. Source inspection on current main shows native Anthropic-prefixed ids are returned unchanged while the bundled Anthropic static catalog stores unprefixed ids, and the linked issue supplies production fallback logs showing doubled/leaked prefixes. Is this the best way to solve the issue? Yes. The PR fixes the shared normalization layer that feeds catalog, wrapper, embedded lookup, and fallback paths, which is narrower and cleaner than adding fallback-specific string handling. AGENTS.md: found and applied where relevant. Codex review notes: model gpt-5.5, reasoning high; reviewed against 1e08af453a06. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +5, Tests +112. Total +117 across 5 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
509a16f to
0389ece
Compare
|
Updated the PR body with redacted local runtime fallback proof from the real @clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
0389ece to
5965951
Compare
5965951 to
4ee13a1
Compare
|
Rebased again and refreshed the PR body/proof on head @clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
Maintainer verification before landing #88587. Behavior addressed: Native Anthropic fallback refs such as Real environment tested: Maintainer source checkout on macOS, current Exact steps or command run after this patch: Evidence after fix: PR CI completed successfully for the head SHA; only superseded duplicate Observed result after fix: Source review confirms the production change is scoped to What was not tested: I did not run a live gateway failover with real provider credentials from this machine, and I did not rerun the local Vitest/tsgo commands already supplied by the contributor and CI. |
…n-rotation-current * origin/main: docs: strengthen review dependency inspection rules refactor: expand acp core package (#88618) fix(doctor): diagnose malformed provider catalogs fix(agents): normalize prefixed Anthropic model ids (#88587) chore: bump OpenClaw version to 2026.5.31 feat(codex): add portable Codex command pickers (#82224) fix(tui): preserve pending local runs during session sync (#87959) docs: clarify inline code comments fix(auto-reply): warn on substantive private message-tool finals fix(tui): use middle truncation for paths and commands in tool display (#88050) fix(webchat): suppress stale active session rows (#87962) fix(tui): skip history reload when final event has displayable output (#88004) test(discord): isolate timer-sensitive request tests fix(auth): coerce persisted device auth tokens fix(e2e): heartbeat resource-sampled docker lanes # Conflicts: # src/gateway/server-methods/exec-approvals.ts # src/gateway/server-methods/nodes-pending.ts # src/infra/node-pairing.ts # src/tui/tui-command-handlers.test.ts
|
Thanks for the fast turnaround on this. Wanted to share an empirical data point that suggests the fix scope should be widened before merge. TL;DR: I deployed a workaround for the issue on our pod by swapping the cost-tier model from Same shape as the Anthropic case: the prefixed model id leaks across fallback candidates, only the leading provider qualifier swaps per candidate. Root cause confirmation: looking at the shipped Suggestion: would it be possible to generalize the strip rather than add an anthropic-specific branch? Something like a final pass that, regardless of provider, strips a leading Happy to test against any candidate branch if you push one — our pod reproduces the leak deterministically on every heartbeat firing (~30/hour on each affected agent). |
Summary
anthropic/claude-haiku-4-5resolving as a literal nested model id.Linked context
Closes #88560
Related #88517, #77167, #88470
Real behavior proof (required for external PRs)
Behavior or issue addressed: A configured fallback chain with prefixed Anthropic entries should resolve each candidate to its own provider/model pair, and Anthropic static catalog ids should not retain a nested
anthropic/prefix.Real environment tested: Local OpenClaw source checkout at
/private/tmp/openclaw-88560on macOS, branchfix/fallback-modelid-normalization-88560, rebased ontof7a1d3f3f6, running the repo's real fallback runtime path, Vitest, and tsgo test runners against the changed code.Exact steps or command run after this patch:
timeout 180 node scripts/test-projects.mjs packages/model-catalog-core/src/provider-model-id-normalization.test.ts src/agents/model-ref-shared.test.ts src/agents/embedded-agent-runner/model.test.ts src/agents/model-fallback.test.ts;node --import tsx -e '<inline script invoking runWithModelFallback with prefixed Anthropic primary/fallbacks and redacted local FailoverError failures>'.Evidence after fix (screenshot, recording, terminal capture, console output, redacted runtime log, linked artifact, or copied live output): After rebasing to
f7a1d3f3f6, the focused test run passed 3 Vitest shards: unit-fast1 passed / 12 tests, unit1 passed / 3 tests, agents2 passed / 177 tests.git diff --checkexited 0. Type checks exited 0 fornode scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.test.src.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/test-src-88560-rebased-f7a1.tsbuildinfoandnode scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.test.packages.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/test-packages-88560-rebased-f7a1.tsbuildinfo.Redacted local runtime proof from the real
runWithModelFallbackpath after rebasing tof7a1d3f3f6:Observed result after fix:
normalizeStaticProviderModelId("anthropic", "anthropic/claude-haiku-4-5")returnsclaude-haiku-4-5, fallback candidates resolve toclaude-sonnet-4-6,claude-haiku-4-5, andclaude-opus-4-7, and the real fallback runtime receives unprefixed Anthropic model ids while keeping OpenAI/XAI candidates separate.What was not tested: A live gateway failover run against production Anthropic/OpenAI/Google/XAI credentials was not run from this workstation.
Proof limitations or environment constraints: This uses a local runtime invocation with redacted synthetic provider failures plus repository tests; the issue's production logs and production provider credentials are not available in this local environment.
Before evidence (optional but encouraged): Issue [Bug]: v2026.5.28 — fallback iterator leaks one candidate's modelId into every subsequent provider lookup; produces doubled-prefix errors fleet-wide #88560 documents production failures where all fallback candidates were reported with leaked ids such as
openai/anthropic/claude-haiku-4-5,xai/anthropic/claude-haiku-4-5, andanthropic/anthropic/claude-haiku-4-5.Tests and validation
timeout 180 node scripts/test-projects.mjs packages/model-catalog-core/src/provider-model-id-normalization.test.ts src/agents/model-ref-shared.test.ts src/agents/embedded-agent-runner/model.test.ts src/agents/model-fallback.test.tstimeout 240 node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.test.src.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/test-src-88560-rebased-f7a1.tsbuildinfotimeout 240 node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.test.packages.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/test-packages-88560-rebased-f7a1.tsbuildinfonode --import tsx -e '<inline script invoking runWithModelFallback with prefixed Anthropic primary/fallbacks and redacted local FailoverError failures>'git diff --checkRegression coverage was added for Anthropic prefix stripping, configured provider catalog normalization, fallback candidate chain normalization, and embedded model lookup arguments.
Risk checklist
Did user-visible behavior change? (
Yes/No)Yes. Prefixed Anthropic model ids now resolve to the native Anthropic model id for static catalog lookup.
Did config, environment, or migration behavior change? (
Yes/No)No.
Did security, auth, secrets, network, or tool execution behavior change? (
Yes/No)No.
What is the highest-risk area?
Anthropic model-id normalization compatibility for existing configs.
How is that risk mitigated?
The change is scoped to the native
anthropicprovider prefix and preserves existing Anthropic aliases; tests cover both the shared package and OpenClaw wrapper paths.Current review state
What is the next action?
Await ClawSweeper re-review and fresh CI after the rebase/proof update.
What is still waiting on author, maintainer, CI, or external proof?
CI, ClawSweeper, and maintainer review. No known author-side blocker after this proof update.
Which bot or reviewer comments were addressed?
Addressed ClawSweeper's request for redacted runtime fallback proof showing prefixed Anthropic entries resolving to their own provider/model ids, then refreshed that proof after rebasing to
f7a1d3f3f6.