Changelog
Release history for the AgentDuet Python SDK. Each release lists new features, behavior changes, fixes, and any action needed when you upgrade. The current documentation targets 1.1.0b10.
The 1.1.0b* versions are pre-releases. Install the documented version with pip install agentduet==1.1.0b10.
A plain pip install agentduet does not select pre-releases by default.
1.1.0b10 — 2026-10-26
Documentation
- Updated the PyPI package description to list every trigger-condition option, including fallback recording and spoken drop messages.
- No SDK behavior changed from
1.1.0b9.
Known issue
VoiceAgent.call_out(), dial(), and place_call() use the wrong incoming audio track for agent-placed outgoing calls.
The call can connect and play model audio, but the model does not receive the callee’s audio correctly.
Versions 1.1.0b2 through 1.1.0b10 are affected. The fix is not included in this release.
For outbound two-way audio, use Session.make_call() and Call.dial() directly.
Read the remote audio from call.callee.audio_stream().
See the outbound Quick Start.
1.1.0b9 — 2026-10-26
Added
- Fallback call recordings: Set
fallback_recording(True)to record calls that the fallback connects without an agent. Register@sm.on_call_recordingto receive recording details, then usesm.download_recording()to get stereo Ogg Opus audio. - Recording acknowledgment: By default, a successful recording handler acknowledges and deletes the recording on the server.
Use
auto_ack=Falseto control deletion after you store the recording.list_call_recordings()lists pending recordings;ack_call_recordings()acknowledges them and returns a count. - Spoken drop messages: Use
drop_message(text)withCallFallback.DROPto play a message before the server ends the call. The message must contain 1 to 500 characters after trimming.
Changed
- A notified call must be claimed within 10 seconds of delivery, reduced from 60 seconds.
- At the session limit, the server waits up to 15 seconds for a slot, reduced from 30 seconds. The claim period starts when the notification arrives.
Upgrade action: Call session.process_call(noti) before slow setup, database requests, or model connections.
Review your fallback policy because an unclaimed call can connect without the agent or end.
See Trigger Conditions and Event Handling.
1.1.0b8 — 2026-10-13
Added
- DDUET conversation handover: Use
Session.hand_over_conversation()to transfer a conversation to staff. Send the closing message first. You can include a staff-only summary. The method returnsConversationHandoverResult; inspectsuccessand the error fields.
After handover, conversation messages stop reaching the agent and further sends return FORBIDDEN.
Only staff can assign the conversation back to the agent.
DDUET voice calls and remote function calls can still reach the agent.
Changed
- Control connections now reconnect with full-jitter exponential backoff: a random delay within an increasing window, capped at 8 seconds.
- Heartbeat pings run every 15 seconds with a 5-second response timeout.
Removed
- Removed
TriggerConditionsBuilder.call_log()andTriggerConditions.call_log. Do not post a call-log message part from your application.
See DDUET conversation handover and connection recovery.
1.1.0b7 — 2026-10-06
Added
- Server-bound sessions: Incoming messages, call notifications, and function calls include an optional
session_id. Reuse this ID when the server supplies one. - Participant attachment: Pass
participant=Address(...)toopen_session()to attach the remote party immediately. - Session keep-alive: Use
async with session.keep_alive():during slow work to refresh an existing session slot. The default refresh interval is 20 seconds. It does not restore an expired slot. - Conversation association: Echo an incoming
conversationvalue on relatedsend_message()andmake_call()operations. On DDUET, this also identifies the conversation for the call-log entry. - Call fallback: Configure
CallFallback.DROPorCONNECT_TO_DESTINATIONfor calls that no agent claims. - Conversation ID aliases: DDUET parsing reads
convoIdfirst and falls back tosessionUid. Theconvo_idanddduet_convo_idproperties expose the same values under the new name.
Changed
- Opening a new session without
participant=does not yet create a server session or consume a session slot. The first claim or send creates it. - The server applies fallback when a call remains unclaimed.
An incoming call connects to its destination only when
inbound_callisALLand the fallback permits connection. Otherwise, the server ends the call.
Upgrade action: Reuse server-provided session and conversation IDs.
Set every trigger option that your application needs; each setup replaces the full configuration.
The call timing was reduced again in 1.1.0b9, as listed above.
See Sessions and Call Handoff and Trigger Conditions.
1.1.0b6 — 2026-10-05
Added
- DDUET remote function calls: Register
@sm.on_function_call(name)to receive anIncomingFunctionCall. Claim the call withsession.process_function_call(fn)before doing the work. Answer withsession.send_function_result()or reject it withfn.reject(). - Delivery reporting: The SDK reports message receipt and processing outcomes to the service. Outcomes include successful handling, handler errors, and dropped messages. Applications do not need a new callback for these reports.
Changed
Renamed identity fields to make message and call direction explicit:
Notifications also expose the opposite address as to_address or from_address.
Call.caller, Call.callee, Call.participant, and SendDduetMessage.participant keep their names.
Deprecated
- Previous identity properties remain as read-only aliases in this release and emit
DeprecationWarning. - The old
subscriber=keyword remains accepted where its replacement issubscriber_id=. Passing both spellings raisesTypeError.
Fixed
- Fixed incoming event delivery stopping after the 100th frame.
Upgrade action: Use the current field and parameter names.
To find deprecated usage, run your tests with -W error::DeprecationWarning.
See Participant Model and remote function calls.
1.1.0b5 — 2026-09-14
Added
- DDUET media upload: Use
Session.upload_media(UploadDduetMedia(...))to upload a file. Reference the returnedUploadedMediain a message withSendDduetMessage.compose()orUploadedMedia.as_part(). - Media downloads through sessions:
Session.download_media()returns one attachment’s bytes.download_media_all()returns orderedDownloadedMediaresults, including individual failures. - Call origin:
Call.originidentifies whether the agent, subscriber, or external participant started the call. Only an agent-originated call usesdial().
Breaking changes
- Replaced the media URL helpers introduced in
1.1.0b4with session upload and download methods. RemovedSessionManager.get_dduet_media_urls(),get_media_urls(),MediaUrl, and the module-leveldownload_media()helper. - Renamed
DduetMediaUidtoDduetMediaAttachment. Attachments now carry the metadata and routing needed to download them. - Removed
ba_uidfrom outgoing DDUET messages. Open the session for the acting business account; the session supplies its identity on each send. - Changed the serialized call origin from
_origintoorigin, usingAGENT,SUBSCRIBER, orPARTICIPANT. Earlier JSON handoff payloads are incompatible with this format.
Upgrade action: Replace the removed media helpers and outgoing-message ba_uid= arguments.
Drain pending call handoffs before upgrading across the origin-format change.
Use the same SDK version on both nodes that exchange serialized calls.
See DDUET media and Sessions and Call Handoff.
1.1.0b4 — 2026-09-03
Added
- Added DDUET media-download URL resolution and a download helper.
These original media APIs were replaced in 1.1.0b5.
For current applications, use the Session media methods.
1.1.0b3 — 2026-08-25
Added
- Token-provider authentication: Pass a zero-argument sync or async function to
SessionManagerConfig.create(token_provider=...). It must return a non-empty bearer token. - The SDK requests a fresh token before each control connection attempt and authenticated HTTP request.
TokenProviderErrorreports a failed provider or an invalid token value. A provider failure during reconnection stops retries and surfaces throughrun_forever()andsm.fatal_error.
This is a third authentication option alongside API key authentication and mTLS. Use an async provider for long waits, such as interactive sign-in.
See Token provider authentication.
1.1.0b2 — 2026-08-21
Breaking changes
- Removed the nested DDUET
addressobject introduced in1.1.0b1. - Replaced
IncomingMessage.addressandIncomingMessage.dduet_session_uidwith the typedmsg.dduetview. - Outgoing DDUET messages use
session_uidandparticipantto address replies. The temporary outgoingba_uidargument was later removed in1.1.0b5. SendMessageResult.dduet_session_uidreads the conversation identifier from the send response.
Documentation
- Updated the DDUET quick start and reference tables to use the flat message format.
- Documented the
user_uidandba_uidcomparison for identifying the message author. DDUET reply handlers should ignore messages authored by their own business-account staff.
WhatsApp message routing and voice calling were unaffected by the DDUET message-format change. See DDUET messages.
1.1.0b1 — 2026-08-17
Added
- DDUET chat: Added a messaging channel for text and media, including
Network.DDUET,Address.dduet(), andSendDduetMessage. - Outgoing-call notifications: Added
@sm.on_outgoing_callfor calls that the subscriber starts outside the SDK. Enable these notifications withoutbound_call(True). - Outgoing message idempotency: Added
client_msg_idtosession.send_message(). Reuse the same ID when retrying one logical message so the server can identify a completed send.
Breaking changes
- Introduced a nested DDUET
addressobject for message routing. That format was replaced in1.1.0b2and must not be used with1.1.0b10.
1.0.0 — 2026-08-10
First stable release under the agentduet package name.
This release redesigns the earlier telcoflow-sdk API around connector notifications, subscriber sessions, and calls.
Added
SessionManagerfor the control connection and incoming call and message handlers.Sessionfor claiming calls, creating outgoing calls, and sending messages for a subscriber.CallandCallPartyfor call control and separate caller and callee audio streams.VoiceAgentfor model-adapter-based voice agents. Ready-made adapters ship in the separateagentduet-adapterspackage.CallAudioConfigfor sample rate, outgoing buffer size, and incoming audio queue limits.- Trigger conditions for connector routing, API key and mTLS authentication, and JSON call handoff between workers.
Changed
- Call states are
NEW,OPENING,RINGING,LIVE, andTERMINATED. - Expected command failures return an unsuccessful
CommandResult. State errors, closed calls, and full audio buffers raise exceptions. - Call audio uses separate party tracks. The previous audio-mode setting is no longer required.
Removed
- Removed the
ActiveCallAPI and the SDK TTS methods introduced in0.27.1. - Removed
CloseReason, the public voice-connection property, and the top-levelBufferClosedErrorexport.
Migration from telcoflow-sdk
- Replace the package dependency and imports with
agentduet. - Register notification handlers on
SessionManager. - Open a session for the subscriber, then claim or create a call through that session.
- Read party audio through
call.caller.audio_stream()orcall.callee.audio_stream(). - Catch
TransportErrorfor control-connection failures andCallClosedErrorwhen a voice call ends. - Replace
WSS_BASE_URLwithAGENTDUET_BASE_URL.
DDUET messaging and application-supplied client_msg_id were added in the 1.1.0 pre-release series, not in 1.0.0.
Earlier telcoflow-sdk releases
Versions 0.27.1 and earlier used the telcoflow-sdk package name.
The following entries describe that historical API. They are not instructions for the current agentduet release.
0.27.1 — 2026-05-06
Added
- Voice cloning through
ActiveCall.enable_tts(voice_id)andActiveCall.send_tts(text). CallEvent.CALL_ERROR,CallErrorCode.TTS_SESSION_ERROR, andActiveCall.on_error()for non-fatal call errors.
These SDK TTS methods were removed in agentduet 1.0.0.
0.27.0 — 2026-04-13
Added
- Channel selection on
ActiveCall.audio_stream(channel_id=...)for mixed and separate party audio. AudioMode.MIXEDandAudioMode.ISOLATEDconfiguration.
Current AgentDuet calls use separate CallParty streams instead of this API.
0.26.1 — 2026-04-06
Fixed
- Restored control-connection reconnection after transient failures.
0.26.0 — 2026-03-26
Fixed
- Sent the interruption command to the server when an interruption occurred.
0.25.0 — 2026-03-25
Changed
- Renamed
ActiveCall.force_disconnect()to the private_force_close()method. - Added automatic cleanup when a call ends.
Upgrade action: Remove application calls to force_disconnect() and let the SDK manage cleanup.
0.24.0 — 2026-03-19
Added
- Support for 8000 Hz audio alongside 16000 Hz and 24000 Hz.
Fixed
- Minor bugs.
0.21.0 — 2026-03-16
Changed
- Renamed the command-response timeout parameter to
response_timeout_seconds.
Added
BufferClosedErrorandActiveCall.force_disconnect()for the APIs available at that time.
0.20.0 — 2026-03-10
Changed
- Introduced enum-based event registration and improved signal and connection handling.
- Changed
ActiveCall.close()so the agent leaves while the server manages media shutdown.
Added
ActiveCall.disconnect()to end a call for all parties.
Removed
- Removed
ActiveCall.hangup(), deprecated event constants, andActiveCall.is_connected().
0.18.0 — 2026-03-07
Changed
- An unanswered
connect()reportsCALL_UNANSWEREDthroughCallCommandErrorin this historical API. Applications could handle the error and decide whether to retry or end the call.
