Skip to content

feat: add set_effort, set_max_thinking_tokens, and apply_flag_settings to ClaudeSDKClient#1076

Open
Magic-Man-us wants to merge 2 commits into
anthropics:mainfrom
Magic-Man-us:feat/set-effort-thinking-flag-settings
Open

feat: add set_effort, set_max_thinking_tokens, and apply_flag_settings to ClaudeSDKClient#1076
Magic-Man-us wants to merge 2 commits into
anthropics:mainfrom
Magic-Man-us:feat/set-effort-thinking-flag-settings

Conversation

@Magic-Man-us

Copy link
Copy Markdown

Summary

Closes #981.

Adds public mid-conversation setters to ClaudeSDKClient, symmetric with the existing set_model and set_permission_mode, so callers can change effort and thinking between turns in streaming mode.

Background

Issue #981 proposed new set_effort and set_thinking control subtypes. Those subtypes do not exist in the bundled CLI (verified against 2.1.195: zero occurrences of set_effort or set_thinking; the CLI exposes apply_flag_settings and set_max_thinking_tokens). This PR mirrors the actual surface of the TypeScript SDK's Query interface instead, so it works against the shipping CLI today.

What changed

New public methods on ClaudeSDKClient:

  • apply_flag_settings(settings): forwards an apply_flag_settings control request. Flag settings sit above user/project/local settings and below managed policy settings, and apply to subsequent turns.
  • set_max_thinking_tokens(max_thinking_tokens, thinking_display): forwards a set_max_thinking_tokens control request. Marked deprecated to match the TypeScript SDK; prefer the launch-time thinking option. The thinking_display argument preserves the omit vs explicit None distinction (omit keeps the session display mode, None resets to the API default).
  • set_effort(effort): convenience wrapper over apply_flag_settings({"effortLevel": effort}). effortLevel is the real flag-settings key (verified in the CLI); passing None clears the override and falls back to the launch value.

set_thinking is intentionally not added: there is no single CLI subtype matching the ThinkingConfig union, and set_max_thinking_tokens is the real mechanism.

Types:

  • Adds SDKControlSetModelRequest, SDKControlSetMaxThinkingTokensRequest, and SDKControlApplyFlagSettingsRequest to the SDKControlRequest union. set_model was previously dispatched as an untyped dict, so this also closes the parity gap the issue called out.
  • Exports ThinkingDisplay.

Tests

Adds 9 tests in tests/test_streaming_client.py covering the forwarded wire shape, the not-connected guard for each method, and the omit, explicit-null, and explicit-value cases for thinking_display.

Verification

  • python -m ruff check src/ tests/: passes
  • python -m ruff format src/ tests/ --check: passes
  • python -m mypy src/: passes
  • python -m pytest tests/: 1003 passed, 5 skipped

…s to ClaudeSDKClient

Adds public mid-conversation setters to ClaudeSDKClient, symmetric with the
existing set_model / set_permission_mode, for changing effort and thinking
between turns (streaming mode only). Resolves anthropics#981.

The control subtypes proposed in the issue (set_effort / set_thinking) do not
exist in the CLI; this mirrors the actual surface of the TypeScript SDK's Query
interface instead:

- apply_flag_settings(settings) -> apply_flag_settings control request. Effort
  is carried as the effortLevel flag-settings key.
- set_max_thinking_tokens(max_thinking_tokens, thinking_display) ->
  set_max_thinking_tokens control request. Preserves the omit-vs-explicit-None
  distinction for thinking_display via a sentinel. Marked deprecated to match
  the TS SDK; prefer the launch-time thinking option.
- set_effort(effort) -> ergonomic wrapper over apply_flag_settings({effortLevel}).

Adds typed SDKControlSetModelRequest, SDKControlSetMaxThinkingTokensRequest, and
SDKControlApplyFlagSettingsRequest to the SDKControlRequest union (set_model was
previously dispatched as an untyped dict), exports ThinkingDisplay, and covers
the new methods with forward-shape, not-connected, and display-mode tests.
Copilot AI review requested due to automatic review settings June 28, 2026 18:35
@Magic-Man-us

Copy link
Copy Markdown
Author

I am doing this to mirror parity with the TS SDK as expected.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds mid-conversation (streaming-mode) control setters to ClaudeSDKClient so callers can adjust effort/flag settings and thinking-token budget between turns, aligning the Python SDK surface with the currently shipping CLI control protocol.

Changes:

  • Add ClaudeSDKClient.set_effort(), set_max_thinking_tokens() (deprecated), and apply_flag_settings() forwarding to control requests.
  • Extend SDKControlRequest typing union with set_model, set_max_thinking_tokens, and apply_flag_settings request shapes; export ThinkingDisplay.
  • Add streaming-client tests validating wire shape, not-connected guards, and omit vs explicit-null vs explicit-value behavior for thinking_display.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/test_streaming_client.py Adds tests and a helper to locate emitted control requests for the new client setters.
src/claude_agent_sdk/types.py Introduces an omit-vs-None sentinel and adds TypedDict variants for new control request subtypes; exports ThinkingDisplay.
src/claude_agent_sdk/client.py Adds the new public streaming-mode setter methods on ClaudeSDKClient.
src/claude_agent_sdk/_internal/query.py Implements the new control request forwarders used by ClaudeSDKClient.
src/claude_agent_sdk/init.py Re-exports ThinkingDisplay from the public package surface.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/claude_agent_sdk/_internal/query.py
Comment thread src/claude_agent_sdk/client.py
- Use identity check `is not _OMIT` instead of `isinstance(_, _Omitted)`
  so only the singleton sentinel counts as omitted, not any _Omitted().
- Hide the internal _Omitted sentinel from the public
  set_max_thinking_tokens signature via @overload; callers see
  `thinking_display: ThinkingDisplay | None`.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Comment on lines +411 to +415
async def set_max_thinking_tokens(
self,
max_thinking_tokens: int | None,
thinking_display: ThinkingDisplay | None | _Omitted = _OMIT,
) -> None:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] : Add set_effort and set_thinking to ClaudeSDKClient

2 participants