From f3080547c13aecc6e645eae5b1f4e51b4b01663a Mon Sep 17 00:00:00 2001 From: waleed Date: Tue, 30 Jun 2026 11:28:39 -0700 Subject: [PATCH 1/3] feat(providers): add Claude Sonnet 5 model - Add claude-sonnet-5 (1M context, 128k output, adaptive thinking with low/medium/high/xhigh/max effort) as the new flagship Anthropic Sonnet - Use introductory pricing ($2/$10 per MTok, $0.20 cached) in effect through Aug 31 2026 - Promote to recommended and set as Anthropic defaultModel; demote claude-sonnet-4-6 - Route claude-sonnet-5 through adaptive thinking in anthropic/core.ts (manual budget_tokens returns a 400) --- apps/sim/providers/anthropic/core.ts | 4 +++- apps/sim/providers/models.ts | 23 +++++++++++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/apps/sim/providers/anthropic/core.ts b/apps/sim/providers/anthropic/core.ts index 57056e6acca..0c27f32f28d 100644 --- a/apps/sim/providers/anthropic/core.ts +++ b/apps/sim/providers/anthropic/core.ts @@ -84,6 +84,7 @@ const THINKING_BUDGET_TOKENS: Record = { /** * Checks if a model supports adaptive thinking (thinking.type: "adaptive"). + * Sonnet 5 supports ONLY adaptive thinking (manual budget_tokens returns a 400 error). * Opus 4.8 and Opus 4.7 support ONLY adaptive thinking (no extended thinking / budget_tokens). * Opus 4.6 and Sonnet 4.6 support both extended and adaptive thinking — use adaptive. * Opus 4.5 supports effort but NOT adaptive thinking — it uses budget_tokens with type: "enabled". @@ -91,6 +92,7 @@ const THINKING_BUDGET_TOKENS: Record = { function supportsAdaptiveThinking(modelId: string): boolean { const normalizedModel = modelId.toLowerCase() return ( + normalizedModel.includes('sonnet-5') || normalizedModel.includes('opus-4-8') || normalizedModel.includes('opus-4.8') || normalizedModel.includes('opus-4-7') || @@ -105,7 +107,7 @@ function supportsAdaptiveThinking(modelId: string): boolean { /** * Builds the thinking configuration for the Anthropic API based on model capabilities and level. * - * - Opus 4.8, Opus 4.7: Uses adaptive thinking only (no extended thinking support) + * - Sonnet 5, Opus 4.8, Opus 4.7: Uses adaptive thinking only (no extended thinking support) * - Opus 4.6, Sonnet 4.6: Uses adaptive thinking with effort parameter * - Other models: Uses budget_tokens-based extended thinking * diff --git a/apps/sim/providers/models.ts b/apps/sim/providers/models.ts index 3666033af1f..2cb735f928a 100644 --- a/apps/sim/providers/models.ts +++ b/apps/sim/providers/models.ts @@ -661,7 +661,7 @@ export const PROVIDER_DEFINITIONS: Record = { fileAttachment: { maxBytes: 50 * 1024 * 1024, strategy: 'remote-url' }, name: 'Anthropic', description: "Anthropic's Claude models", - defaultModel: 'claude-sonnet-4-6', + defaultModel: 'claude-sonnet-5', modelPatterns: [/^claude/], icon: AnthropicIcon, color: '#D97757', @@ -669,6 +669,26 @@ export const PROVIDER_DEFINITIONS: Record = { toolUsageControl: true, }, models: [ + { + id: 'claude-sonnet-5', + pricing: { + input: 2.0, + cachedInput: 0.2, + output: 10.0, + updatedAt: '2026-06-30', + }, + capabilities: { + nativeStructuredOutputs: true, + maxOutputTokens: 128000, + thinking: { + levels: ['low', 'medium', 'high', 'xhigh', 'max'], + default: 'high', + }, + }, + contextWindow: 1000000, + releaseDate: '2026-06-30', + recommended: true, + }, { id: 'claude-opus-4-8', pricing: { @@ -747,7 +767,6 @@ export const PROVIDER_DEFINITIONS: Record = { }, contextWindow: 1000000, releaseDate: '2026-02-17', - recommended: true, }, { id: 'claude-opus-4-5', From c712c01917027c35716f6b0692fa7089c7696457 Mon Sep 17 00:00:00 2001 From: waleed Date: Tue, 30 Jun 2026 11:36:52 -0700 Subject: [PATCH 2/3] fix(providers): expose temperature capability on claude-sonnet-5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sonnet 5 accepts the temperature parameter (0-1, per Anthropic API docs), and it replaces claude-sonnet-4-6 as the default/recommended Anthropic model. Omitting the capability silently dropped temperature control for workflows on the default model. The request builder already strips temperature whenever thinking is active, so this only takes effect when thinking is disabled — where temperature is valid. --- apps/sim/providers/models.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/sim/providers/models.ts b/apps/sim/providers/models.ts index 2cb735f928a..0c3e01ac01e 100644 --- a/apps/sim/providers/models.ts +++ b/apps/sim/providers/models.ts @@ -678,6 +678,7 @@ export const PROVIDER_DEFINITIONS: Record = { updatedAt: '2026-06-30', }, capabilities: { + temperature: { min: 0, max: 1 }, nativeStructuredOutputs: true, maxOutputTokens: 128000, thinking: { From 09f9e13515ae3645ac2a8916013f623ef9906cf2 Mon Sep 17 00:00:00 2001 From: waleed Date: Tue, 30 Jun 2026 11:49:08 -0700 Subject: [PATCH 3/3] feat(blocks): default agent-family blocks to claude-sonnet-5 Propagate the Sonnet 5 flagship promotion to the block/executor/UI defaults so the default model is consistent everywhere: - agent/router/evaluator/pi block defaultValue + agent runtime fallback - executor AGENT/ROUTER/EVALUATOR DEFAULT_MODEL constants + pi-handler DEFAULT_MODEL - combobox model-field default fallback - update coupled tests (blocks, router/evaluator handlers, copilot model-suggestion validation) to the new default/recommended set Stagehand's anthropic model pin is left on claude-sonnet-4-6 (separate tool-internal choice, not a block default). --- .../components/sub-block/components/combobox/combobox.tsx | 6 +++--- apps/sim/blocks/blocks.test.ts | 2 +- apps/sim/blocks/blocks/agent.ts | 4 ++-- apps/sim/blocks/blocks/evaluator.ts | 2 +- apps/sim/blocks/blocks/pi.ts | 2 +- apps/sim/blocks/blocks/router.ts | 4 ++-- apps/sim/executor/constants.ts | 6 +++--- .../executor/handlers/evaluator/evaluator-handler.test.ts | 4 ++-- apps/sim/executor/handlers/pi/pi-handler.ts | 2 +- apps/sim/executor/handlers/router/router-handler.test.ts | 4 ++-- .../tools/server/workflow/edit-workflow/validation.test.ts | 2 +- 11 files changed, 19 insertions(+), 19 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/combobox/combobox.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/combobox/combobox.tsx index ef09dc6ffac..b2856d10013 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/combobox/combobox.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/combobox/combobox.tsx @@ -23,7 +23,7 @@ import { useWorkflowStore } from '@/stores/workflows/workflow/store' /** * Constants for ComboBox component behavior */ -const DEFAULT_MODEL = 'claude-sonnet-4-6' +const DEFAULT_MODEL = 'claude-sonnet-5' const ZOOM_FACTOR_BASE = 0.96 const MIN_ZOOM = 0.1 const MAX_ZOOM = 1 @@ -238,7 +238,7 @@ export const ComboBox = memo(function ComboBox({ /** * Determines the default option value to use. - * Priority: explicit defaultValue > claude-sonnet-4-6 for model field > first option + * Priority: explicit defaultValue > claude-sonnet-5 for model field > first option */ const defaultOptionValue = useMemo(() => { if (defaultValue !== undefined) { @@ -250,7 +250,7 @@ export const ComboBox = memo(function ComboBox({ // Default not available (e.g. provider disabled) — fall through to other fallbacks } - // For model field, default to claude-sonnet-4-6 if available + // For model field, default to claude-sonnet-5 if available if (subBlockId === 'model') { const defaultModelOption = evaluatedOptions.find( (opt) => getOptionValue(opt) === DEFAULT_MODEL diff --git a/apps/sim/blocks/blocks.test.ts b/apps/sim/blocks/blocks.test.ts index b6b1338b9ef..ddf4e78acdb 100644 --- a/apps/sim/blocks/blocks.test.ts +++ b/apps/sim/blocks/blocks.test.ts @@ -510,7 +510,7 @@ describe.concurrent('Blocks Module', () => { expect(modelSubBlock).toBeDefined() expect(modelSubBlock?.type).toBe('combobox') expect(modelSubBlock?.required).toBe(true) - expect(modelSubBlock?.defaultValue).toBe('claude-sonnet-4-6') + expect(modelSubBlock?.defaultValue).toBe('claude-sonnet-5') }) it('should have LLM tool access', () => { diff --git a/apps/sim/blocks/blocks/agent.ts b/apps/sim/blocks/blocks/agent.ts index afa55b44db1..89c0d6e9912 100644 --- a/apps/sim/blocks/blocks/agent.ts +++ b/apps/sim/blocks/blocks/agent.ts @@ -130,7 +130,7 @@ Return ONLY the JSON array.`, type: 'combobox', placeholder: 'Type or select a model...', required: true, - defaultValue: 'claude-sonnet-4-6', + defaultValue: 'claude-sonnet-5', options: getModelOptions, commandSearchable: true, }, @@ -503,7 +503,7 @@ Return ONLY the JSON array.`, ], config: { tool: (params: Record) => { - const model = params.model || 'claude-sonnet-4-6' + const model = params.model || 'claude-sonnet-5' if (!model) { throw new Error('No model selected') } diff --git a/apps/sim/blocks/blocks/evaluator.ts b/apps/sim/blocks/blocks/evaluator.ts index 01fbfc3a55b..1de2fb19511 100644 --- a/apps/sim/blocks/blocks/evaluator.ts +++ b/apps/sim/blocks/blocks/evaluator.ts @@ -177,7 +177,7 @@ export const EvaluatorBlock: BlockConfig = { type: 'combobox', placeholder: 'Type or select a model...', required: true, - defaultValue: 'claude-sonnet-4-6', + defaultValue: 'claude-sonnet-5', options: getModelOptions, }, ...getProviderCredentialSubBlocks(), diff --git a/apps/sim/blocks/blocks/pi.ts b/apps/sim/blocks/blocks/pi.ts index f040e78ae13..b466ef77587 100644 --- a/apps/sim/blocks/blocks/pi.ts +++ b/apps/sim/blocks/blocks/pi.ts @@ -93,7 +93,7 @@ export const PiBlock: BlockConfig = { type: 'combobox', placeholder: 'Type or select a model...', required: true, - defaultValue: 'claude-sonnet-4-6', + defaultValue: 'claude-sonnet-5', options: getPiModelOptions, commandSearchable: true, }, diff --git a/apps/sim/blocks/blocks/router.ts b/apps/sim/blocks/blocks/router.ts index 16e567029d7..15835f9b8af 100644 --- a/apps/sim/blocks/blocks/router.ts +++ b/apps/sim/blocks/blocks/router.ts @@ -171,7 +171,7 @@ export const RouterBlock: BlockConfig = { type: 'combobox', placeholder: 'Type or select a model...', required: true, - defaultValue: 'claude-sonnet-4-6', + defaultValue: 'claude-sonnet-5', options: getModelOptions, }, ...getProviderCredentialSubBlocks(), @@ -298,7 +298,7 @@ export const RouterV2Block: BlockConfig = { type: 'combobox', placeholder: 'Type or select a model...', required: true, - defaultValue: 'claude-sonnet-4-6', + defaultValue: 'claude-sonnet-5', options: getModelOptions, }, ...getProviderCredentialSubBlocks(), diff --git a/apps/sim/executor/constants.ts b/apps/sim/executor/constants.ts index 03d2cebe635..08fdf93a171 100644 --- a/apps/sim/executor/constants.ts +++ b/apps/sim/executor/constants.ts @@ -207,7 +207,7 @@ export const HTTP = { } as const export const AGENT = { - DEFAULT_MODEL: 'claude-sonnet-4-6', + DEFAULT_MODEL: 'claude-sonnet-5', get DEFAULT_FUNCTION_TIMEOUT() { return getMaxExecutionTimeout() }, @@ -242,13 +242,13 @@ export const MEMORY = { } as const export const ROUTER = { - DEFAULT_MODEL: 'claude-sonnet-4-6', + DEFAULT_MODEL: 'claude-sonnet-5', DEFAULT_TEMPERATURE: 0, INFERENCE_TEMPERATURE: 0.1, } as const export const EVALUATOR = { - DEFAULT_MODEL: 'claude-sonnet-4-6', + DEFAULT_MODEL: 'claude-sonnet-5', DEFAULT_TEMPERATURE: 0.1, RESPONSE_SCHEMA_NAME: 'evaluation_response', JSON_INDENT: 2, diff --git a/apps/sim/executor/handlers/evaluator/evaluator-handler.test.ts b/apps/sim/executor/handlers/evaluator/evaluator-handler.test.ts index 664a80a21ae..2f8993e0835 100644 --- a/apps/sim/executor/handlers/evaluator/evaluator-handler.test.ts +++ b/apps/sim/executor/handlers/evaluator/evaluator-handler.test.ts @@ -481,7 +481,7 @@ describe('EvaluatorBlockHandler', () => { json: () => Promise.resolve({ content: JSON.stringify({ score: 7 }), - model: 'claude-sonnet-4-6', + model: 'claude-sonnet-5', tokens: {}, cost: 0, timing: {}, @@ -494,6 +494,6 @@ describe('EvaluatorBlockHandler', () => { const fetchCallArgs = mockFetch.mock.calls[0] const requestBody = JSON.parse(fetchCallArgs[1].body) - expect(requestBody.model).toBe('claude-sonnet-4-6') + expect(requestBody.model).toBe('claude-sonnet-5') }) }) diff --git a/apps/sim/executor/handlers/pi/pi-handler.ts b/apps/sim/executor/handlers/pi/pi-handler.ts index 961859c712d..986ab4a211c 100644 --- a/apps/sim/executor/handlers/pi/pi-handler.ts +++ b/apps/sim/executor/handlers/pi/pi-handler.ts @@ -37,7 +37,7 @@ import type { import type { SerializedBlock } from '@/serializer/types' const logger = createLogger('PiBlockHandler') -const DEFAULT_MODEL = 'claude-sonnet-4-6' +const DEFAULT_MODEL = 'claude-sonnet-5' function asOptString(value: unknown): string | undefined { if (typeof value !== 'string') return undefined diff --git a/apps/sim/executor/handlers/router/router-handler.test.ts b/apps/sim/executor/handlers/router/router-handler.test.ts index d5e54239b48..81c1a62ab55 100644 --- a/apps/sim/executor/handlers/router/router-handler.test.ts +++ b/apps/sim/executor/handlers/router/router-handler.test.ts @@ -238,12 +238,12 @@ describe('RouterBlockHandler', () => { await handler.execute(mockContext, mockBlock, inputs) - expect(mockGetProviderFromModel).toHaveBeenCalledWith('claude-sonnet-4-6') + expect(mockGetProviderFromModel).toHaveBeenCalledWith('claude-sonnet-5') const fetchCallArgs = mockFetch.mock.calls[0] const requestBody = JSON.parse(fetchCallArgs[1].body) expect(requestBody).toMatchObject({ - model: 'claude-sonnet-4-6', + model: 'claude-sonnet-5', temperature: 0.1, }) }) diff --git a/apps/sim/lib/copilot/tools/server/workflow/edit-workflow/validation.test.ts b/apps/sim/lib/copilot/tools/server/workflow/edit-workflow/validation.test.ts index 726c29f70e6..1a83b20593a 100644 --- a/apps/sim/lib/copilot/tools/server/workflow/edit-workflow/validation.test.ts +++ b/apps/sim/lib/copilot/tools/server/workflow/edit-workflow/validation.test.ts @@ -274,7 +274,7 @@ describe('validateInputsForBlock', () => { expect(result.errors).toHaveLength(1) expect(result.errors[0]?.field).toBe('model') expect(result.errors[0]?.error).toContain('Unknown model id') - expect(result.errors[0]?.error).toContain('claude-sonnet-4-6') + expect(result.errors[0]?.error).toContain('claude-sonnet-5') }) it('rejects legacy claude-4.5-haiku style ids', () => {