anthropics / anthropics/claude-agent-sdk-python

[Feature Request] Seed externally-persisted conversation history into a fresh ClaudeSDKClient as role-based messages

Đang mở
#848 2 bình luận 0 reaction 0 người được giao Xem trên GitHub
Ngôn ngữ chính
Python
Star
8.1k
Fork
1.3k
Merge trung bình
2 ngày 31 phút
Pull request đã merge (30 ngày)
1

Mô tả

## Summary

When building an agent on top of an externally-managed conversation store (e.g. AWS Bedrock AgentCore Memory, a database-backed chat app, Redis, etc.), there's no supported way to seed prior turns into a fresh `ClaudeSDKClient` session as role-based messages. The only options today are disk-backed `.jsonl` session files or stuffing history into `system_prompt` as text — both with real drawbacks.

## Use case

We're running `ClaudeSDKClient` inside a Bedrock AgentCore runtime (stateless per-invocation container). Conversation history is the source-of-truth in AgentCore Memory (managed service). On each new user turn we want to:

1. Load prior turns from AgentCore Memory
2. Construct a new `ClaudeSDKClient` with that history seeded as proper user/assistant (and ideally tool_use/tool_result) turns
3. Call `client.query(new_user_message)` and stream the response

The SDK handles everything after step 2 beautifully. It's only the seeding that has no clean path.

## Current state

SDK 0.1.56:

- `ClaudeAgentOptions.resume: str | None` exists, but it reads a local `.jsonl` from `~/.claude/projects//.jsonl`. Cross-host / ephemeral-container hostile.
- `ClaudeAgentOptions.continue_conversation: bool` — same disk-backed constraint.
- `ClaudeSDKClient.query(prompt: str | AsyncIterable[dict[str, Any]])` accepts a dict iterable, but [the docs](https://code.claude.com/docs/en/agent-sdk/python) frame this as streaming the _current_ interaction, not seeding prior turns. Unclear whether feeding historical role-based dicts would populate session context or just be re-interpreted.
- `ClaudeAgentOptions.system_prompt` is typed as `str | SystemPromptPreset | SystemPromptFile | None` — no list-of-content-blocks form, so can't even add `cache_control` breakpoints around a stuffed history block.

## Workarounds we've considered

1. **Stuff history into `system_prompt` as text** (e.g. `**USER**: ... **ASSISTANT**: ...`). This is what [Anthropic's own sessions docs](https://code.claude.com/docs/en/agent-sdk/sessions#resume-across-hosts) recommend ("capture the results you need… and pass them into a fresh session's prompt"). Drawbacks:
- Prompt cache invalidates every turn because system_prompt hash changes.
- Model loses role/turn semantics; can't see tool_use/tool_result pairs from prior turns.
- Arbitrary truncation rules needed to stay under context; loses fidelity.

2. **Write AgentCore Memory → local `.jsonl` → `resume=`.** The file format is undocumented, so minor SDK updates can silently break it. We'd also need to reconstruct tool_use/tool_result pairs correctly or the model gets confused on the first turn.

3. **Abandon `ClaudeSDKClient` and call the `anthropic` SDK directly**, losing the Agent/sub-agent/hook/MCP machinery. Significant regression for apps that use those features.

## Proposed API (open to alternatives)

A few shapes that would solve this cleanly:

```python
# Option A: explicit `messages` on options
options = ClaudeAgentOptions(
system_prompt="...",
messages=[
{"role": "user", "content": "..."},
{"role": "assistant", "content": [...with tool_use blocks...]},
{"role": "user", "content": [...with tool_result blocks...]},
],
...
)

# Option B: pluggable session store
options = ClaudeAgentOptions(
session_store=MySessionStore(), # pulls history on connect
session_id="user-42",
...
)

# Option C: clarify query(AsyncIterable[dict]) as the history-seeding path
# and document the dict shape + guarantee that prior-turn dicts are
# treated as context rather than replayed as new queries.
```

## Related issues

- #109 (closed — shipped `get_session_messages` / `list_sessions` / `get_session_info` in 0.1.46). Solved **reading** existing sessions, not seeding new ones.
- #481 (closed without resolution comment). Asked roughly this question via `connect(prompt=history_stream)`; no documented answer.

## Why this matters

The SDK is positioned as a general-purpose Agent SDK (quoting a commenter on #109). For anyone building multi-session chat on top of managed memory services (AgentCore, Vertex AI, LangGraph-style state stores) or custom databases, the current gap forces an unfortunate choice between losing prompt caching, losing tool semantics, or re-implementing the agentic loop outside the SDK. A first-class history-seed API would unlock a large class of production use cases.

Happy to help test a proposed API or contribute a PR if useful guidance emerges.

Hướng dẫn đóng góp

Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.