diff --git a/python/src/agent_squad/agents/anthropic_agent.py b/python/src/agent_squad/agents/anthropic_agent.py index bbcc8ac51..68069637d 100644 --- a/python/src/agent_squad/agents/anthropic_agent.py +++ b/python/src/agent_squad/agents/anthropic_agent.py @@ -28,7 +28,7 @@ class AnthropicAgentOptions(AgentOptions): """ api_key: Optional[str] = None client: Optional[Any] = None - model_id: str = "claude-3-5-sonnet-20240620" + model_id: str = "claude-sonnet-4-20250514" streaming: Optional[bool] = False inference_config: Optional[dict[str, Any]] = None retriever: Optional[Retriever] = None @@ -65,7 +65,7 @@ def __init__(self, options: AnthropicAgentOptions): self.model_id = options.model_id - default_inference_config = {"maxTokens": 1000, "temperature": 0.1, "topP": 0.9, "stopSequences": []} + default_inference_config = {"maxTokens": 1000, "temperature": 0.1, "stopSequences": []} if options.inference_config: self.inference_config = {**default_inference_config, **options.inference_config} @@ -165,10 +165,14 @@ def _build_input(self, messages: list[Any], system_prompt: str) -> dict: "messages": messages, "system": system_prompt, "temperature": self.inference_config.get("temperature"), - "top_p": self.inference_config.get("topP"), "stop_sequences": self.inference_config.get("stopSequences"), } + # Only pass top_p if explicitly set — newer Anthropic models reject both temperature and top_p + top_p = self.inference_config.get("topP") + if top_p is not None: + json_input["top_p"] = top_p + # Add any additional model request fields if self.additional_model_request_fields: for key, value in self.additional_model_request_fields.items(): diff --git a/python/src/agent_squad/classifiers/anthropic_classifier.py b/python/src/agent_squad/classifiers/anthropic_classifier.py index f926a22cf..322b1ff58 100644 --- a/python/src/agent_squad/classifiers/anthropic_classifier.py +++ b/python/src/agent_squad/classifiers/anthropic_classifier.py @@ -6,7 +6,7 @@ from agent_squad.types import ConversationMessage from agent_squad.classifiers import Classifier, ClassifierResult, ClassifierCallbacks -ANTHROPIC_MODEL_ID_CLAUDE_3_5_SONNET = "claude-3-5-sonnet-20240620" +ANTHROPIC_MODEL_ID_CLAUDE_SONNET_4 = "claude-sonnet-4-20250514" class AnthropicClassifierOptions: def __init__(self, @@ -28,7 +28,7 @@ def __init__(self, options: AnthropicClassifierOptions): raise ValueError("Anthropic API key is required") self.client = Anthropic(api_key=options.api_key) - self.model_id = options.model_id or ANTHROPIC_MODEL_ID_CLAUDE_3_5_SONNET + self.model_id = options.model_id or ANTHROPIC_MODEL_ID_CLAUDE_SONNET_4 self.callbacks = options.callbacks @@ -36,9 +36,11 @@ def __init__(self, options: AnthropicClassifierOptions): self.inference_config = { 'max_tokens': options.inference_config.get('max_tokens', default_max_tokens), 'temperature': options.inference_config.get('temperature', 0.0), - 'top_p': options.inference_config.get('top_p', 0.9), 'stop_sequences': options.inference_config.get('stop_sequences', []), } + # Only pass top_p if explicitly set — newer Anthropic models reject both temperature and top_p + if 'top_p' in options.inference_config: + self.inference_config['top_p'] = options.inference_config['top_p'] self.tools: List[dict] = [ { @@ -81,21 +83,26 @@ async def process_request(self, "inferenceConfig": { "maxTokens": self.inference_config['max_tokens'], "temperature": self.inference_config['temperature'], - "topP": self.inference_config['top_p'], "stopSequences": self.inference_config['stop_sequences'], }, } + if 'top_p' in self.inference_config: + kwargs['inferenceConfig']['topP'] = self.inference_config['top_p'] + await self.callbacks.on_classifier_start('on_classifier_start', input_text, **kwargs) - response:Message = self.client.messages.create( - model=self.model_id, - max_tokens=self.inference_config['max_tokens'], - messages=[user_message], - system=self.system_prompt, - temperature=self.inference_config['temperature'], - top_p=self.inference_config['top_p'], - tools=self.tools - ) + call_params = { + "model": self.model_id, + "max_tokens": self.inference_config['max_tokens'], + "messages": [user_message], + "system": self.system_prompt, + "temperature": self.inference_config['temperature'], + "tools": self.tools, + } + if 'top_p' in self.inference_config: + call_params['top_p'] = self.inference_config['top_p'] + + response:Message = self.client.messages.create(**call_params) tool_use = next((c for c in response.content if c.type == "tool_use"), None) diff --git a/python/src/agent_squad/types/types.py b/python/src/agent_squad/types/types.py index 29d71a783..d7519891a 100644 --- a/python/src/agent_squad/types/types.py +++ b/python/src/agent_squad/types/types.py @@ -11,6 +11,7 @@ BEDROCK_MODEL_ID_LLAMA_3_70B = "meta.llama3-70b-instruct-v1:0" OPENAI_MODEL_ID_GPT_O_MINI = "gpt-4o-mini" ANTHROPIC_MODEL_ID_CLAUDE_3_5_SONNET = "claude-3-5-sonnet-20240620" +ANTHROPIC_MODEL_ID_CLAUDE_SONNET_4 = "claude-sonnet-4-20250514" class AgentProviderType(Enum): BEDROCK = "BEDROCK" diff --git a/typescript/src/agents/anthropicAgent.ts b/typescript/src/agents/anthropicAgent.ts index f7625719b..9c4b1b0a3 100644 --- a/typescript/src/agents/anthropicAgent.ts +++ b/typescript/src/agents/anthropicAgent.ts @@ -1,6 +1,6 @@ import { Agent, AgentCallbacks, AgentOptions } from "./agent"; import { - ANTHROPIC_MODEL_ID_CLAUDE_3_5_SONNET, + ANTHROPIC_MODEL_ID_CLAUDE_SONNET_4, ANTHROPIC_MODEL_ID_CLAUDE_3_5_SONNET, ConversationMessage, ParticipantRole, TemplateVariables, @@ -112,17 +112,20 @@ export class AnthropicAgent extends Agent { this.streaming = options.streaming ?? false; - this.modelId = options.modelId || ANTHROPIC_MODEL_ID_CLAUDE_3_5_SONNET; + this.modelId = options.modelId || ANTHROPIC_MODEL_ID_CLAUDE_SONNET_4; this.thinking = options.thinking ?? null; - const defaultMaxTokens = 1000; // You can adjust this default value as needed + const defaultMaxTokens = 1000; this.inferenceConfig = { maxTokens: options.inferenceConfig?.maxTokens ?? defaultMaxTokens, temperature: options.inferenceConfig?.temperature ?? 0.1, - topP: options.inferenceConfig?.topP ?? 0.9, stopSequences: options.inferenceConfig?.stopSequences ?? [], }; + // Only set topP if explicitly provided — newer Anthropic models reject both temperature and topP + if (options.inferenceConfig?.topP !== undefined) { + this.inferenceConfig.topP = options.inferenceConfig.topP; + } this.retriever = options.retriever; @@ -294,13 +297,12 @@ export class AnthropicAgent extends Agent { this.toolConfig?.toolMaxRecursions || this.defaultMaxRecursions; do { // Call Anthropic - const llmInput = { + const llmInput: any = { model: this.modelId, max_tokens: this.inferenceConfig.maxTokens, messages: messages, system: systemPrompt, temperature: this.inferenceConfig.temperature, - top_p: this.inferenceConfig.topP, thinking: this.thinking, ...(this.toolConfig && { tools: @@ -309,6 +311,10 @@ export class AnthropicAgent extends Agent { : this.toolConfig.tool, }), }; + // Only pass top_p if explicitly set — newer Anthropic models reject both temperature and top_p + if (this.inferenceConfig.topP !== undefined) { + llmInput.top_p = this.inferenceConfig.topP; + } const response = await this.handleSingleResponse(llmInput); const toolUseBlocks = response.content.filter( @@ -399,7 +405,7 @@ export class AnthropicAgent extends Agent { let recursions = this.toolConfig?.toolMaxRecursions || 5; do { - const stream = await this.client.messages.stream({ + const streamConfig: any = { model: this.modelId, max_tokens: this.inferenceConfig.maxTokens, messages: messages, @@ -409,13 +415,18 @@ export class AnthropicAgent extends Agent { type: this.thinking?.type === "enabled" ? "enabled" : "disabled", budget_tokens: this.thinking?.budget_tokens }, - top_p: this.inferenceConfig.topP, ...(this.toolConfig && { tools: this.toolConfig.tool instanceof AgentTools ? this.formatTools(this.toolConfig.tool) : this.toolConfig.tool, }), + }; + // Only pass top_p if explicitly set — newer Anthropic models reject both temperature and top_p + if (this.inferenceConfig.topP !== undefined) { + streamConfig.top_p = this.inferenceConfig.topP; + } + const stream = await this.client.messages.stream(streamConfig); }); let toolBlock: Anthropic.ToolUseBlock = { diff --git a/typescript/src/classifiers/anthropicClassifier.ts b/typescript/src/classifiers/anthropicClassifier.ts index fbe2f0b9a..2e32dc582 100644 --- a/typescript/src/classifiers/anthropicClassifier.ts +++ b/typescript/src/classifiers/anthropicClassifier.ts @@ -1,5 +1,5 @@ import { - ANTHROPIC_MODEL_ID_CLAUDE_3_5_SONNET, + ANTHROPIC_MODEL_ID_CLAUDE_SONNET_4, ANTHROPIC_MODEL_ID_CLAUDE_3_5_SONNET, ConversationMessage, ParticipantRole, } from "../types"; @@ -80,13 +80,12 @@ export class AnthropicClassifier extends Classifier { throw new Error("Anthropic API key is required"); } this.client = new Anthropic({ apiKey: options.apiKey }); - this.modelId = options.modelId || ANTHROPIC_MODEL_ID_CLAUDE_3_5_SONNET; + this.modelId = options.modelId || ANTHROPIC_MODEL_ID_CLAUDE_SONNET_4; // Set default value for max_tokens if not provided const defaultMaxTokens = 1000; // You can adjust this default value as needed this.inferenceConfig = { maxTokens: options.inferenceConfig?.maxTokens ?? defaultMaxTokens, temperature: options.inferenceConfig?.temperature, - topP: options.inferenceConfig?.topP, stopSequences: options.inferenceConfig?.stopSequences, }; @@ -105,15 +104,19 @@ async processRequest( }; try { - const response = await this.client.messages.create({ + const callParams: any = { model: this.modelId, max_tokens: this.inferenceConfig.maxTokens, messages: [userMessage], system: this.systemPrompt, temperature: this.inferenceConfig.temperature, - top_p: this.inferenceConfig.topP, tools: this.tools - }); + }; + // Only pass top_p if explicitly set — newer Anthropic models reject both temperature and top_p + if (this.inferenceConfig.topP !== undefined) { + callParams.top_p = this.inferenceConfig.topP; + } + const response = await this.client.messages.create(callParams); const toolUse = response.content.find( (content): content is Anthropic.ToolUseBlock => content.type === "tool_use" diff --git a/typescript/src/types/index.ts b/typescript/src/types/index.ts index b14e33f91..e51d49b1b 100644 --- a/typescript/src/types/index.ts +++ b/typescript/src/types/index.ts @@ -4,6 +4,7 @@ export const BEDROCK_MODEL_ID_CLAUDE_3_5_SONNET = "anthropic.claude-3-5-sonnet-2 export const BEDROCK_MODEL_ID_LLAMA_3_70B = "meta.llama3-70b-instruct-v1:0"; export const OPENAI_MODEL_ID_GPT_O_MINI = "gpt-4o-mini"; export const ANTHROPIC_MODEL_ID_CLAUDE_3_5_SONNET = "claude-3-5-sonnet-20240620"; +export const ANTHROPIC_MODEL_ID_CLAUDE_SONNET_4 = "claude-sonnet-4-20250514"; export const AgentTypes = { DEFAULT: "Common Knowledge",