anthropics / anthropics/claude-agent-sdk-python

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

Aberta
#848 2 comentários 0 reações 0 responsáveis Ver no GitHub
Linguagem predominante
Python
Estrelas
8.1k
Forks
1.3k
Merge médio
2d 31min
PRs com merge (30d)
1

Descrição

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

Guia de contribuição

Nenhum guia de contribuição indexado para este repositório

Avaliação

Esta issue ainda não foi avaliada.

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.