anthropics / anthropics/claude-agent-sdk-python

[FEATURE] : Add set_effort and set_thinking to ClaudeSDKClient

Abierto
#981 0 comentarios 0 reacciones 0 asignados Ver en GitHub
enhancement
Lenguaje dominante
Python
Estrellas
8.1k
Forks
1.3k
Merge medio
2 d 31 min
PR fusionados (30 d)
1

Descripción

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

Guía de contribución

No hay ninguna guía de contribución indexada para este repositorio

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.