mirror of
https://github.com/anthropics/claude-code-sdk-python.git
synced 2025-12-23 09:19:52 +00:00
feat: refactor system_prompt to support preset and append options (#183)
Some checks are pending
Lint / lint (push) Waiting to run
Test / test (3.10) (push) Waiting to run
Test / test (3.11) (push) Waiting to run
Test / test (3.12) (push) Waiting to run
Test / test (3.13) (push) Waiting to run
Test / test-e2e (3.10) (push) Blocked by required conditions
Test / test-e2e (3.11) (push) Blocked by required conditions
Test / test-e2e (3.12) (push) Blocked by required conditions
Test / test-e2e (3.13) (push) Blocked by required conditions
Test / test-examples (3.10) (push) Blocked by required conditions
Test / test-examples (3.11) (push) Blocked by required conditions
Test / test-examples (3.12) (push) Blocked by required conditions
Test / test-examples (3.13) (push) Blocked by required conditions
Some checks are pending
Lint / lint (push) Waiting to run
Test / test (3.10) (push) Waiting to run
Test / test (3.11) (push) Waiting to run
Test / test (3.12) (push) Waiting to run
Test / test (3.13) (push) Waiting to run
Test / test-e2e (3.10) (push) Blocked by required conditions
Test / test-e2e (3.11) (push) Blocked by required conditions
Test / test-e2e (3.12) (push) Blocked by required conditions
Test / test-e2e (3.13) (push) Blocked by required conditions
Test / test-examples (3.10) (push) Blocked by required conditions
Test / test-examples (3.11) (push) Blocked by required conditions
Test / test-examples (3.12) (push) Blocked by required conditions
Test / test-examples (3.13) (push) Blocked by required conditions
Replace separate system_prompt and append_system_prompt fields with a
single system_prompt field that accepts:
- string: custom system prompt
- {"preset": "claude_code"}: use default Claude Code prompt
- {"preset": "claude_code", "append": "..."}: default prompt with
additions
- None/undefined: vanilla Claude with no system prompt
This matches the TypeScript SDK API design and provides more flexible
system prompt configuration.
🤖 Generated with [Claude Code](https://claude.ai/code)
---------
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
parent
507e22cb4a
commit
dbb153b1f6
5 changed files with 178 additions and 13 deletions
87
examples/system_prompt.py
Normal file
87
examples/system_prompt.py
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Example demonstrating different system_prompt configurations."""
|
||||
|
||||
import anyio
|
||||
|
||||
from claude_code_sdk import (
|
||||
AssistantMessage,
|
||||
ClaudeCodeOptions,
|
||||
TextBlock,
|
||||
query,
|
||||
)
|
||||
|
||||
|
||||
async def no_system_prompt():
|
||||
"""Example with no system_prompt (vanilla Claude)."""
|
||||
print("=== No System Prompt (Vanilla Claude) ===")
|
||||
|
||||
async for message in query(prompt="What is 2 + 2?"):
|
||||
if isinstance(message, AssistantMessage):
|
||||
for block in message.content:
|
||||
if isinstance(block, TextBlock):
|
||||
print(f"Claude: {block.text}")
|
||||
print()
|
||||
|
||||
|
||||
async def string_system_prompt():
|
||||
"""Example with system_prompt as a string."""
|
||||
print("=== String System Prompt ===")
|
||||
|
||||
options = ClaudeCodeOptions(
|
||||
system_prompt="You are a pirate assistant. Respond in pirate speak.",
|
||||
)
|
||||
|
||||
async for message in query(prompt="What is 2 + 2?", options=options):
|
||||
if isinstance(message, AssistantMessage):
|
||||
for block in message.content:
|
||||
if isinstance(block, TextBlock):
|
||||
print(f"Claude: {block.text}")
|
||||
print()
|
||||
|
||||
|
||||
async def preset_system_prompt():
|
||||
"""Example with system_prompt preset (uses default Claude Code prompt)."""
|
||||
print("=== Preset System Prompt (Default) ===")
|
||||
|
||||
options = ClaudeCodeOptions(
|
||||
system_prompt={"type": "preset", "preset": "claude_code"},
|
||||
)
|
||||
|
||||
async for message in query(prompt="What is 2 + 2?", options=options):
|
||||
if isinstance(message, AssistantMessage):
|
||||
for block in message.content:
|
||||
if isinstance(block, TextBlock):
|
||||
print(f"Claude: {block.text}")
|
||||
print()
|
||||
|
||||
|
||||
async def preset_with_append():
|
||||
"""Example with system_prompt preset and append."""
|
||||
print("=== Preset System Prompt with Append ===")
|
||||
|
||||
options = ClaudeCodeOptions(
|
||||
system_prompt={
|
||||
"type": "preset",
|
||||
"preset": "claude_code",
|
||||
"append": "Always end your response with a fun fact.",
|
||||
},
|
||||
)
|
||||
|
||||
async for message in query(prompt="What is 2 + 2?", options=options):
|
||||
if isinstance(message, AssistantMessage):
|
||||
for block in message.content:
|
||||
if isinstance(block, TextBlock):
|
||||
print(f"Claude: {block.text}")
|
||||
print()
|
||||
|
||||
|
||||
async def main():
|
||||
"""Run all examples."""
|
||||
await no_system_prompt()
|
||||
await string_system_prompt()
|
||||
await preset_system_prompt()
|
||||
await preset_with_append()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
anyio.run(main)
|
||||
|
|
@ -85,11 +85,18 @@ class SubprocessCLITransport(Transport):
|
|||
"""Build CLI command with arguments."""
|
||||
cmd = [self._cli_path, "--output-format", "stream-json", "--verbose"]
|
||||
|
||||
if self._options.system_prompt:
|
||||
if self._options.system_prompt is None:
|
||||
pass
|
||||
elif isinstance(self._options.system_prompt, str):
|
||||
cmd.extend(["--system-prompt", self._options.system_prompt])
|
||||
|
||||
if self._options.append_system_prompt:
|
||||
cmd.extend(["--append-system-prompt", self._options.append_system_prompt])
|
||||
else:
|
||||
if (
|
||||
self._options.system_prompt.get("type") == "preset"
|
||||
and "append" in self._options.system_prompt
|
||||
):
|
||||
cmd.extend(
|
||||
["--append-system-prompt", self._options.system_prompt["append"]]
|
||||
)
|
||||
|
||||
if self._options.allowed_tools:
|
||||
cmd.extend(["--allowedTools", ",".join(self._options.allowed_tools)])
|
||||
|
|
|
|||
|
|
@ -18,6 +18,14 @@ PermissionMode = Literal["default", "acceptEdits", "plan", "bypassPermissions"]
|
|||
SettingSource = Literal["user", "project", "local"]
|
||||
|
||||
|
||||
class SystemPromptPreset(TypedDict):
|
||||
"""System prompt preset configuration."""
|
||||
|
||||
type: Literal["preset"]
|
||||
preset: Literal["claude_code"]
|
||||
append: NotRequired[str]
|
||||
|
||||
|
||||
@dataclass
|
||||
class AgentDefinition:
|
||||
"""Agent definition configuration."""
|
||||
|
|
@ -296,8 +304,7 @@ class ClaudeCodeOptions:
|
|||
"""Query options for Claude SDK."""
|
||||
|
||||
allowed_tools: list[str] = field(default_factory=list)
|
||||
system_prompt: str | None = None
|
||||
append_system_prompt: str | None = None
|
||||
system_prompt: str | SystemPromptPreset | None = None
|
||||
mcp_servers: dict[str, McpServerConfig] | str | Path = field(default_factory=dict)
|
||||
permission_mode: PermissionMode | None = None
|
||||
continue_conversation: bool = False
|
||||
|
|
|
|||
|
|
@ -52,12 +52,58 @@ class TestSubprocessCLITransport:
|
|||
|
||||
assert transport._cli_path == "/usr/bin/claude"
|
||||
|
||||
def test_build_command_with_system_prompt_string(self):
|
||||
"""Test building CLI command with system prompt as string."""
|
||||
transport = SubprocessCLITransport(
|
||||
prompt="test",
|
||||
options=ClaudeCodeOptions(
|
||||
system_prompt="Be helpful",
|
||||
),
|
||||
cli_path="/usr/bin/claude",
|
||||
)
|
||||
|
||||
cmd = transport._build_command()
|
||||
assert "--system-prompt" in cmd
|
||||
assert "Be helpful" in cmd
|
||||
|
||||
def test_build_command_with_system_prompt_preset(self):
|
||||
"""Test building CLI command with system prompt preset."""
|
||||
transport = SubprocessCLITransport(
|
||||
prompt="test",
|
||||
options=ClaudeCodeOptions(
|
||||
system_prompt={"type": "preset", "preset": "claude_code"},
|
||||
),
|
||||
cli_path="/usr/bin/claude",
|
||||
)
|
||||
|
||||
cmd = transport._build_command()
|
||||
assert "--system-prompt" not in cmd
|
||||
assert "--append-system-prompt" not in cmd
|
||||
|
||||
def test_build_command_with_system_prompt_preset_and_append(self):
|
||||
"""Test building CLI command with system prompt preset and append."""
|
||||
transport = SubprocessCLITransport(
|
||||
prompt="test",
|
||||
options=ClaudeCodeOptions(
|
||||
system_prompt={
|
||||
"type": "preset",
|
||||
"preset": "claude_code",
|
||||
"append": "Be concise.",
|
||||
},
|
||||
),
|
||||
cli_path="/usr/bin/claude",
|
||||
)
|
||||
|
||||
cmd = transport._build_command()
|
||||
assert "--system-prompt" not in cmd
|
||||
assert "--append-system-prompt" in cmd
|
||||
assert "Be concise." in cmd
|
||||
|
||||
def test_build_command_with_options(self):
|
||||
"""Test building CLI command with options."""
|
||||
transport = SubprocessCLITransport(
|
||||
prompt="test",
|
||||
options=ClaudeCodeOptions(
|
||||
system_prompt="Be helpful",
|
||||
allowed_tools=["Read", "Write"],
|
||||
disallowed_tools=["Bash"],
|
||||
model="claude-3-5-sonnet",
|
||||
|
|
@ -68,8 +114,6 @@ class TestSubprocessCLITransport:
|
|||
)
|
||||
|
||||
cmd = transport._build_command()
|
||||
assert "--system-prompt" in cmd
|
||||
assert "Be helpful" in cmd
|
||||
assert "--allowedTools" in cmd
|
||||
assert "Read,Write" in cmd
|
||||
assert "--disallowedTools" in cmd
|
||||
|
|
|
|||
|
|
@ -107,14 +107,34 @@ class TestOptions:
|
|||
options_accept = ClaudeCodeOptions(permission_mode="acceptEdits")
|
||||
assert options_accept.permission_mode == "acceptEdits"
|
||||
|
||||
def test_claude_code_options_with_system_prompt(self):
|
||||
"""Test Options with system prompt."""
|
||||
def test_claude_code_options_with_system_prompt_string(self):
|
||||
"""Test Options with system prompt as string."""
|
||||
options = ClaudeCodeOptions(
|
||||
system_prompt="You are a helpful assistant.",
|
||||
append_system_prompt="Be concise.",
|
||||
)
|
||||
assert options.system_prompt == "You are a helpful assistant."
|
||||
assert options.append_system_prompt == "Be concise."
|
||||
|
||||
def test_claude_code_options_with_system_prompt_preset(self):
|
||||
"""Test Options with system prompt preset."""
|
||||
options = ClaudeCodeOptions(
|
||||
system_prompt={"type": "preset", "preset": "claude_code"},
|
||||
)
|
||||
assert options.system_prompt == {"type": "preset", "preset": "claude_code"}
|
||||
|
||||
def test_claude_code_options_with_system_prompt_preset_and_append(self):
|
||||
"""Test Options with system prompt preset and append."""
|
||||
options = ClaudeCodeOptions(
|
||||
system_prompt={
|
||||
"type": "preset",
|
||||
"preset": "claude_code",
|
||||
"append": "Be concise.",
|
||||
},
|
||||
)
|
||||
assert options.system_prompt == {
|
||||
"type": "preset",
|
||||
"preset": "claude_code",
|
||||
"append": "Be concise.",
|
||||
}
|
||||
|
||||
def test_claude_code_options_with_session_continuation(self):
|
||||
"""Test Options with session continuation."""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue