Key Updates in Claude Code v2.1.317 - Changing Effort for Subagents on Different Models and Removal of Read Stubs

Key Updates in Claude Code v2.1.317 - Changing Effort for Subagents on Different Models and Removal of Read Stubs

Claude Code v2.1.317 is out. This post covers its 87 changes by security, breaking changes and new features, focusing on effort changes for subagents on other models and removal of the Read tool stub. I tried the subagent effort.
2026.11.03

This page has been translated by machine translation. View original

I'm Ishikawa from the Cloud Business Division. Claude Code v2.1.317 (released 2026-11-02) is out. This time I'll focus on the change to the effort of subagents running on a different model and the removal of the Read tool stub. Today, I tried out the effort of subagents running on a different model.

The previous update article is here.

https://dev.classmethod.jp/articles/20261031-cc-updates-v2-1-316/

Update Summary

v2.1.317 includes 87 changes. According to the CHANGELOG, there are 62 Fixed, 10 Added, 8 Improved, 6 Changed, and 1 Removed. In this article, 7 of these related to permissions, confirmations, and handling of failures are grouped under Security, and 3 that affect existing usage are treated as Breaking Changes / Deprecations. The release also includes changes targeting self-hosted runners (9), the VS Code extension (7), Claude apps gateway (5), and cloud sessions (4).

Also, according to the official X post, Message threads were released (public beta).

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

Message threads is a new feature of the Messages API that saves you from resending the conversation history every turn. You start a thread by sending the full history in the first request with the thread parameter, and after that you send only the new message and the previous response ID. The thread is not written to disk but held in memory in an encrypted state, and it expires 5 minutes after the last request. Claude reads the full text each time, so token consumption does not change, but the time until the response starts is shortened. As a result, the median is reduced by about 35% at 500K to 1M tokens. It is well suited to long-running coding agents and Computer Use.

https://claude.com/ja/resources/articles/message-threads

Notable Updates

Added a confirmation before sending the account email address over the network

A check has been added that asks for confirmation before a Web tool or shell tool call sends the account email address over the network.

Note that the v2.1.234 CHANGELOG states that Claude is now instructed to use the account email address only to identify the user and not to send it to unrelated services unless requested. What has been added this time is a check that asks for confirmation before a tool call sends the email address.

For those who often delegate external access to Web tools and shell tools, I feel it will be easier to notice unintended transmissions because a confirmation comes up before the account email address is sent.

Added onFailure: "block" to Agent SDK hook callbacks

onFailure: "block" has been added to Agent SDK hook callbacks. When a callback fails, it blocks the action instead of letting it run as is.

onFailure: "block" was added to command hooks and HTTP hooks in v2.1.295 (a hook that cannot be started, times out, or exits with an unexpected exit code blocks the action instead of letting it through). In v2.1.317, it can also be specified for Agent SDK hook callbacks. As for the behavior when it is not specified, based on the phrase "instead of letting it run" in the CHANGELOG, I infer that the action is executed even if the callback fails.

If you implement permission checks or auditing with Agent SDK hooks, I think it is a good idea to specify onFailure: "block" on hooks where you want processing to stop on failure.

Changed subagents on a different model to run with that model's saved effort

Subagents and teammates that run on a model different from the main conversation now use that model's saved effort level, or that model's default, instead of the session's effort level.

The official documentation explains that Claude Code saves the effort level per model under the modelSettings key in the user settings. The model's default effort is high for models that support effort, medium for Opus 5.5, Sonnet 5.5, and Haiku 5.5, and xhigh for Opus 4.7. The behavior before and after the change is summarized below in "Breaking Changes / Deprecations", and the actual behavior is verified in "Trying it out".

If you run the main conversation at a high effort while using Sonnet or Haiku subagents, the subagents' effort may change, so I think it is a good idea to check that model's saved effort.

Removed the Read tool's "file unchanged since your last Read" stub

The Read tool's "file unchanged since your last Read" stub has been removed. When you read an unchanged file again, the content of that file is returned.

