anthropics / anthropics/claude-agent-sdk-python

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

Aperta
#848 2 commenti 0 reazioni 0 assegnatari Vedi su GitHub
Lingua principale
Python
Stelle
8.1k
Fork
1.3k
Merge medio
2g 31m
PR unite (30g)
1

Descrizione

## 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.

Guida per i contributori

Nessuna guida per i contributori indicizzata per questo repository

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.