Skip to content

Unify model and session interface#17

Merged
mehtarac merged 12 commits into
mehtarac:mainfrom
mkmeral:provider-interface-refactor
Nov 4, 2025
Merged

Unify model and session interface#17
mehtarac merged 12 commits into
mehtarac:mainfrom
mkmeral:provider-interface-refactor

Conversation

@mkmeral
Copy link
Copy Markdown

@mkmeral mkmeral commented Oct 30, 2025

Description

This PR implements a unified bidirectional streaming interface that simplifies the API while maintaining strong typing and provider flexibility. Following the decision from PR #11, we've adopted a unified model interface that combines configuration and connection state in a single class, eliminating the separate session abstraction.

Key Changes

1. Unified Model Interface

Before (Two-Layer):

model = NovaSonicBidirectionalModel(region="us-east-1")
session = await model.create_bidirectional_connection(system_prompt="...")
await session.send_text_content("Hello")
await session.receive_events()
await session.close()

After (Unified):

model = NovaSonicBidirectionalModel(region="us-east-1")
await model.connect(system_prompt="...")
await model.send("Hello")
await model.receive()
await model.close()

2. Unified send() Method

Replaced multiple content-specific methods with a single polymorphic send() method:

Before:

await session.send_text_content("Hello")
await session.send_audio_content(audio_event)
await session.send_image_content(image_event)
await session.send_tool_result(tool_id, result)
await session.send_interrupt()

After:

await model.send(TextInputEvent(text="Hello", role="user"))
await model.send(AudioInputEvent(audioData=bytes, format="pcm", ...))
await model.send(ImageInputEvent(imageData=bytes, mimeType="image/jpeg"))
await model.send(ToolResult(toolUseId="123", status="success", ...))

3. New Typed Input Events

Added TextInputEvent for consistency with other input event types:

class TextInputEvent(TypedDict):
    text: str
    role: Role

4. Simplified Connection Lifecycle

  • BidirectionalModel now directly implements connect(), send(), receive(), and close()
  • Removed BidirectionalModelSession as a separate abstraction
  • Added backwards compatibility alias: BidirectionalModelSession = BidirectionalModel

5. Updated All Provider Implementations

  • Nova Sonic: Unified interface with internal state management
  • Gemini Live: Simplified SDK integration without separate session class
  • OpenAI Realtime: Streamlined WebSocket connection handling

6. Comprehensive Unit Tests

Added extensive test coverage for all three providers:

  • tests/strands/experimental/bidirectional_streaming/models/test_gemini_live.py (500 lines)
  • tests/strands/experimental/bidirectional_streaming/models/test_novasonic.py (551 lines)
  • Tests cover initialization, connection lifecycle, event conversion, and unified send method

Benefits

Simpler API: Single interface per model, familiar pattern matching core Strands Agent
Better Type Safety: Explicit typed events for all input types
Cleaner Architecture: Internal separation maintained without exposing complexity
Industry Alignment: Matches patterns from Google Gemini Live and OpenAI Realtime APIs
Backwards Compatible: Alias provided for existing code using BidirectionalModelSession

Related Issues

Implements the unified interface decision from #11

Documentation PR

Documentation updates will follow in a separate PR to agents-docs

Type of Change

Breaking change

Testing

  • ✅ Added comprehensive unit tests for all three providers (Gemini Live, Nova Sonic, OpenAI Realtime)
  • ✅ Tests cover initialization, connection lifecycle, unified send method, event conversion
  • ✅ All existing integration tests updated to use new interface
  • I ran hatch run prepare

Checklist

  • I have read the CONTRIBUTING document
  • I have added any necessary tests that prove my fix is effective or my feature works
  • I have updated the documentation accordingly
  • I have added an appropriate example to the documentation to outline the feature, or no new docs are needed
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Comment thread src/strands/experimental/bidirectional_streaming/models/bidirectional_model.py Outdated
@JackYPCOnline
Copy link
Copy Markdown
Collaborator

Overall comment regarding file naming convention: Since these files are already located within the bidirectional_streaming directory, we don't need to include "bidirectional_streaming" in each individual file name, eg we could just call base_model, event_type something.

Comment thread src/strands/experimental/bidirectional_streaming/models/novasonic.py Outdated
Comment thread src/strands/experimental/bidirectional_streaming/models/gemini_live.py Outdated
Comment thread src/strands/experimental/bidirectional_streaming/models/novasonic.py Outdated
Comment thread src/strands/experimental/bidirectional_streaming/models/novasonic.py Outdated
Comment thread src/strands/experimental/bidirectional_streaming/models/openai.py
Comment thread src/strands/experimental/bidirectional_streaming/models/openai.py
@github-actions github-actions Bot added size/xl and removed size/xl labels Nov 4, 2025
@mkmeral mkmeral mentioned this pull request Nov 4, 2025
"event": {
"contentStart": {
"promptName": self.prompt_name,
"promptName": self.session_id,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you replied me, but here is session_id? bad rebase?

"event": {
"audioInput": {
"promptName": self.prompt_name,
"promptName": self.session_id,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also here

@JackYPCOnline
Copy link
Copy Markdown
Collaborator

TODO: This pr is a dependency to other ongoing works. Merge this PR now, need to follow up on naming and coding consistency.

@mehtarac mehtarac merged commit 6e56dd5 into mehtarac:main Nov 4, 2025
1 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants