anthropics / anthropics/claude-agent-sdk-python

[FEATURE] : Add set_effort and set_thinking to ClaudeSDKClient

Ouverte
#981 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub
enhancement
Langage dominant
Python
Étoiles
8.1k
Forks
1.3k
Merge moyen
2 j 31 min
PR mergées (30 j)
1

Description

## 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

```python
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:

```python
await client.set_model(...)
await client.set_permission_mode(...)
```

## Workaround

Send the raw control request through the private `Query._send_control_request`:

```python
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

1. 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.

2. If not, please add public `client.set_effort()` and `client.set_thinking()` methods, symmetric with `set_model`:

```python
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.

3. Backed by new control-protocol subtypes on `@anthropic-ai/claude-code`:

```jsonc
{ "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 `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.

4. Once the CLI subtypes land, the Python SDK PR is a forwarder identical in shape to `set_model`:

```python
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})
```

Guide de contribution

Aucun guide de contribution indexé pour ce dépôt

Évaluation

Cette issue n'a pas encore été évaluée.

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.