Claude Code v2.1.284 Major Updates - Sonnet 5.5 Arrives and Auto Mode Default Expansion to All Plans

Claude Code v2.1.284 Major Updates - Sonnet 5.5 Arrives and Auto Mode Default Expansion to All Plans

Claude Code v2.1.284 released. Adds Sonnet 5.5, defaults to auto mode when permissions unset. Security and model improvements. Migration results using /claude-api migrate for Sonnet 5.5 code included.
2026.09.29

This page has been translated by machine translation. View original

Here is the translated content:

This is Ishikawa from the Cloud Business Division. Claude Code v2.1.284 (released 2026-09-28) has been released. Today, I tried using /claude-api migrate to automatically migrate code for the new Sonnet 5.5. Since this release includes changes to the behavior at the start of permission modes, please also check the breaking changes.

The previous update article is here.

https://dev.classmethod.jp/articles/20260924-cc-updates-v2-1-283/

Update Summary

v2.1.284 includes 100 changes. In this article's classification, there are 53 fixes, 21 improvements, 13 new features, 6 security updates, 5 breaking changes, and more. In addition to changes in the VS Code extension (18 items) and Claude Tag (10 items), there are also grouped changes around the Claude apps gateway and usage limits.

Also, Sonnet 5.5, which is smarter, more efficient, and 30% faster than Sonnet 5, has been announced. Since it costs up to 30% less for most tasks, Claude Code usage will expand even further. Use it for well-defined daily tasks such as bug fixes and rapid feature iteration.

https://x.com/ClaudeDevs/status/2104641318555353400

Highlighted Updates

New Feature: Addition of Claude Sonnet 5.5

Claude Sonnet 5.5 (claude-sonnet-5-5) has been added and became the default Sonnet model in the Anthropic API. With 1M context, the pricing is $2 input / $10 output per million tokens, and $0.20 for cache reads.

For those using sonnet in the Anthropic API, it would be good to be aware that the default Sonnet is changing.

Bug Fix: Fixed a bug where "Prompt is too long" error persists after compact

A bug where the "Prompt is too long" error persisted after compact has been fixed. If the request after compact is still too long, it reduces the amount of recent conversation retained and compacts again.

I feel this is a fix that will help those who have experienced being stuck in an error even after compact in long sessions. On the other hand, since re-compacting reduces the amount of recent conversation retained, I think it's worth being aware that previous instructions may drop out of the summary.

Bug Fix: Fixed a bug where raw errors are displayed for corrupted response streams

A bug where raw errors such as "JSON Parse error" or "undefined is not an object" were displayed, or the word "undefined" was written into responses when the response stream was corrupted, has been fixed. It will either be retried or reported as an interrupted response.

Since having "undefined" mixed into a response poses a risk of using it without noticing, I feel it's reassuring that it will now be handled as a retry or interruption.

Security: Auto mode start when permission mode is not set expanded to all plans and all providers

When a permission mode is not set, interactive terminal and VS Code sessions will now start in auto mode. This applies to all plans and all providers, and if permissions.defaultMode is set, that takes priority.

I think the impact is greater for those who have been using it without being aware of permission modes. If you want to continue using Manual mode, I feel it's safer to explicitly set permissions.defaultMode, referring to the configuration example in the breaking changes section below.

Security: Fixed pre-approval of plugins under allowManagedPermissionRulesOnly

Under the management setting allowManagedPermissionRulesOnly, a problem where plugins from the marketplace, claude.ai, and npm could pre-approve their own tools via allowed-tools has been fixed. Pre-approval is maintained only for plugins from official Anthropic sources and plugins from sources trusted by management settings.

For organizations that have consolidated permission rules on the admin side with allowManagedPermissionRulesOnly, tools of plugins from sources not trusted by management settings will no longer be pre-approved, so I believe that if there are plugins whose pre-approval you want to maintain, you will need to configure those sources as trusted in the management settings.

Security: Sanitization of invisible characters and tags mimicking Claude Code markup in MEMORY.md

When loading automatic memory, invisible characters and tags mimicking Claude Code's own markup contained in MEMORY.md and invoked memory notes will now be sanitized before being passed to Claude.

For those using automatic memory, I see this as an improvement that applies simply by updating, without any special configuration.

Update Details

New Features

  • Addition of Claude Sonnet 5.5 (claude-sonnet-5-5) (see Highlighted Updates)
  • "Yes, but ask again next time" has been added to the confirmation before reading outside the working directory in auto mode. This allows only that one read, and subsequent reads will prompt for confirmation again
  • /mcp reconnect all has been added to the interactive terminal, allowing you to reconnect MCP servers that failed to connect or require authentication all at once
  • Key binding actions effortSlider:decreaseEffort, increaseEffort, and toggleUltracode have been added, allowing you to reassign the arrow keys and Tab key for the /effort slider in keybindings.json
  • Regarding Claude apps gateway spend limits, if the gateway is running on this version or later, the amount will be displayed (e.g., "$271.40 / $500.00 spent this month") in /usage and the status line. rate_limits.spend_limit in the status line now includes used_usd, limit_usd, and period
  • In the Claude apps gateway, a startup warning will now be displayed if availableModels in the management policy is empty, or if the startup model for Claude Code is not included without setting model or enforceAvailableModels
  • You can now specify auth: { google: {} } as the destination for telemetry.forward_to in the Claude apps gateway, allowing you to directly export telemetry to Google Cloud OTLP endpoints using the gateway's Google Cloud credentials
  • Certificate-based client authentication (private_key_jwt) between the Claude apps gateway and identity providers is now supported. This is for identity providers that issue certificate credentials instead of client secrets
  • [VS Code] An option to display the time above each prompt and response has been added, with a date row inserted where the date changes (setting "Claude Code: Show Message Timestamps", default is off)
  • [VS Code] Plugin load errors and notes are now displayed on each row in Manage plugins, with a popup added that allows disabling, uninstalling, and copying errors
  • [VS Code] An Ultracode on/off switch has been added below the Effort slider, replacing the Ultracode step on the slider. The model pill will display "· Ultracode" at any effort level
  • [Claude Tag] You can now select a model family like "Opus (latest)" for threads, channel defaults, and DMs, and the selection will follow the latest model in that family
  • [Claude Tag] The analytics spending forecast chart now includes the spending that counts toward the organization-wide limit and the percentage of the limit used

Improvements

  • Improved startup time and memory usage by building the configuration schema only for the parts actually used in the configuration file
  • Changed retries after a connection drop mid-response to share the same retry count as other retries for that request. Requests that keep failing will be cut off sooner
  • Changed the first turn in non-interactive mode so that even if CLAUDE_CODE_MCP_STARTUP_WAIT_MS is 0, it waits up to 2 seconds for connecting MCP servers specified in --allowedTools or mcp_tool hooks
  • Improved the usage limit waiting display. The limit status and a countdown including usage credit options are now consolidated into one block below the prompt, and the limit message no longer repeats the countdown
  • /rate-limit-options is now displayed in /help and the command menu for claude.ai subscribers, making it easier to find the command pointed to by usage limit notifications
  • The notification when Sonnet model safeguards flag a message has been changed to explain the reason and show an option to edit and retry
  • The "No such tool available" error when Claude in Chrome tools are called without a prefix now shows the tool name that should be called
  • Monitor event rows now display the output content of each event rather than repeating the description, and no longer repeats unchanged "Waiting for N … to finish" rows for each event
  • /claude-api has been improved. hillclimb no longer spends rounds on rewording prompts that are too small to measure in evals, and additionally requested pages are now created as standalone local files that load nothing from the network, placed alongside report.html
  • In lists such as /tasks, /copy, and /hooks, details after each name are now aligned in one column if they fit, and placed at the right edge if they don't
  • claude plugin marketplace add now shows a message and how to undo when it replaces a marketplace that has already been added from a different source with the same name
  • The startup rejection message when API keys, tokens, or apiKeyHelper are configured while management settings require sign-in (forceLoginMethod or forceLoginOrgUUID) now shows the credentials in use, where they are configured, and how to remove them
  • Running claude remote-control in an untrusted folder will now prompt for workspace trust in the terminal without exiting
  • /recap has been changed to output a short notification and decline to run when relayed from chat threads (including your own), routines, or Webhooks. It continues to run as before when entered from a terminal, Claude app, Remote Control, -p, or SDK host
  • On artifact pages, Claude now writes design guidelines within the page rather than as a reply, and uses the name the user has already given as the page title
  • The Artifact tool will now request the correct link or content without stopping when only a claude.ai chat or project link, an in-chat artifact, or only an artifact ID is passed
  • The /artifacts filter tabs are now displayed as single-word labels (All · Mine · Shared) next to the title, using the same tab bar as /config and /plugin
  • [Claude Tag] Changed to post a private sign-in guide every time, not just the first time, in response to @mentions from users who have not connected a Claude account. Additionally, improvements have been made to the delivery scope of "Notify members now" in management settings, waiting notifications for on-demand runners in self-hosted environments, error display and GitHub sign-in when adding channel managers, and the display of channel access lists

Security

  • Fix for pre-approval of plugins under allowManagedPermissionRulesOnly (see Highlighted Updates)
  • Sanitization of invisible characters and tags mimicking Claude Code markup in MEMORY.md (see Highlighted Updates)
  • Fixed a problem where the value of ANTHROPIC_FOUNDRY_RESOURCE was embedded in the Foundry endpoint hostname without validation. Values that are not simple resource names will be rejected
  • Fixed a bug where rules symlinked to .claude/rules from outside the project were skipped without ever displaying an approval prompt for external imports. The same approval is now required for .claude directories symlinked from outside the project
  • Fixed a bug where a key pressed the moment a terminal regains focus could answer the Remote Control activation confirmation before the short safety delay resumes
  • Hardened handling of errors thrown by async script hooks in the Workflow tool sandbox

Fixes

  • Fixed raw error display for corrupted response streams: See Highlighted Updates
  • Fixed bug where "Prompt is too long" error persists after compact: See Highlighted Updates
  • Fixed bug where a turn ends with an error immediately after a thinking block: Fixed a bug where receiving an overloaded error or server error immediately after a thinking block would end the turn with an error instead of retrying
  • Fixed crash due to invalid image/document blocks in Agent SDK sessions: Fixed a bug where including an image with an invalid source in a user message caused a crash, and a bug where all turns after an invalid document block failed. Invalid images are replaced with a descriptive note
  • Fixed bug where MCP tool calls fail in resumed sessions: Fixed a bug where MCP tool calls failed with "No such tool available" while an MCP server was connecting. Calls will now wait up to 10 seconds for the server to connect
  • Fixed bug where claude mcp add reports success under MCP server restrictions: Fixed a bug where it reported success when management settings restricted MCP servers to plugin sources. Servers that will not be loaded are not saved, and the rejection is displayed along with how to address it
  • Fixed Bash tool failures when many plugins are enabled on Windows: bin/ directories of non-existent plugins will not be added to PATH, and inherited entries will not be added twice
  • Fixed {"decision":"block"} in Elicitation-type hooks being ignored: {"decision":"block"} returned by Elicitation and ElicitationResult hooks now rejects MCP elicitation in the same way as exit code 2
  • Fixed Explore subagent switching to Opus with unrecognized model IDs: When running a session with a model ID that Claude Code does not recognize, such as a custom model via proxy, the Explore subagent was switching to Opus on the Claude API. Explore now inherits the session's model
  • Fixed Claude apps gateway returning 431 errors: Fixed a bug where requests from sign-ins where the identity provider returned many groups always returned 431 Request Header Fields Too Large. Request headers up to 256 KiB are now accepted
  • [VS Code] Fixed "Prompt is too long" after compact when attaching large text files: This was a bug that occurred when attaching large text files to a message
  • A quietly welcome fix: [VS Code] Fixed a bug where in-chat links to files with non-ASCII characters, spaces, or parentheses in the path could not be opened. For environments using Japanese file or folder names, being able to open files directly from in-chat links is a welcome improvement.
  • In addition, numerous minor bugs have been fixed in full-screen rendering, vim mode, plugin marketplace and installation, usage limit notifications, the VS Code extension, Claude Tag, and more.

Breaking Changes

Auto mode start when permission mode is not set expanded to all plans and all providers

This is the change to the startup mode of interactive terminal and VS Code sessions introduced in the Highlighted Updates.

Before the change (up to v2.1.283): Example when starting without setting permissions.defaultMode

claude   # Starts in Manual (default) mode depending on plan or provider

After the change (v2.1.284 and later):

claude   # Starts in auto mode for all plans and all providers

If you want to continue starting in Manual mode as before, explicitly set permissions.defaultMode (example configuration in ~/.claude/settings.json).

{
  "permissions": {
    "defaultMode": "default"
  }
}

The official documentation explains that default is the configuration value for Manual mode. Note that the official documentation's description of startup modes states that auto mode start for all plans and all providers applies "from v2.1.283 onward," but the CHANGELOG records it as a change in v2.1.284 (as of 2026-09-29). This article follows the CHANGELOG.

Ultracode no longer forces xhigh effort

Ultracode has been changed to a separate toggle within /effort (Tab key, or /effort ultracode [on|off]). It no longer forces xhigh effort and can be kept on at any effort level. In the VS Code extension, an Ultracode on/off switch has also been added below the Effort slider.

Example before the change (up to v2.1.283):

/effort   # Selecting Ultracode fixes effort to xhigh

Example after the change (v2.1.284 and later):

/effort ultracode on   # Turn Ultracode on (effort level remains the same)
/effort xhigh          # Specify the effort level as well if you want to use xhigh as before

The safety-related model switch behavior for sessions where an Opus model is fixed using ANTHROPIC_DEFAULT_OPUS_MODEL or modelOverrides has changed. In the Anthropic API, instead of the fixed model, the API selects the fallback model based on the type of flag.

Example before the change (up to v2.1.283): Based on the CHANGELOG description, it is inferred that the fixed model was used as the fallback.

export ANTHROPIC_DEFAULT_OPUS_MODEL=<Opus model ID to fix>
# The fallback for safety-related model switches was the fixed model (inferred)

Example after the change (v2.1.284 and later):

export ANTHROPIC_DEFAULT_OPUS_MODEL=<Opus model ID to fix>
# In the Anthropic API, the API selects the fallback model based on the type of flag

Rejecting artifact publishing for files on network shares

Artifact publishing has been changed to reject files on network shares (\\host\share paths or /net automounts), except for files on mapped network drives added via --add-dir.

Example before the change (up to v2.1.283): Files with paths like the following on network shares (paths are examples). Based on the CHANGELOG description, it is inferred that these files could be published before the change.

\\fileserver\share\report.html
/net/fileserver/share/report.html

After the change (v2.1.284 and later): The above paths will be rejected. You can publish files on mapped network drives by adding them with --add-dir (example):

claude --add-dir Z:\share

[VS Code] CLAUDE_CONFIG_DIR only applies when it is an absolute path

CLAUDE_CONFIG_DIR in the claudeCode.environmentVariables setting has been changed to only apply when it is an absolute path, and it will also now be passed to terminals that inherit the conversation.

Below are examples of CLAUDE_CONFIG_DIR values specified in claudeCode.environmentVariables. The fact that relative paths also applied before the change is inferred from the CHANGELOG description.

Before the change (up to v2.1.283):

CLAUDE_CONFIG_DIR = .claude-work             # Also applied with relative paths (inferred)

After the change (v2.1.284 and later):

CLAUDE_CONFIG_DIR = /Users/you/.claude-work  # Only applies when it is an absolute path

Trying to migrate code for Sonnet 5.5 using /claude-api migrate

Claude Sonnet 5.5 has the same 1M context and same token pricing as Sonnet 5, but there are incompatible changes in how the API is used. The Anthropic blog post "Claude Sonnet 5.5: What's New for API Developers" lists 5 breaking changes and 1 response format change as changes that require attention when migrating from Sonnet 5. It also introduces that Claude Code's /claude-api migrate can be used to apply model ID replacement and these changes to a codebase.

So, I tried using /claude-api migrate to rewrite a Python program written for Sonnet 5 for Sonnet 5.5.

Changes that require attention when migrating from Sonnet 5 to Sonnet 5.5