In long tasks that reread the same file many times, the content is returned on every reread, so I expect context consumption may increase compared to before.

Fixed the issue where claude -p inside a session shares the session ID, and added CLAUDE_CODE_DISABLE_NESTED_SESSION_ID

An issue where claude -p run inside a cloud or self-hosted runner session shared that session's ID has been fixed. Previously, claude -p could write to the session's transcript, and a different conversation could be resumed on restart. An issue where claude -p under the same conditions generated its own title and sent it to the session has also been fixed.

In addition, the environment variable CLAUDE_CODE_DISABLE_NESTED_SESSION_ID has been added. When set to 1 on a self-hosted runner, claude -p run inside a session uses that session's ID and transcript, as in previous versions.

If you call claude -p inside self-hosted runner sessions, the handling of session IDs changes, so I think it is safest to check whether you need CLAUDE_CODE_DISABLE_NESTED_SESSION_ID.

Added a cost report to the Claude apps gateway admin API

A cost report, GET /v1/organizations/analytics/cost, has been added to the Claude apps gateway admin API. By specifying a date range, you can read past spending as a total, by developer, by day, and by IdP group.

The per-IdP-group aggregation uses the daily record of IdP groups, which was also added. On a Claude apps gateway configured with admin:, each developer's IdP groups are recorded daily and retained for the period of admin.identity_retention_days.

Organizations that manage developers' usage fees with the Claude apps gateway can read past spending by IdP group, so I think this could be used to understand costs on a group basis.

Update Details

New Features

  • Added a notification of the loading status of remote managed settings to the Code tab in Claude Desktop: A notification is displayed when the organization's remote managed settings have not been loaded into the session, and also when they have been loaded.
  • Added a notification for when the auto mode check returns no answer: A notification is displayed when the auto mode check returned no answer for a subagent's tool call. Previously, nothing was shown on the main screen.
  • Added attributes to OTel metrics, events, and spans: anthropic.plan, anthropic.seat_type, anthropic.provider, and anthropic.custom_base_url have been added.
  • Added a cost report to the Claude apps gateway admin API: With GET /v1/organizations/analytics/cost, you can specify a date range and read past spending as a total, by developer, by day, and by IdP group.
  • Added a daily record of developers' IdP groups to the Claude apps gateway: It is recorded on a Claude apps gateway configured with admin: and retained for the period of admin.identity_retention_days. It is used for the per-IdP-group aggregation in the cost report.
  • Added the environment variable CLAUDE_CODE_DISABLE_NESTED_SESSION_ID: When set to 1 on a self-hosted runner, claude -p run inside a session uses that session's ID and transcript, as in previous versions (also covered in "Breaking Changes / Deprecations" below).
  • [Cloud sessions] Added link cards: For links that an MCP server asks to open, you can choose to open or decline. Requests no longer go without being displayed.

Security

  • Added a confirmation before sending the account email address over the network: Asks for confirmation before a Web tool or shell tool call sends the account email address over the network.
  • Added onFailure: "block" to Agent SDK hook callbacks: When a callback fails, it blocks the action instead of letting it run as is.
  • Added a warning to /schedule for connectors that were not requested: A warning is displayed when a new cloud scheduled task is given a connector that was not requested. The warning also shows how to remove it.
  • Fixed an issue where no information was displayed in the second of two permission prompts shown at the same time: In claude.ai and the mobile app, the file path or command was not displayed in the second of two permission prompts shown simultaneously.
  • Fixed an issue where "don't ask again" was offered for mod tool calls: This occurred in Remote Control and SDK hosts.
  • Fixed an issue where agent team teammates started in auto mode: When the lead session was in manual mode, teammates running in tmux or iTerm2 panes started in auto mode.
  • Fixed an issue where permission mode changes were lost in background sessions: When a background session was upgraded or terminated, the most recently changed permission mode could be lost.

Improvements / Developer Experience

  • Changed SendMessage: Messages to a running background agent arrive sooner. A running command is moved to the background without being stopped.
  • Improved the "Resume this session with" hint on exit: The flags specified at startup (for example, --chrome --debug) are now included before --resume in the displayed hint.
  • Improved the error when Azure credentials cannot be loaded in Microsoft Foundry: It prompts you to check and refresh the credentials and reports it as cloud_credential_error.
  • Improved the startup error when a required Claude apps gateway cannot be reached: It points to the network rather than sign-in, and if the gateway's TLS certificate cannot be verified, it says so.
  • Improved /design-sync: If the design system has already been migrated to Claude, it says so first, and it stops before the build instead of failing at upload time.
  • Changed the prompt when plugin monitors exit: For plugin monitors, the "Background work is running" prompt is no longer shown on exit.
  • Changed the built-in plugin-authoring skill: After a created mod works, it suggests helping you share the mod, only once.
  • Improved Remote Control fork names: When the app does not set a fork name, the "(fork)" suffix is kept even for long names, and for sessions started with claude remote-control, a fork of "Name (fork)" becomes "Name (fork 2)".
  • [Cloud sessions] Changed the admin settings organization environment dialog: It now has the same short layout as the personal dialog, each section opens from its row, and if there is unsaved input, you are asked to confirm before closing.
  • [Claude Tag] Changed links to artifacts newly pasted in Slack: They are displayed as a simple card with an Open button that opens the artifact in Claude, rather than in the Slack side panel.
  • Improved self-hosted runner recovery from server errors and unresponsive connections: After a 5xx other than 501 and 529, the runner's next poll and sessions open a new connection instead of reusing the failed one. Sessions also open a new connection when a heartbeat gets no response, instead of trying idle connections one after another.

Fixes

  • Fixed claude -p finishing with exit code 0 when disk space is insufficient: When writing the transcript or ~/.claude.json was lost due to insufficient free disk space or a quota, it exited with exit code 0. After the fix, it shows an error and exits with exit code 1 in the text and json output formats. A full NFS export may go undetected.
  • Fixed claude auth status exiting before saving a token refresh: It could exit before saving a time-consuming token refresh, causing you to be signed out on the next run.
  • Fixed MCP servers disconnecting after the first turn in Claude Desktop: In some Claude Desktop sessions, project and local MCP servers were disconnected.
  • Fixed partial Grep and Glob results being treated as complete results: When a search hit its time limit, Claude treated the partial results as complete results.
  • Fixed "Prompt is too long" after a large CLAUDE.md change: This occurred after auto-compaction in sessions where a very large CLAUDE.md had changed since the previous send.
  • Fixed certificate errors behind TLS-inspecting proxies: After a root certificate update, API requests behind some TLS-inspecting proxies failed with "unable to get local issuer certificate".
  • Fixed an empty AWS_BEARER_TOKEN_BEDROCK being passed to stdio MCP servers: When it was set to empty in the env settings, the empty value was passed. After the fix, the variable is left unset, and the server can use the machine's own AWS credentials.
  • Fixed the Claude apps gateway hiding Amazon Bedrock's "Input is too long." error: Sessions failed every turn with "upstream rejected the request" without compacting.
  • A quietly welcome fix: Pressing Ctrl+C to clear text typed in the prompt stopped all running background agents, and this has been fixed. I think this is a welcome fix for those who often rewrite prompts while running agents in the background.
  • In addition, many other minor bugs have been fixed, including OpenTelemetry export via proxies, self-hosted runners and cloud sessions, agent teams and scheduled tasks, Windows paths, and the VS Code extension.

Breaking Changes / Deprecations

There are no items explicitly marked as breaking changes in the CHANGELOG, but this article covers the following 3 items that affect existing usage. The before and after below are all examples constructed from the CHANGELOG descriptions.

Removal of the Read tool's "file unchanged since your last Read" stub

This is an example of using Read twice in a row on an unchanged file.

Before (up to v2.1.316):

Read file.txt → file contents
(without changing file.txt)
Read file.txt → "file unchanged since your last Read" stub

After (v2.1.317 onward):

Read file.txt → file contents
(without changing file.txt)
Read file.txt → file contents

claude -p inside a session no longer shares the session ID

