Skip to content

Commit 5fb0cc1

Browse files
Python: feat(claude): add plugins, setting_sources, thinking, and effort options to ClaudeAgentOptions (#4425)
* feat(claude): add plugins, setting_sources, thinking, and effort options Add four Claude Agent SDK options to ClaudeAgentOptions that are clean passthroughs with no abstraction conflicts: - plugins: load Claude Code plugins programmatically via SdkPluginConfig - setting_sources: control which .claude settings files are loaded - thinking: modern extended thinking config (adaptive/enabled/disabled) - effort: control thinking depth (low/medium/high/max) * feat(claude): remove max_thinking_tokens, add plugins/setting_sources/thinking/effort Remove the deprecated max_thinking_tokens field from ClaudeAgentOptions in favor of the new thinking field (ThinkingConfig). Add four Claude Agent SDK options as clean passthroughs: - plugins: load Claude Code plugins via SdkPluginConfig - setting_sources: control which .claude settings files are loaded - thinking: extended thinking config (adaptive/enabled/disabled) - effort: thinking depth control (low/medium/high/max)
1 parent 965a1ec commit 5fb0cc1

1 file changed

Lines changed: 63 additions & 16 deletions

File tree

  • python/packages/claude/agent_framework_claude

python/packages/claude/agent_framework_claude/_agent.py

Lines changed: 63 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,10 @@
5858
PermissionMode,
5959
SandboxSettings,
6060
SdkBeta,
61+
SdkPluginConfig,
62+
SettingSource,
6163
)
64+
from claude_agent_sdk.types import ThinkingConfig
6265

6366

6467
logger = logging.getLogger("agent_framework.claude")
@@ -118,9 +121,6 @@ class ClaudeAgentOptions(TypedDict, total=False):
118121
fallback_model: str
119122
"""Fallback model if primary fails."""
120123

121-
max_thinking_tokens: int
122-
"""Maximum tokens for thinking blocks."""
123-
124124
allowed_tools: list[str]
125125
"""Allowlist of tools. If set, Claude can ONLY use tools in this list."""
126126

@@ -163,6 +163,18 @@ class ClaudeAgentOptions(TypedDict, total=False):
163163
betas: list[SdkBeta]
164164
"""Beta features to enable."""
165165

166+
plugins: list[SdkPluginConfig]
167+
"""Plugin configurations for custom commands and capabilities."""
168+
169+
setting_sources: list[SettingSource]
170+
"""Which Claude settings files to load ("user", "project", "local")."""
171+
172+
thinking: ThinkingConfig
173+
"""Extended thinking configuration (adaptive, enabled, or disabled)."""
174+
175+
effort: Literal["low", "medium", "high", "max"]
176+
"""Effort level for thinking depth."""
177+
166178

167179
OptionsT = TypeVar(
168180
"OptionsT",
@@ -213,7 +225,11 @@ def __init__(
213225
description: str | None = None,
214226
context_providers: Sequence[BaseContextProvider] | None = None,
215227
middleware: Sequence[AgentMiddlewareTypes] | None = None,
216-
tools: ToolTypes | Callable[..., Any] | str | Sequence[ToolTypes | Callable[..., Any] | str] | None = None,
228+
tools: ToolTypes
229+
| Callable[..., Any]
230+
| str
231+
| Sequence[ToolTypes | Callable[..., Any] | str]
232+
| None = None,
217233
default_options: OptionsT | MutableMapping[str, Any] | None = None,
218234
env_file_path: str | None = None,
219235
env_file_encoding: str | None = None,
@@ -289,7 +305,11 @@ def __init__(
289305

290306
def _normalize_tools(
291307
self,
292-
tools: ToolTypes | Callable[..., Any] | str | Sequence[ToolTypes | Callable[..., Any] | str] | None,
308+
tools: ToolTypes
309+
| Callable[..., Any]
310+
| str
311+
| Sequence[ToolTypes | Callable[..., Any] | str]
312+
| None,
293313
) -> None:
294314
"""Separate built-in tools (strings) from custom tools.
295315
@@ -358,7 +378,9 @@ async def _ensure_session(self, session_id: str | None = None) -> None:
358378
session_id: The session ID to use, or None for a new session.
359379
"""
360380
needs_new_client = (
361-
not self._started or self._client is None or (session_id and session_id != self._current_session_id)
381+
not self._started
382+
or self._client is None
383+
or (session_id and session_id != self._current_session_id)
362384
)
363385

364386
if needs_new_client:
@@ -381,7 +403,9 @@ async def _ensure_session(self, session_id: str | None = None) -> None:
381403
self._client = None
382404
raise AgentException(f"Failed to start Claude SDK client: {ex}") from ex
383405

384-
def _prepare_client_options(self, resume_session_id: str | None = None) -> SDKOptions:
406+
def _prepare_client_options(
407+
self, resume_session_id: str | None = None
408+
) -> SDKOptions:
385409
"""Prepare SDK options for client initialization.
386410
387411
Args:
@@ -421,7 +445,9 @@ def _prepare_client_options(self, resume_session_id: str | None = None) -> SDKOp
421445

422446
# Prepare custom tools (FunctionTool instances)
423447
custom_tools_server, custom_tool_names = (
424-
self._prepare_tools(self._custom_tools) if self._custom_tools else (None, [])
448+
self._prepare_tools(self._custom_tools)
449+
if self._custom_tools
450+
else (None, [])
425451
)
426452

427453
# MCP servers - merge user-provided servers with custom tools server
@@ -468,9 +494,13 @@ def _prepare_tools(
468494
if not sdk_tools:
469495
return None, []
470496

471-
return create_sdk_mcp_server(name=TOOLS_MCP_SERVER_NAME, tools=sdk_tools), tool_names
497+
return create_sdk_mcp_server(
498+
name=TOOLS_MCP_SERVER_NAME, tools=sdk_tools
499+
), tool_names
472500

473-
def _function_tool_to_sdk_mcp_tool(self, func_tool: FunctionTool) -> SdkMcpTool[Any]:
501+
def _function_tool_to_sdk_mcp_tool(
502+
self, func_tool: FunctionTool
503+
) -> SdkMcpTool[Any]:
474504
"""Convert a FunctionTool to an SDK MCP tool.
475505
476506
Args:
@@ -493,7 +523,9 @@ async def handler(args: dict[str, Any]) -> dict[str, Any]:
493523
return {"content": [{"type": "text", "text": f"Error: {e}"}]}
494524

495525
# Get JSON schema from pydantic model
496-
schema: dict[str, Any] = func_tool.input_model.model_json_schema() if func_tool.input_model else {}
526+
schema: dict[str, Any] = (
527+
func_tool.input_model.model_json_schema() if func_tool.input_model else {}
528+
)
497529
input_schema: dict[str, Any] = {
498530
"type": "object",
499531
"properties": schema.get("properties", {}),
@@ -554,7 +586,9 @@ def default_options(self) -> dict[str, Any]:
554586
opts["instructions"] = system_prompt
555587
return opts
556588

557-
def _finalize_response(self, updates: Sequence[AgentResponseUpdate]) -> AgentResponse[Any]:
589+
def _finalize_response(
590+
self, updates: Sequence[AgentResponseUpdate]
591+
) -> AgentResponse[Any]:
558592
"""Build AgentResponse and propagate structured_output as value.
559593
560594
Args:
@@ -593,7 +627,10 @@ def run(
593627
stream: bool = False,
594628
session: AgentSession | None = None,
595629
**kwargs: Any,
596-
) -> Awaitable[AgentResponse[Any]] | ResponseStream[AgentResponseUpdate, AgentResponse[Any]]:
630+
) -> (
631+
Awaitable[AgentResponse[Any]]
632+
| ResponseStream[AgentResponseUpdate, AgentResponse[Any]]
633+
):
597634
"""Run the agent with the given messages.
598635
599636
Args:
@@ -659,15 +696,23 @@ async def _get_stream(
659696
if text:
660697
yield AgentResponseUpdate(
661698
role="assistant",
662-
contents=[Content.from_text(text=text, raw_representation=message)],
699+
contents=[
700+
Content.from_text(
701+
text=text, raw_representation=message
702+
)
703+
],
663704
raw_representation=message,
664705
)
665706
elif delta_type == "thinking_delta":
666707
thinking = delta.get("thinking", "")
667708
if thinking:
668709
yield AgentResponseUpdate(
669710
role="assistant",
670-
contents=[Content.from_text_reasoning(text=thinking, raw_representation=message)],
711+
contents=[
712+
Content.from_text_reasoning(
713+
text=thinking, raw_representation=message
714+
)
715+
],
671716
raw_representation=message,
672717
)
673718
elif isinstance(message, AssistantMessage):
@@ -684,7 +729,9 @@ async def _get_stream(
684729
"server_error": "Claude API server error",
685730
"unknown": "Unknown error from Claude API",
686731
}
687-
error_msg = error_messages.get(message.error, f"Claude API error: {message.error}")
732+
error_msg = error_messages.get(
733+
message.error, f"Claude API error: {message.error}"
734+
)
688735
# Extract any error details from content blocks
689736
if message.content:
690737
for block in message.content:

0 commit comments

Comments
 (0)