From fede37b49620c63d536ea8197717b87a14fe4fa9 Mon Sep 17 00:00:00 2001 From: Clay Arnold <99657852+314clay@users.noreply.github.com> Date: Thu, 19 Feb 2026 12:33:17 +1300 Subject: [PATCH] fix: add claude-opus-4-6 to temperature/top_p guard (#12874) Co-authored-by: Claude Opus 4.6 --- openhands/llm/llm.py | 5 +++-- tests/unit/llm/test_llm.py | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/openhands/llm/llm.py b/openhands/llm/llm.py index cbbac29c1e..1a0734a6ee 100644 --- a/openhands/llm/llm.py +++ b/openhands/llm/llm.py @@ -198,13 +198,14 @@ class LLM(RetryMixin, DebugMixin): if 'claude-opus-4-1' in self.config.model.lower(): kwargs['thinking'] = {'type': 'disabled'} - # Anthropic constraint: Opus 4.1, Opus 4.5, and Sonnet 4 models cannot accept both temperature and top_p + # Anthropic constraint: Opus 4.1, Opus 4.5, Opus 4.6, and Sonnet 4 models cannot accept both temperature and top_p # Prefer temperature (drop top_p) if both are specified. _model_lower = self.config.model.lower() - # Apply to Opus 4.1, Opus 4.5, and Sonnet 4 models to avoid API errors + # Apply to Opus 4.1, Opus 4.5, Opus 4.6, and Sonnet 4 models to avoid API errors if ( ('claude-opus-4-1' in _model_lower) or ('claude-opus-4-5' in _model_lower) + or ('claude-opus-4-6' in _model_lower) or ('claude-sonnet-4' in _model_lower) ) and ('temperature' in kwargs and 'top_p' in kwargs): kwargs.pop('top_p', None) diff --git a/tests/unit/llm/test_llm.py b/tests/unit/llm/test_llm.py index b04425e631..e27bc354d9 100644 --- a/tests/unit/llm/test_llm.py +++ b/tests/unit/llm/test_llm.py @@ -1274,6 +1274,25 @@ def test_opus_45_keeps_temperature_drops_top_p(mock_completion): assert 'top_p' not in call_kwargs +@patch('openhands.llm.llm.litellm_completion') +def test_opus_46_keeps_temperature_drops_top_p(mock_completion): + mock_completion.return_value = { + 'choices': [{'message': {'content': 'ok'}}], + } + config = LLMConfig( + model='anthropic/claude-opus-4-6', + api_key='k', + temperature=0.7, + top_p=0.9, + ) + llm = LLM(config, service_id='svc') + llm.completion(messages=[{'role': 'user', 'content': 'hi'}]) + call_kwargs = mock_completion.call_args[1] + assert call_kwargs.get('temperature') == 0.7 + # Anthropic rejects both temperature and top_p together on Opus 4.6; we keep temperature and drop top_p + assert 'top_p' not in call_kwargs + + @patch('openhands.llm.llm.litellm_completion') def test_sonnet_4_keeps_temperature_drops_top_p(mock_completion): mock_completion.return_value = {