Universal.Operative.Sdk.Realtime.OpenAI 1.0.0

dotnet add package Universal.Operative.Sdk.Realtime.OpenAI --version 1.0.0
                    
NuGet\Install-Package Universal.Operative.Sdk.Realtime.OpenAI -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Universal.Operative.Sdk.Realtime.OpenAI" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Universal.Operative.Sdk.Realtime.OpenAI" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Universal.Operative.Sdk.Realtime.OpenAI" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Universal.Operative.Sdk.Realtime.OpenAI --version 1.0.0
                    
#r "nuget: Universal.Operative.Sdk.Realtime.OpenAI, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Universal.Operative.Sdk.Realtime.OpenAI@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Universal.Operative.Sdk.Realtime.OpenAI&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Universal.Operative.Sdk.Realtime.OpenAI&version=1.0.0
                    
Install as a Cake Tool

About

Universal.Operative.Sdk.Realtime.OpenAI adapts the OpenAI Realtime API to Universal.Operative.Sdk.Realtime's provider-neutral IModel/IRealtimeSession/SessionEvent model. Ported from the Ong.Bot/Operative.Marin prototype.

Two connection paths in this release: Model.ConnectAsync (server-mediated WebSocket — audio relays through your process) and Model.ConnectForCallAsync (SIP passthrough — audio flows directly between the caller and OpenAI, never touching your process). Browser-direct WebRTC (an ephemeral-key handshake so a browser tab talks to OpenAI without your server in the audio path) isn't implemented yet.

How to Use

Installation

dotnet add package Universal.Operative.Sdk
dotnet add package Universal.Operative.Sdk.Realtime
dotnet add package Universal.Operative.Sdk.Realtime.OpenAI

Quick start

using Universal.Operative.Sdk.Realtime;
using Universal.Operative.Sdk.Realtime.OpenAI;

var model = new Model(apiKey, modelId: "gpt-realtime", defaultVoice: "marin");

IRealtimeSession session = await model.ConnectAsync(new RealtimeSessionOptions
{
    SystemPrompt = [new TextBlock("You are a helpful voice assistant.")],
    Tools = [myTool],
});

IOperative operative = OperativeBuilder.Create(session).AddTool(myTool).Build();

await foreach (SessionOutputEvent e in operative.RunAsync())
{
    switch (e)
    {
        case SessionReadyEvent: Console.WriteLine("connected"); break;
        case TranscriptDeltaEvent t: Console.WriteLine($"{t.Role}: {t.Text}"); break;
        case AudioOutputDeltaEvent a: /* play a.Audio (24kHz PCM16) */ break;
        case InterruptedEvent: /* stop playback immediately */ break;
    }
}

await operative.SendAsync(new AppendAudioInputEvent { Audio = micChunk });

Fidelity notes

  • Capabilities: AudioInProcess | ToolCalling | Transcripts — audio flows through this same WebSocket, and there's no native session resumption (SessionCapabilities.NativeResumption/ClientAssistedResumption are both unset).
  • Tool results: the full ToolResult content (all blocks, not just text) is flattened into OpenAI's single-string function_call_output — text blocks contribute their text verbatim, anything else is JSON-serialized rather than silently dropped.
  • Tool choice: RealtimeSessionOptions.ToolChoice is sent as OpenAI's own tool_choice at connect time (same shape as Chat Completions/Responses — a bare string for auto/required/none, a structured object to force one specific tool).
  • Raw passthrough: OpenAI's Realtime API has substantially more event types than are mapped to canonical events here (item lifecycle events, rate-limit updates, built-in MCP tool events, text-modality deltas). Anything not explicitly mapped arrives as a RawPassthroughEvent rather than being dropped.
  • Mid-session reconfiguration: OpenAI's session.update (changing instructions/voice/tools/tool-choice after connecting) has no canonical SessionInputEvent yet — unconfirmed whether Gemini or Nova Sonic support anything equivalent, so it isn't promoted. This adapter recognizes RawSendEvent for it two ways: pass a constructed SessionUpdateEvent (from Universal.OpenAI.Realtime.Client) as Payload for full control, or just set RawJson to a {"type":"session.update",...} string — the adapter deserializes that one specific shape directly (no polymorphism involved, so this only recognizes that one allowlisted type; anything else needs the typed Payload). Any other unhandled input event still throws NotSupportedException.
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 41 8/12/2026

OpenAI Realtime adapter for Universal.Operative.Sdk.Realtime. Two connection paths: Model.ConnectAsync (server-mediated WebSocket) and Model.ConnectForCallAsync (SIP passthrough, audio flows directly between the caller and OpenAI). Browser-direct WebRTC isn't implemented. RealtimeSessionOptions.ToolChoice is sent as OpenAI's own tool_choice at connect time; RawSendEvent carries mid-session session.update (e.g. changing tool_choice).