The following blog post lists 6 changes. In this sample, items 1 and 2 apply.

https://claude.dev/blog/building-with-claude-sonnet-5-5/

# Change content Applies to this sample
1 thinking: {"type": "disabled"} results in a 400 error. To stop thinking, use {"type": "between_tools"} (only when effort is high or below) Applies (advise)
2 tool_choice any / tool (forcing tool calls) results in a 400 error. Replace with auto and strict: true tools, and instruct when to use them in the prompt Applies (ask_weather)
3 Thinking blocks are bound to the model and conversation. Conversations should be append-only Does not apply (single requests only)
4 In the Claude API and Google Cloud, computer use can only be used with computer_toolset_20260801 Does not apply
5 The advisor models that can be combined with the advisor tool have changed Does not apply
6 Text between tool calls is returned in thinking blocks Does not apply

The migration guide in the claude-api skill bundled with Claude Code includes the error messages when items 1 and 2 are sent to Sonnet 5.5 as-is.

"thinking.type.disabled" is not supported for this model. Use "thinking.type.between_tools" for the lowest thinking setting, or "thinking.type.adaptive" and "output_config.effort" to control thinking behavior.
tool_choice: type "tool" and "any" are not supported for this model.

In other words, simply replacing the model ID with claude-sonnet-5-5 will not make this sample work.

Step 1: Prepare a sample for Sonnet 5

I prepared a sample for Sonnet 5 that checks the weather and gives a brief clothing recommendation. In ask_weather, tool_choice forces the get_weather tool call, and in advise, thinking is disabled to prioritize response speed. Both are valid approaches in Sonnet 5 but will result in 400 errors in Sonnet 5.5.

weather_bot_before.py
"""A sample that checks the weather and gives a brief clothing recommendation (for Claude Sonnet 5)"""
import json
import sys

import anthropic

MODEL = "claude-sonnet-5"

client = anthropic.Anthropic()

WEATHER_TOOL = {
    "name": "get_weather",
    "description": "Get the current weather in a specified city",
    "input_schema": {
        "type": "object",
        "properties": {"city": {"type": "string", "description": "City name"}},
        "required": ["city"],
    },
}

def get_weather(city: str) -> dict:
    # Fixed data for demo (actually calls a weather API)
    return {"city": city, "condition": "Sunny", "temperature_c": 24}

def ask_weather(question: str) -> dict:
    """Force the get_weather tool to be called and retrieve weather from the tool's input"""
    response = client.messages.create(
        model=MODEL,
        max_tokens=1024,
        tools=[WEATHER_TOOL],
        tool_choice={"type": "tool", "name": "get_weather"},
        messages=[{"role": "user", "content": question}],
    )
    tool_use = next(b for b in response.content if b.type == "tool_use")
    return get_weather(**tool_use.input)

def advise(weather: dict) -> str:
    """Return a brief clothing recommendation for the weather (thinking disabled to prioritize response speed)"""
    response = client.messages.create(
        model=MODEL,
        max_tokens=1024,
        thinking={"type": "disabled"},
        messages=[
            {
                "role": "user",
                "content": f"Please tell me in one sentence what to wear for this weather: {json.dumps(weather, ensure_ascii=False)}",
            }
        ],
    )
    return next(b.text for b in response.content if b.type == "text")

if __name__ == "__main__":
    question = sys.argv[1] if len(sys.argv) > 1 else "What's the weather in Tokyo?"
    weather = ask_weather(question)
    print(weather)
    print(advise(weather))

Step 2: Run /claude-api migrate

In a Claude Code interactive session, enter the following:

/claude-api migrate weather_bot_before.py to weather_bot_after.py

20260929-cc-updates-v2-1-281-1

Specify the target model for migration. This time, it is sonnet5.5.

20260929-cc-updates-v2-1-281-3

Then, weather_bot_after.py is created.

weather_bot_after.py
"""A sample that checks the weather and gives a brief clothing recommendation (for Claude Sonnet 5.5)"""
import json
import sys

import anthropic

MODEL = "claude-sonnet-5-5"

client = anthropic.Anthropic()

# Re-run the same request with a different model when rejected by the safety classifier (Claude API only)
FALLBACK_OPTIONS = {
    "betas": ["server-side-fallback-2026-07-01"],
    "fallbacks": "default",
}

# Since tool_choice forcing is not available, tool call verification and retries are handled in code
MAX_TOOL_ATTEMPTS = 3

WEATHER_TOOL = {
    "name": "get_weather",
    "description": "Get the current weather in a specified city",
    "strict": True,
    "input_schema": {
        "type": "object",
        "properties": {"city": {"type": "string", "description": "City name"}},
        "required": ["city"],
        "additionalProperties": False,
    },
}

def get_weather(city: str) -> dict:
    # Fixed data for demo (actually calls a weather API)
    return {"city": city, "condition": "Sunny", "temperature_c": 24}

def check_refusal(response) -> None:
    """Reject refused responses (HTTP 200 + stop_reason="refusal") before reading content"""
    if response.stop_reason == "refusal":
        category = response.stop_details.category if response.stop_details else None
        raise RuntimeError(f"Request was refused (category={category})")

def ask_weather(question: str) -> dict:
    """Have the get_weather tool called and retrieve weather from the tool's input"""
    for _ in range(MAX_TOOL_ATTEMPTS):
        response = client.beta.messages.create(
            model=MODEL,
            max_tokens=16000,
            system="Please retrieve the weather of the city in the question by calling the get_weather tool.",
            tools=[WEATHER_TOOL],
            output_config={"effort": "low"},
            messages=[{"role": "user", "content": question}],
            **FALLBACK_OPTIONS,
        )
        check_refusal(response)
        tool_use = next((b for b in response.content if b.type == "tool_use"), None)
        if tool_use is not None:
            return get_weather(**tool_use.input)
    raise RuntimeError(f"get_weather tool was not called {MAX_TOOL_ATTEMPTS} times")

def advise(weather: dict) -> str:
    """Return a brief clothing recommendation for the weather (set effort to low to prioritize response speed)"""
    response = client.beta.messages.create(
        model=MODEL,
        max_tokens=16000,
        output_config={"effort": "low"},
        messages=[
            {
                "role": "user",
                "content": f"Please tell me in one sentence what to wear for this weather: {json.dumps(weather, ensure_ascii=False)}",
            }
        ],
        **FALLBACK_OPTIONS,
    )
    check_refusal(response)
    return next(b.text for b in response.content if b.type == "text")

if __name__ == "__main__":
    question = sys.argv[1] if len(sys.argv) > 1 else "What's the weather in Tokyo?"
    weather = ask_weather(question)
    print(weather)
    print(advise(weather))

Step3: Check the diff

Use diff to see exactly how it was rewritten.

% diff weather_bot_before.py weather_bot_after.py
1c1
< """天気を調べて服装を一言アドバイスするサンプル(Claude Sonnet 5 向け)"""
---
> """天気を調べて服装を一言アドバイスするサンプル(Claude Sonnet 5.5 向け)"""
7c7
< MODEL = "claude-sonnet-5"
---
> MODEL = "claude-sonnet-5-5"
10a11,19
> # 安全性分類器に拒否されたとき、同じリクエストを別モデルで再実行する(Claude API のみ)
> FALLBACK_OPTIONS = {
>     "betas": ["server-side-fallback-2026-07-01"],
>     "fallbacks": "default",
> }
>
> # tool_choice の強制が使えないため、呼び出しの確認とリトライはコード側で行う
> MAX_TOOL_ATTEMPTS = 3
>
13a23
>     "strict": True,
17a28
>         "additionalProperties": False,
26a38,44
> def check_refusal(response) -> None:
>     """拒否された応答(HTTP 200 + stop_reason="refusal")を content を読む前に弾く"""
>     if response.stop_reason == "refusal":
>         category = response.stop_details.category if response.stop_details else None
>         raise RuntimeError(f"リクエストが拒否されました (category={category})")
>
>
28,37c46,61
<     """get_weather ツールを必ず呼ばせて、ツールの入力から天気を取得する"""
<     response = client.messages.create(
<         model=MODEL,
<         max_tokens=1024,
<         tools=[WEATHER_TOOL],
<         tool_choice={"type": "tool", "name": "get_weather"},
<         messages=[{"role": "user", "content": question}],
<     )
<     tool_use = next(b for b in response.content if b.type == "tool_use")
<     return get_weather(**tool_use.input)
---
>     """get_weather ツールを呼ばせて、ツールの入力から天気を取得する"""
>     for _ in range(MAX_TOOL_ATTEMPTS):
>         response = client.beta.messages.create(
>             model=MODEL,
>             max_tokens=16000,
>             system="質問に含まれる都市の天気を、get_weather ツールを呼び出して取得してください。",
>             tools=[WEATHER_TOOL],
>             output_config={"effort": "low"},
>             messages=[{"role": "user", "content": question}],
>             **FALLBACK_OPTIONS,
>         )
>         check_refusal(response)
>         tool_use = next((b for b in response.content if b.type == "tool_use"), None)
>         if tool_use is not None:
>             return get_weather(**tool_use.input)
>     raise RuntimeError(f"get_weather ツールが {MAX_TOOL_ATTEMPTS} 回呼び出されませんでした")
41,42c65,66
<     """天気に合う服装を一言で返す(応答の速さを優先して thinking を無効化)"""
<     response = client.messages.create(
---
>     """天気に合う服装を一言で返す(応答の速さを優先して effort を low にする)"""
>     response = client.beta.messages.create(
44,45c68,69
<         max_tokens=1024,
<         thinking={"type": "disabled"},
---
>         max_tokens=16000,
>         output_config={"effort": "low"},
51a76
>         **FALLBACK_OPTIONS,
52a78
>     check_refusal(response)

Organizing the diff by Claude's explanatory categories gives the following:

Category Change Location
Required Change model ID from claude-sonnet-5 to claude-sonnet-5-5 MODEL
Required Change forced tool_choice to {"type": "auto"} and instruct tool use via system prompt. Retry once if tool is not called ask_weather
Required Add strict: True and additionalProperties: False to tool definition WEATHER_TOOL
Required Remove thinking={"type": "disabled"} and specify output_config={"effort": "low"} advise
Additional changes included Change max_tokens from 1024 to 16000 Both calls
Additional changes included Add exception handling when stop_reason is refusal Both calls
Additional changes included Switch to client.beta.messages.create and add server-side fallback (betas and fallbacks="default") Both calls

Step4: Cross-reference with the migration guide and verify syntax

I cross-referenced the Sonnet 5.5 section of the bundled migration guide against the rewritten code.

  • Disabling thinking: The migration guide recommends first trying adaptive thinking with low effort, and only using {"type": "between_tools"} with high or lower effort when thinking needs to be stopped. The rewritten advise follows the first approach (omitting the thinking specification and setting effort to low).
  • Forced tool_choice: The migration guide describes replacing it with a combination of auto, a prompt indicating where to use the tool, and strict: true, and notes that since auto does not guarantee a call, you should check whether the tool was called and retry if not. The rewritten ask_weather follows this pattern.

Summary

Migrating from Sonnet 5 to Sonnet 5.5 is not as simple as just swapping the model ID, but using /claude-api migrate lets you delegate the work of applying breaking change fixes to your code. The more files a project has to migrate, the greater the benefit.

Closing Thoughts

We confirmed that Sonnet 5.5 becomes the default Sonnet in the Anthropic API at the same token price as Sonnet 5, and that Claude API code migration can be handled with /claude-api migrate. Whether you're using Claude Code or the Claude API, this feels like a release that makes moving to Sonnet 5.5 easy.

If you're using Sonnet, why not update and try migrating your Claude API code with /claude-api migrate as well?

References

https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md

https://code.claude.com/docs/en/changelog

https://code.claude.com/docs/en/permission-modes

https://code.claude.com/docs/en/model-config

https://dev.classmethod.jp/articles/20260924-cc-updates-v2-1-283/


Claudeならクラスメソッドにお任せください

クラスメソッドは、Anthropic社とリセラー契約を締結しています。各種製品ガイドから、業種別の活用法、フェーズごとのお悩み解決などサービス支援ページにまとめております。まずはご覧いただき、お気軽にご相談ください。

サービス詳細を見る

Share this article

AI白書