This is an example of running claude -p inside a cloud or self-hosted runner session. CLAUDE_CODE_DISABLE_NESTED_SESSION_ID is described in the CHANGELOG as something to set on self-hosted runners, and its handling in cloud sessions is not described.

Before (up to v2.1.316):

Run claude -p inside a session
→ Shares that session's ID and writes to the session's transcript
→ A different conversation may be resumed on restart

After (v2.1.317 onward):

Run claude -p inside a session
→ Does not share that session's ID

To restore the previous behavior on a self-hosted runner
→ Set CLAUDE_CODE_DISABLE_NESTED_SESSION_ID=1

Effort of subagents and teammates on a different model

This is an example of running the main conversation on Opus 5.5 with effort high and launching a subagent with model: sonnet. The behavior before the change is an inference from the phrase "instead of the session's effort level" in the CHANGELOG. Of the behavior after the change, the case where Sonnet's effort is not saved is verified in "Trying it out" below.

Before (up to v2.1.316, inferred):

Subagent with model: sonnet → the session's effort (high)

After (v2.1.317 onward):

Subagent with model: sonnet → Sonnet's saved effort
If nothing is saved, that model's default
(in this environment, medium for Sonnet 5.5)

Trying out the effort of subagents on a different model

I did a similar verification in the previous update (v2.1.316), but for v2.1.317 I also carried out the following verifications along with the update.

  • Also tallied the model name (message.model) to confirm that it ran on Sonnet
  • Confirmed that model and effort were not passed in the Agent tool call
  • Ran with environment variables inherited from the current session, such as CLAUDE_EFFORT=xhigh, removed

I checked the effort of a subagent running on a model different from the main conversation, which was changed in v2.1.317, by comparing it with a subagent running on the same model as the main conversation.

Verification method

In the following commands, I put the absolute path of the verification directory in the shell variable V and use it. For this verification, I prepare a directory created under a temporary directory for the Claude Code session.

# Example: create an empty directory for verification and put its path in V
% V="$(mktemp -d)"
% mkdir -p $V/work
% cd $V/work

The verification conditions are as follows.

  • With --model opus --effort high, the main conversation is set to Opus 5.5 with effort high
  • With --agents, define two subagents: probe-same (model: inherit), which runs on the same model as the main conversation, and probe-sonnet (model: sonnet), which runs on Sonnet
  • With --tools Agent, the only available tool is Agent, and with --strict-mcp-config, no MCP servers are loaded
  • The prompt tells it not to specify the model and effort parameters of the Agent tool
  • In this environment, Sonnet's effort is not saved in the user settings' modelSettings (the user settings' effortLevel is xhigh, but the session's effort is set to high with --effort high)
  • The environment variables CLAUDE_CODE_EFFORT_LEVEL and CLAUDE_CODE_SUBAGENT_EFFORT are not set

Note that because I ran the commands from inside a Claude Code session this time, I ran the subsequent claude commands in a subshell in which the environment variables inherited from the session (CLAUDECODE, CLAUDE_CODE_CHILD_SESSION, CLAUDE_CODE_SESSION_ID, CLAUDE_EFFORT, CLAUDE_CODE_MESSAGING_SOCKET, CLAUDE_CODE_MESSAGING_TOKEN, CLAUDE_PID, CLAUDE_CODE_SESSION_ATTENDED) were unset. This step is unnecessary if you run directly from a terminal.

% AGENTS='{"probe-same":{"description":"Probe agent that runs on the main conversation model","prompt":"Reply with only: ok","model":"inherit"},"probe-sonnet":{"description":"Probe agent that runs on Sonnet","prompt":"Reply with only: ok","model":"sonnet"}}'

Subagent on the same model as the main (runA)

% claude -p --max-turns 1 --model opus --effort high --tools Agent --strict-mcp-config \
  --agents "$AGENTS" --output-format stream-json --verbose \
  "Agent ツールで probe-same サブエージェントを 1 つ起動してください。model と effort のパラメータは指定しないでください" > $V/runA.jsonl

Sonnet subagent (runB)

% claude -p --max-turns 1 --model opus --effort high --tools Agent --strict-mcp-config \
  --agents "$AGENTS" --output-format stream-json --verbose \
  "Agent ツールで probe-sonnet サブエージェントを 1 つ起動してください。model と effort のパラメータは指定しないでください" > $V/runB.jsonl

Checking the results

First, I confirmed that Claude did not pass the model and effort parameters when calling the Agent tool.

% for r in runA runB; do
    jq -c 'select(.type=="assistant") | .message.content[]? | select(.type=="tool_use" and .name=="Agent") | .input | {subagent_type, model, effort}' $V/$r.jsonl
  done
{"subagent_type":"probe-same","model":null,"effort":null}
{"subagent_type":"probe-sonnet","model":null,"effort":null}

I checked the effort in the session records (JSONL) that Claude Code saves automatically. In this environment, the main session's record was saved at ~/.claude/projects/<directory corresponding to the working directory>/<session ID>.jsonl, and the subagents' records were saved in the same place at <session ID>/subagents/agent-*.jsonl. I tally the message.model and effort values in the assistant records of each record.

% P=~/.claude/projects/<作業ディレクトリに対応するディレクトリ>
% for r in runA runB; do
    SID=$(jq -r 'select(.type=="system" and .subtype=="init") | .session_id' $V/$r.jsonl | head -1)
    echo "== $r"
    echo "main:";     jq -r 'select(.type=="assistant") | "\(.message.model) \(.effort)"' "$P/$SID.jsonl" | sort | uniq -c
    echo "subagent:"; jq -r 'select(.type=="assistant") | "\(.message.model) \(.effort)"' "$P/$SID"/subagents/agent-*.jsonl | sort | uniq -c
  done
== runA
main:
   3 claude-opus-5-5 high
subagent:
   2 claude-opus-5-5 high
== runB
main:
   3 claude-opus-5-5 high
subagent:
   1 claude-sonnet-5-5 medium

The numbers are the count of assistant records in each record that have that combination of model and effort.

  • The subagent on the same model as the main (runA) ran, according to the session record, on claude-opus-5-5 at high, the same as the main conversation.
  • The Sonnet subagent (runB) ran, according to the session record, on claude-sonnet-5-5 at medium while the main conversation stayed at high. Because this is an environment where Sonnet's effort is not saved, this matches the default for Sonnet 5.5 in the official documentation (medium).

Both runs had an exit code of 0. The stream-json result events were as follows: for each run, the first was error_max_turns, indicating that the --max-turns 1 limit was reached, and the second was success.

% for r in runA runB; do jq -c 'select(.type=="result") | {subtype, terminal_reason}' $V/$r.jsonl; done
{"subtype":"error_max_turns","terminal_reason":"max_turns"}
{"subtype":"success","terminal_reason":"completed"}
{"subtype":"error_max_turns","terminal_reason":"max_turns"}
{"subtype":"success","terminal_reason":"completed"}

What I checked this time is only the behavior in v2.1.317, and I did not compare it with older versions. I also did not check combinations with CLAUDE_CODE_SUBAGENT_EFFORT or the effort field in subagent definitions, nor the behavior of Haiku subagents and teammates.

The main stayed at Opus 5.5 high, while the Sonnet subagent ran at Sonnet 5.5's default of medium. I feel it is a welcome change that subagents now run on each model's default rather than being dragged along by the main's effort.

Conclusion

I feel v2.1.317 is a version that includes 3 behavior changes affecting existing usage: the effort of subagents on a different model, rereading with Read, and the session ID of claude -p inside a runner. It also includes changes that lean toward the safe side, such as the confirmation before sending the email address and onFailure: "block" for Agent SDK hooks.

If you use subagents on a different model or operate self-hosted runners, why not update and try it out?

References

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

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

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

https://code.claude.com/docs/en/sub-agents

https://dev.classmethod.jp/articles/20261031-cc-updates-v2-1-316/


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

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

サービス詳細を見る

Share this article

AI白書