Skip to content

Bidi - Snapshot support #3968

Closed
Closed

Description

@mehtarac

SDK Language

Python

Problem Statement

Support snapshot capture, restore, and snapshot-based session persistence for BidiAgent.

On upstream/main, Agent exposes take_snapshot() and load_snapshot(), but BidiAgent does not. SnapshotSessionManager.initialize() explicitly rejects Bidi. The shared repository session managers already support Bidi message history and application state through LocalAgent; snapshot support should extend that same design.

Proposed Solution

Share the snapshot contract through LocalAgent

Add take_snapshot() and load_snapshot() to the shared LocalAgent protocol and implement them on BidiAgent, with compatible signatures and the existing Snapshot envelope. This lets the session manager delegate capture and restore to the agent.

Follow the generic pattern established by SessionManager: a manager supporting both agent types implements the SessionManager[LocalAgent] contract. Widen the snapshot manager's common persistence methods accordingly and remove its Bidi rejection once the required surface exists.

Apply LocalAgent where an operation actually works for both agents:

Area Intended boundary
Snapshot capture/restore, save/list/restore APIs, and shared message/state handling LocalAgent and its shared snapshot methods
Shared initialization/message hooks AgentInitializedEvent[LocalAgent] and MessageAddedEvent[LocalAgent] where callbacks need explicit annotations
Regular invocation callback Keep AfterInvocationEvent specific to Agent
Bidi stop callback Keep BidiAgentStopEvent specific to BidiAgent; delegate the common save decision to shared logic
Conversation manager, model/interrupt internals, context-manager stash, and agent-level storage fallback Keep concrete Agent handling, narrowing at the boundary where needed
Graph/Swarm persistence Retain the existing MultiAgentBase path

LocalAgent is the shared protocol, not itself a generic. Parameterize the interfaces that carry an agent type. In particular, review SnapshotTrigger, which currently accepts Agent: shared triggers must support LocalAgent, while existing Agent-only callback typing should remain valid for Agent-only use. Follow the existing generic/default conventions and cover both forms with typing tests.

Do not mechanically replace every Agent annotation, add unsupported state to LocalAgent, or introduce parallel save_bidi_snapshot/restore_bidi_snapshot APIs. If the change requires extensive casts, type ignores, or a new dispatch framework, reconsider where the shared boundary was applied.

Capture the fields Bidi actually owns

Add the Bidi snapshot field/preset handling alongside the existing snapshot definitions:

  • The Bidi "session" preset captures messages and application state, matching repository session persistence.
  • Support system_prompt through include, preserving its structured content-block representation. SnapshotSessionManager already opts into this field.
  • Preserve app_data, independent copies, and the rule that fields absent from a snapshot leave the target unchanged.
  • Preserve the existing Agent preset and its conversation-manager, interrupt, and model state. Bidi should not serialize placeholder versions of these fields merely to reuse that preset.
  • Validate explicitly requested unsupported fields consistently with the snapshot API. Keep the shared method signatures compatible rather than narrowing an override's accepted keyword types.

This restores durable conversation/application state into a newly configured agent. Live connections, provider resumption handles, audio buffers, pending tasks, and invocation_state are outside this change.

Wire persistence to Bidi lifecycle events

SnapshotSessionManager overrides register_hooks(), so widening its type annotations alone will not provide Bidi persistence.

Restore synchronously through the existing shared initialization event, before Bidi opens its model connection. Reuse the shared message-added event for the "message" strategy.

Proposed initial completion boundary: use BidiAgentStopEvent, matching the repository session manager and the former Bidi invocation hook. Reuse the existing save/trigger decision:

  • "message" saves on each message and flushes final state at stop.
  • "invocation" saves at stop.
  • "trigger" saves when its trigger fires at stop, or when explicitly requested.
  • Preserve immutable-checkpoint behavior and the existing fallback save when a trigger raises.

Respect stop-hook ordering and cleanup-failure behavior. BidiResponseCompleteEvent describes an individual model response, not the lifetime of the streaming session; per-response checkpoint cadence can be considered separately.

Bidi currently has no agent-level storage or context_manager. Use the manager's supplied storage, or its local-file fallback, and guard Agent-only storage/stash handling. Reuse the existing serialization and storage layout.

Acceptance Criteria

  • Bidi supports direct snapshot capture/restore, applicable presets and include/exclude options, structured prompts, independent copies, and missing-field behavior.
  • A fresh BidiAgent and manager over the same storage/session/agent IDs restore messages, application state, and the persisted prompt before model startup.
  • Bidi supports latest snapshots, immutable checkpoint creation/listing/restore, and session deletion through the existing APIs.
  • Tests cover each save policy, trigger success/failure, final state changes at stop, and stop cleanup errors. Define and test restoration behavior while a Bidi connection is active; do not silently replace local state while the provider continues with different history.
  • Typing tests exercise the shared snapshot contract and manager with both agents, including shared and Agent-only triggers. Replace the existing typing assertion that rejects a Bidi snapshot manager.
  • Existing Agent snapshots, stateful-model restoration, redaction persistence, stash integration, and Graph/Swarm persistence continue to pass.
  • Update the Bidi session-management and snapshot documentation with capture/restore and persistence examples, replacing the current Bidi unsupported statements.

Use Case

A voice assistant can resume persisted conversation history and application state after a process restart, or restore an earlier checkpoint through the same snapshot APIs used by regular agents.

Alternatives Solutions

Continue using FileSessionManager or S3SessionManager for message-log persistence. They already support Bidi, but do not provide the snapshot checkpoint/time-travel API.

Additional Context

Part of #1722. Related shared-typing work: #3764.

Reference PRs:

Implementation references inspected on September 24, 2026, at upstream/main commit 18becd79d70d131f5417631916ab154b099df0b9:

Activity

  1. self-assigned this
    on Aug 25, 2026
  2. added theissue type on Aug 25, 2026
  3. 1 remaining item

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Fields

Language

None yet

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions