Skip to content

Commit 5656d20

Browse files
authored
feat: add session_id option to ClaudeAgentOptions (#750)
## Summary Adds the `session_id` option to `ClaudeAgentOptions`, allowing users to specify a custom session ID (UUID) rather than having one auto-generated. This brings the Python SDK to parity with the TypeScript SDK's `sessionId` option and the CLI's `--session-id` flag. Fixes #338 ## Problem Users who want to control session IDs (e.g., for batch processing, session tracking, or integration with external systems) currently have to extract the auto-generated ID from the first `SystemMessage`: ```python session_id = None async for msg in query(prompt="..."): if hasattr(msg, "session_id"): session_id = msg.session_id # awkward extraction ... ``` The CLI supports `--session-id <uuid>` and the TypeScript SDK exposes `sessionId` in options, but the Python SDK had no equivalent. ## Fix - **`types.py`**: Add `session_id: str | None = None` to `ClaudeAgentOptions` - **`subprocess_cli.py`**: Pass `--session-id` to the CLI when `session_id` is set ```python options = ClaudeAgentOptions( session_id="550e8400-e29b-41d4-a716-446655440000", ) async for msg in query(prompt="...", options=options): # msg.session_id == "550e8400-e29b-41d4-a716-446655440000" ``` ## Verification **End-to-end with live SDK instance:** ``` Using custom session_id: f5e728c6-a604-48e2-8728-a08bde1f3c9e SystemMessage: session_id=N/A AssistantMessage: session_id=f5e728c6-a604-48e2-8728-a08bde1f3c9e AssistantMessage: session_id=f5e728c6-a604-48e2-8728-a08bde1f3c9e RateLimitEvent: session_id=f5e728c6-a604-48e2-8728-a08bde1f3c9e ResultMessage: session_id=f5e728c6-a604-48e2-8728-a08bde1f3c9e Expected session_id: f5e728c6-a604-48e2-8728-a08bde1f3c9e Actual session_id: f5e728c6-a604-48e2-8728-a08bde1f3c9e PASS: Session ID matches custom ID! ``` **Test suite:** - 404 tests pass - 2 unit tests added (`test_session_id`, `test_session_id_not_set_by_default`) - `ruff check` + `ruff format` clean - `mypy src/` clean
1 parent 278570d commit 5656d20

File tree

3 files changed

+26
-0
lines changed

3 files changed

+26
-0
lines changed

src/claude_agent_sdk/_internal/transport/subprocess_cli.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,9 @@ def _build_command(self) -> list[str]:
231231
if self._options.resume:
232232
cmd.extend(["--resume", self._options.resume])
233233

234+
if self._options.session_id:
235+
cmd.extend(["--session-id", self._options.session_id])
236+
234237
# Handle settings and sandbox: merge sandbox into settings if both are provided
235238
settings_value = self._build_settings_value()
236239
if settings_value:

src/claude_agent_sdk/types.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,6 +1088,7 @@ class ClaudeAgentOptions:
10881088
permission_mode: PermissionMode | None = None
10891089
continue_conversation: bool = False
10901090
resume: str | None = None
1091+
session_id: str | None = None
10911092
max_turns: int | None = None
10921093
max_budget_usd: float | None = None
10931094
disallowed_tools: list[str] = field(default_factory=list)

tests/test_transport.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,28 @@ def test_session_continuation(self):
268268
assert "--resume" in cmd
269269
assert "session-123" in cmd
270270

271+
def test_session_id(self):
272+
"""Test custom session ID option."""
273+
transport = SubprocessCLITransport(
274+
prompt="test",
275+
options=make_options(session_id="550e8400-e29b-41d4-a716-446655440000"),
276+
)
277+
278+
cmd = transport._build_command()
279+
assert "--session-id" in cmd
280+
idx = cmd.index("--session-id")
281+
assert cmd[idx + 1] == "550e8400-e29b-41d4-a716-446655440000"
282+
283+
def test_session_id_not_set_by_default(self):
284+
"""Test that --session-id is not passed when session_id is None."""
285+
transport = SubprocessCLITransport(
286+
prompt="test",
287+
options=make_options(),
288+
)
289+
290+
cmd = transport._build_command()
291+
assert "--session-id" not in cmd
292+
271293
def test_connect_close(self):
272294
"""Test connect and close lifecycle."""
273295

0 commit comments

Comments
 (0)