Skip to content

Commit 6b0f718

Browse files
committed
fix(providers): encode Mythos adaptive requests
1 parent 9b57db3 commit 6b0f718

6 files changed

Lines changed: 94 additions & 16 deletions

File tree

docs/providers/bedrock-mantle.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,18 @@ Choose your preferred auth method and follow the setup steps.
3838
export AWS_REGION="us-west-2"
3939
```
4040
</Step>
41+
<Step title="Opt in to provider data sharing for Claude Fable 5">
42+
Claude Fable 5 and Claude Mythos-class Bedrock models require the Mantle Data Retention API mode `provider_data_share` before invocation. This opt-in allows Bedrock to share prompts and completions with Anthropic and retain them for up to 30 days for trust and safety review.
43+
44+
```bash
45+
curl -X PUT https://bedrock-mantle.us-east-1.api.aws/v1/data_retention \
46+
-H "Authorization: Bearer $AWS_BEARER_TOKEN_BEDROCK" \
47+
-H "Content-Type: application/json" \
48+
-d '{ "mode": "provider_data_share" }'
49+
```
50+
51+
Use another Bedrock model in the config if you cannot accept that retention mode.
52+
</Step>
4153
<Step title="Verify models are discovered">
4254
```bash
4355
openclaw models list

docs/providers/bedrock.md

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,18 +38,6 @@ Choose your preferred auth method and follow the setup steps.
3838
export AWS_BEARER_TOKEN_BEDROCK="..."
3939
```
4040
</Step>
41-
<Step title="Opt in to provider data sharing for Claude Fable 5">
42-
Claude Fable 5 and Claude Mythos-class Bedrock models require the Bedrock Data Retention API mode `provider_data_share` before invocation. This opt-in allows Bedrock to share prompts and completions with Anthropic and retain them for up to 30 days for trust and safety review.
43-
44-
```bash
45-
curl -X PUT https://bedrock-mantle.us-east-1.api.aws/v1/data_retention \
46-
-H "x-api-key: $BEDROCK_API_KEY" \
47-
-H "Content-Type: application/json" \
48-
-d '{ "mode": "provider_data_share" }'
49-
```
50-
51-
Use another Bedrock model in the config if you cannot accept that retention mode.
52-
</Step>
5341
<Step title="Add a Bedrock provider and model to your config">
5442
No `apiKey` is required. Configure the provider with `auth: "aws-sdk"`:
5543

extensions/amazon-bedrock/stream.runtime.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,21 @@ describe("Bedrock thinking effort mapping", () => {
182182
});
183183
});
184184

185+
it("forces adaptive thinking for Bedrock Mythos Preview when callers omit reasoning", () => {
186+
const model = bedrockModel({
187+
id: "us.anthropic.claude-mythos-preview",
188+
name: "US Claude Mythos Preview",
189+
reasoning: true,
190+
});
191+
const options = testing.resolveSimpleBedrockOptions(model, {});
192+
193+
expect(options.reasoning).toBe("high");
194+
expect(testing.buildAdditionalModelRequestFields(model, options)).toEqual({
195+
thinking: { type: "adaptive", display: "summarized" },
196+
output_config: { effort: "high" },
197+
});
198+
});
199+
185200
it("clamps max effort for Claude models without native max support", () => {
186201
expect(
187202
testing.mapThinkingLevelToEffort(

extensions/amazon-bedrock/stream.runtime.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -563,23 +563,39 @@ function resolveClaudeProfileNameModelId(modelName?: string): string | undefined
563563
if (!normalized.includes("claude")) {
564564
return undefined;
565565
}
566-
const family = /(?:fable-5|opus-4-(?:6|7|8)|sonnet-4-6)(?:$|-)/.exec(normalized)?.[0];
566+
const family = /(?:fable-5|mythos-preview|opus-4-(?:6|7|8)|sonnet-4-6)(?:$|-)/.exec(
567+
normalized,
568+
)?.[0];
567569
return family ? `claude-${family.replace(/-$/, "")}` : undefined;
568570
}
569571

572+
function isClaudeMythosPreviewModelId(modelId?: string): boolean {
573+
return /(?:^|-)claude-mythos-preview(?=$|[^a-z0-9])/.test(
574+
modelId
575+
?.trim()
576+
.toLowerCase()
577+
.replace(/[\s_.:]+/g, "-") ?? "",
578+
);
579+
}
580+
570581
/** Check canonical metadata and profile names for adaptive Claude support. */
571582
function supportsAdaptiveThinking(model: Model<"bedrock-converse-stream">): boolean {
572583
const profileModelId = resolveClaudeProfileNameModelId(model.name);
573584
return (
574-
supportsClaudeAdaptiveThinking(model) || supportsClaudeAdaptiveThinking({ id: profileModelId })
585+
supportsClaudeAdaptiveThinking(model) ||
586+
supportsClaudeAdaptiveThinking({ id: profileModelId }) ||
587+
isClaudeMythosPreviewModelId(resolveClaudeModelIdentity(model)) ||
588+
isClaudeMythosPreviewModelId(profileModelId)
575589
);
576590
}
577591

578592
function requiresMandatoryAdaptiveThinking(model: Model<"bedrock-converse-stream">): boolean {
579593
const profileModelId = resolveClaudeProfileNameModelId(model.name);
580594
return (
581595
isClaudeAdaptiveThinkingDefaultModelId(resolveClaudeModelIdentity(model)) ||
582-
(profileModelId ? isClaudeAdaptiveThinkingDefaultModelId(profileModelId) : false)
596+
(profileModelId ? isClaudeAdaptiveThinkingDefaultModelId(profileModelId) : false) ||
597+
isClaudeMythosPreviewModelId(resolveClaudeModelIdentity(model)) ||
598+
isClaudeMythosPreviewModelId(profileModelId)
583599
);
584600
}
585601

src/llm/providers/anthropic.test.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,36 @@ describe("Anthropic provider", () => {
535535
});
536536
});
537537

538+
it("uses adaptive thinking for Foundry Mythos Preview without native max metadata", async () => {
539+
let capturedPayload: unknown;
540+
const stream = streamSimpleAnthropic(
541+
makeAnthropicModel({
542+
id: "prod-mythos-preview",
543+
name: "claude-mythos-preview",
544+
provider: "microsoft-foundry",
545+
reasoning: true,
546+
}),
547+
{
548+
messages: [{ role: "user", content: "hello", timestamp: 0 }],
549+
},
550+
{
551+
apiKey: "sk-ant-provider",
552+
reasoning: "high",
553+
onPayload: (payload) => {
554+
capturedPayload = payload;
555+
throw new Error("stop before network");
556+
},
557+
},
558+
);
559+
560+
await stream.result();
561+
562+
expect(capturedPayload).toMatchObject({
563+
thinking: { type: "adaptive" },
564+
output_config: { effort: "high" },
565+
});
566+
});
567+
538568
it.each([
539569
{
540570
id: "prod-primary",

src/llm/providers/anthropic.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -807,7 +807,24 @@ function normalizeAnthropicToolChoice(
807807
* Check if a model supports adaptive thinking (Fable 5, Opus 4.6+, Sonnet 4.6).
808808
*/
809809
function supportsAdaptiveThinking(model: Model<"anthropic-messages">): boolean {
810-
return supportsClaudeAdaptiveThinking(model) || model.thinkingLevelMap?.max === "max";
810+
return (
811+
supportsClaudeAdaptiveThinking(model) ||
812+
model.thinkingLevelMap?.max === "max" ||
813+
isClaudeMythosPreviewModel(model)
814+
);
815+
}
816+
817+
function isClaudeMythosPreviewModel(model: Model<"anthropic-messages">): boolean {
818+
return [model.id, model.name, model.params?.canonicalModelId]
819+
.filter((value): value is string => typeof value === "string")
820+
.some((value) =>
821+
/(?:^|-)claude-mythos-preview(?=$|[^a-z0-9])/.test(
822+
value
823+
.trim()
824+
.toLowerCase()
825+
.replace(/[\s_.:]+/g, "-"),
826+
),
827+
);
811828
}
812829

813830
function supportsNativeXhighEffort(model: Model<"anthropic-messages">): boolean {

0 commit comments

Comments
 (0)