Files
2025-11-29 18:00:18 +08:00

248 lines
7.8 KiB
Markdown

# Session Management
> Understanding how the Claude Agent SDK handles sessions and session resumption
## Session Management
The Claude Agent SDK provides session management capabilities for handling conversation state and resumption. Sessions allow you to continue conversations across multiple interactions while maintaining full context.
## How Sessions Work
When you start a new query, the SDK automatically creates a session and returns a session ID in the initial system message. You can capture this ID to resume the session later.
### Getting the Session ID
options: { options: {
model: "claude-sonnet-4-5"
}
})
for await (const message of response) {
// The first message is a system init message with the session ID
```python
if (message.type === 'system' && message.subtype === 'init') { if (message.type === 'system' && message.subtype === 'init') {
sessionId = message.session_id
console.log(`Session started with ID: ${sessionId}`)
// You can save this ID for later resumption
}
```
// Process other messages... // Process other messages...
console.log(message)
}
// Later, you can use the saved sessionId to resume
if (sessionId) {
const resumedResponse = query({
```python
prompt: "Continue where we left off",
options: {
resume: sessionId
}
})
}
```
```python Python theme={null}
from claude_agent_sdk import query, ClaudeAgentOptions
session_id = None
async for message in query(
prompt="Help me build a web application",
```
```python
options=ClaudeAgentOptions( options=ClaudeAgentOptions(
model="claude-sonnet-4-5"
)
):
## The first message is a system init message with the session ID
```
```python
if hasattr(message, 'subtype') and message.subtype == 'init': if hasattr(message, 'subtype') and message.subtype == 'init':
session_id = message.data.get('session_id')
print(f"Session started with ID: {session_id}")
# You can save this ID for later resumption
```
## Process other messages... # Process other messages
print(message)
## Later, you can use the saved session_id to resume
if session_id:
async for message in query(
```python
prompt="Continue where we left off", prompt="Continue where we left off",
options=ClaudeAgentOptions(
resume=session_id
)
):
print(message)
```
## Resuming Sessions
The SDK supports resuming sessions from previous conversation states, enabling continuous development workflows. Use the `resume` option with a session ID to continue a previous conversation.
options: { options: {
resume: "session-xyz", // Session ID from previous conversation
model: "claude-sonnet-4-5",
allowedTools: ["Read", "Edit", "Write", "Glob", "Grep", "Bash"]
}
})
// The conversation continues with full context from the previous session
for await (const message of response) {
console.log(message)
}
```
```python Python theme={null}
from claude_agent_sdk import query, ClaudeAgentOptions
## Resume a previous session using its ID
async for message in query(
prompt="Continue implementing the authentication system from where we left off",
```
```python
options=ClaudeAgentOptions( options=ClaudeAgentOptions(
resume="session-xyz", # Session ID from previous conversation
model="claude-sonnet-4-5",
allowed_tools=["Read", "Edit", "Write", "Glob", "Grep", "Bash"]
)
):
print(message)
## The conversation continues with full context from the previous session
```
The SDK automatically handles loading the conversation history and context when you resume a session, allowing Claude to continue exactly where it left off.
## Forking Sessions
When resuming a session, you can choose to either continue the original session or fork it into a new branch. By default, resuming continues the original session. Use the `forkSession` option (TypeScript) or `fork_session` option (Python) to create a new session ID that starts from the resumed state.
### When to Fork a Session
Forking is useful when you want to:
* Explore different approaches from the same starting point
* Create multiple conversation branches without modifying the original
* Test changes without affecting the original session history
* Maintain separate conversation paths for different experiments
### Forking vs Continuing
| Behavior | `forkSession: false` (default) | `forkSession: true` |
| -------------------- | ------------------------------ | ------------------------------------ |
| **Session ID** | Same as original | New session ID generated |
| **History** | Appends to original session | Creates new branch from resume point |
| **Original Session** | Modified | Preserved unchanged |
| **Use Case** | Continue linear conversation | Branch to explore alternatives |
### Example: Forking a Session
options: { model: "claude-sonnet-4-5" } options: { model: "claude-sonnet-4-5" }
})
for await (const message of response) {
if (message.type === 'system' && message.subtype === 'init') {
```python
sessionId = message.session_id sessionId = message.session_id
console.log(`Original session: ${sessionId}`)
}
// Fork the session to try a different approach
const forkedResponse = query({
prompt: "Now let's redesign this as a GraphQL API instead",
```python
options: { options: {
resume: sessionId,
forkSession: true, // Creates a new session ID
model: "claude-sonnet-4-5"
}
})
for await (const message of forkedResponse) {
if (message.type === 'system' && message.subtype === 'init') {
```python
console.log(`Forked session: ${message.session_id}`) console.log(`Forked session: ${message.session_id}`)
// This will be a different session ID
}
// The original session remains unchanged and can still be resumed
const originalContinued = query({
prompt: "Add authentication to the REST API",
```python
options: { options: {
resume: sessionId,
forkSession: false, // Continue original session (default)
model: "claude-sonnet-4-5"
}
})
```
```python Python theme={null}
from claude_agent_sdk import query, ClaudeAgentOptions
## First, capture the session ID
session_id = None
async for message in query(
prompt="Help me design a REST API",
```python
options=ClaudeAgentOptions(model="claude-sonnet-4-5") options=ClaudeAgentOptions(model="claude-sonnet-4-5")
):
if hasattr(message, 'subtype') and message.subtype == 'init':
```python
session_id = message.data.get('session_id') session_id = message.data.get('session_id')
print(f"Original session: {session_id}")
## Fork the session to try a different approach
async for message in query(
prompt="Now let's redesign this as a GraphQL API instead",
```python
options=ClaudeAgentOptions( options=ClaudeAgentOptions(
resume=session_id,
fork_session=True, # Creates a new session ID
model="claude-sonnet-4-5"
)
):
if hasattr(message, 'subtype') and message.subtype == 'init':
```python
forked_id = message.data.get('session_id') forked_id = message.data.get('session_id')
print(f"Forked session: {forked_id}")
## This will be a different session ID
## The original session remains unchanged and can still be resumed
async for message in query(
prompt="Add authentication to the REST API",
```python
options=ClaudeAgentOptions( options=ClaudeAgentOptions(
resume=session_id,
fork_session=False, # Continue original session (default)
model="claude-sonnet-4-5"
)
):
print(message)
```