Skip to content

pond as a third-party session manager: Strands Agents (SessionRepository) + Claude Agent SDK (SessionStore) #60

Description

@tenequm

Context capture from the 2026-06-17 research session. Goal: design pond so it can be contributed as a third-party session manager - to Strands Agents (their community catalog) and to the Claude Agent SDK - riding on the in-flight durability/perf/live-write/erasure work rather than as a separate rewrite.

The two integration seams (both thin Python shims over pond's HTTP API)

Strands: implement SessionRepository, not SessionManager

Strands has two seams. SessionManager = full lifecycle, you own everything (what AgentCore does). SessionRepository = thin CRUD storage; Strands' RepositorySessionManager wraps it and provides lifecycle/serialization. SessionRepository is pond's target (lower effort, pure storage). 8 abstract methods:

create_session(session) -> Session
read_session(session_id) -> Session | None
create_agent(session_id, session_agent) -> None
read_agent(session_id, agent_id) -> SessionAgent | None
update_agent(session_id, session_agent) -> None
create_message(session_id, agent_id, session_message) -> None
read_message(session_id, agent_id, message_id) -> SessionMessage | None
update_message(session_id, agent_id, session_message) -> None
list_messages(session_id, agent_id, limit=None, offset=0) -> list[SessionMessage]

Data model: Session > SessionAgent(state dict, conversation_manager_state dict) > SessionMessage(message, redact_message, message_id = int array index, not a UUID). Wiring: RepositorySessionManager(session_id=..., session_repository=pond_repo).

Claude Agent SDK: implement SessionStore (already scoped)

Mirror, not replacement (CLI writes local JSONL first, SDK forwards batches). Required append(key, entries) / load(key); optional listSessions / delete / listSubkeys. SessionKey = {projectKey, sessionId, subpath?}. delete of a main key must cascade to all subkeys. Acceptance gate = the shipped conformance suite (run_session_store_conformance): deep-equal (not byte-equal), in-order round-trip.

Why pond is differentiated (capability matrix)

Capability AgentCore Memory S3-Vectors plugin Claude SDK SessionStore pond
Lossless raw history No (extracts/summarizes for LTM) No (keeps 1 vector summary/convo, drops raw turns) Yes Yes
Semantic + SQL search Semantic only Semantic only None Yes (pond_search + pond_sql_query)
Cross-agent restore No No No Yes (ingest Codex, restore as Claude Code)
Compliance byte-purge delete No No No (reference adapters leave bytes) Yes (true purge + denylist)
Backend AWS Bedrock (locked) AWS S3 Vectors (locked) any Lance (local/S3/GCS/Azure)

pond is the only option that is lossless AND searchable AND cross-agent-restoring AND compliance-erasable. S3-Vectors is lossy; AgentCore is AWS-locked + summary-based; the SDK mirror has zero search.

How the in-flight work already builds this

Session-manager need Existing/in-flight work
Persist per-message/per-batch (append_message, SDK append) Live-write (micro-batch single-writer, #43) - the shared foundation for both shims; critical path
Lossless complete record (vs S3-Vectors) session-movement-complete (spec 5.4)
delete/deleteSession, cascade to subkeys/children, real purge Erasure session-append-only-exception - pond's cascade-to-children IS the SDK's "delete cascades to subkeys"; true byte-purge beats the SDK reference
SessionMessage.message_id = int array index The §4.6 ordering tiebreaker (source position, never write-time counter)
Search/retrieval (AgentCore has, SDK lacks) pond_search / pond_sql_query (shipped)

The 3 impedance mismatches to resolve at the API/spec level (the important context)

These are where Strands' model does not cleanly fit pond's canonical Session/Message/Part - decide the mapping during API design, not after:

  1. Agent runtime state. Strands SessionAgent carries state (kv dict) + conversation_manager_state (dict). pond models conversation, not agent runtime state - no home in Session/Message/Part. Needs a verbatim opaque blob store (session-scoped options.source.* carrier, or a small dedicated kv path) that read_agent returns byte-faithfully. Least-natural fit; decide explicitly.
  2. Redaction conflicts with append-only. Strands redact_latest_message / update_message replaces the latest message in place (guardrail case) - which adapter-integrity-additive-sync forbids. Options: superseding append + a "current" pointer, or a second narrow mutation exception (sibling to session-append-only-exception). Needs a spec decision or the Strands shim cannot be conformant.
  3. int message_id <-> pond string ids. Strands keys messages by array index; pond preserves source string ids. The shim needs a stable bidirectional index<->id map (the tiebreaker gives ordering; the map is shim-side).

Contribution mechanics

  • Strands: no plugin registry. Build from strands-agents/extension-template-python ("session manager" type), package as strands-{name} / strands_{name}, pass hatch run prepare, publish to PyPI, get listed manually in the community catalog (/docs/community/community-packages/).
  • Claude SDK: pass the conformance suite; the SDK never deletes from your store (retention is the adapter's job - fits pond's append-only + erasure model). The SDK delete method maps to pond's erase.

References

Scope note

Not a near-term plan - this is captured context so the live-write + erasure + completeness API surface is designed with the SDK SessionStore and the Strands SessionRepository as concrete consumers. The headline artifact is the cross-agent resume demo (no other session manager does it).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions