Problem
ClaudeSDKClient exposes set_model and set_permission_mode as public, mid-conversation setters backed by control-protocol subtypes. effort and thinking are first-class fields on ClaudeAgentOptions , but the Python SDK exposes no equivalent setter - both are launch-only, mapped to --effort / --thinking on the CLI command line.
The TypeScript SDK exposes applyFlagSettings on its Query interface as a partial workaround. The Python SDK does not surface it at all.
There is no public mid-conversation knob in the Python SDK for either effort or thinking.
Reproduction
- SDK:
claude-agent-sdk 0.1.60
- Bundled CLI:
cli.js 2.1.111
- Python 3.11.13, Linux
import asyncio
from claude_agent_sdk import ClaudeAgentOptions, ClaudeSDKClient
async def main():
options = ClaudeAgentOptions(model="claude-opus-4-7", effort="low")
async with ClaudeSDKClient(options=options) as client:
await client.query("Quick exploratory question.")
async for _ in client.receive_response():
pass
# Want to bump effort before the next turn — no public method exists.
# client.set_effort("max") # AttributeError
# client.set_thinking({"type": "adaptive"}) # AttributeError
await client.query("Now give a deep planning answer.")
# ...still running at effort=low.
asyncio.run(main())
The only mid-conversation setters on ClaudeSDKClient are:
await client.set_model(...)
await client.set_permission_mode(...)
Workaround
Send the raw control request through the private Query._send_control_request:
await client._query._send_control_request({
"subtype": "apply_flag_settings",
"settings": {"effortLevel": "max"},
})
This is not a clean substitute for dedicated setters:
_send_control_request is private. apply_flag_settings has no TypedDict in SDKControlRequest.
{ effortLevel: "max" } updates the in-memory state.effortValue but is stripped before persistence — flagSettings source serialises as {}.
CLI versions inspected for a dedicated subtype: cli.js 2.1.19 → 2.1.111 and native binaries 2.1.114 → 2.1.143. No set_effort or set_thinking subtype exists in any of them.
What we'd like
-
Confirm whether there's a public API we missed for changing effort or thinking mid-conversation. We checked the methods on ClaudeSDKClient (set_model, set_permission_mode, set_effort?, set_thinking?) and the public exports, and didn't find one.
-
If not, please add public client.set_effort() and client.set_thinking() methods, symmetric with set_model:
class ClaudeSDKClient:
async def set_effort(self, effort: EffortLevel | None) -> None: ...
async def set_thinking(self, thinking: ThinkingConfig | None) -> None: ...
EffortLevel = Literal["low", "medium", "high", "xhigh", "max"] and ThinkingConfig are already in types.py. Semantics matching set_model: streaming-mode only; effective on next turn; None resets to the value supplied at launch.
-
Backed by new control-protocol subtypes on @anthropic-ai/claude-code:
Add corresponding TypedDict variants (SDKControlSetEffortRequest, SDKControlSetThinkingRequest) to the SDKControlRequest union in types.py. Also add the missing SDKControlSetModelRequest for parity — set_model is currently dispatched as an untyped dict.
-
Once the CLI subtypes land, the Python SDK PR is a forwarder identical in shape to set_model:
async def set_effort(self, effort: EffortLevel | None) -> None:
await self._send_control_request({"subtype": "set_effort", "effort": effort})
async def set_thinking(self, thinking: ThinkingConfig | None) -> None:
await self._send_control_request({"subtype": "set_thinking", "thinking": thinking})
Problem
ClaudeSDKClientexposesset_modelandset_permission_modeas public, mid-conversation setters backed by control-protocol subtypes.effortandthinkingare first-class fields onClaudeAgentOptions, but the Python SDK exposes no equivalent setter - both are launch-only, mapped to--effort/--thinkingon the CLI command line.The TypeScript SDK exposes
applyFlagSettingson itsQueryinterface as a partial workaround. The Python SDK does not surface it at all.There is no public mid-conversation knob in the Python SDK for either effort or thinking.
Reproduction
claude-agent-sdk0.1.60cli.js2.1.111The only mid-conversation setters on
ClaudeSDKClientare:Workaround
Send the raw control request through the private
Query._send_control_request:This is not a clean substitute for dedicated setters:
_send_control_requestis private.apply_flag_settingshas noTypedDictinSDKControlRequest.{ effortLevel: "max" }updates the in-memorystate.effortValuebut is stripped before persistence —flagSettingssource serialises as{}.CLI versions inspected for a dedicated subtype: cli.js 2.1.19 → 2.1.111 and native binaries 2.1.114 → 2.1.143. No
set_effortorset_thinkingsubtype exists in any of them.What we'd like
Confirm whether there's a public API we missed for changing effort or thinking mid-conversation. We checked the methods on
ClaudeSDKClient(set_model,set_permission_mode,set_effort?,set_thinking?) and the public exports, and didn't find one.If not, please add public
client.set_effort()andclient.set_thinking()methods, symmetric withset_model:EffortLevel = Literal["low", "medium", "high", "xhigh", "max"]andThinkingConfigare already intypes.py. Semantics matchingset_model: streaming-mode only; effective on next turn;Noneresets to the value supplied at launch.Backed by new control-protocol subtypes on
@anthropic-ai/claude-code:{ "type": "control_request", "request_id": "...", "request": { "subtype": "set_effort", "effort": "low" | "medium" | "high" | "xhigh" | "max" | null } } { "type": "control_request", "request_id": "...", "request": { "subtype": "set_thinking", "thinking": { "type": "adaptive", "display": "summarized" | "omitted" } | { "type": "enabled", "budget_tokens": number, "display": "summarized" | "omitted" } | { "type": "disabled" } | null } }Add corresponding
TypedDictvariants (SDKControlSetEffortRequest,SDKControlSetThinkingRequest) to theSDKControlRequestunion intypes.py. Also add the missingSDKControlSetModelRequestfor parity —set_modelis currently dispatched as an untyped dict.Once the CLI subtypes land, the Python SDK PR is a forwarder identical in shape to
set_model: