[Do not merge][Debug] Preview for voiceagent - #48484
[Do not merge][Debug] Preview for voiceagent#48484xitzhang (xitzhang) wants to merge 69 commits into
Conversation
|
Azure Pipelines: Successfully started running 1 pipeline(s). 10 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
Pull request overview
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
This PR introduces an initial preview of the azure-ai-voiceagents Python SDK, including generated management clients, a hand-written async realtime (WebSocket) client, and supporting samples/tests for validation and guidance.
Changes:
- Adds the new
azure-ai-voiceagentspackage skeleton (generated clients/models + packaging metadata). - Implements an async realtime WebSocket client (
aio/_realtime.py) and an aiohttp transport workaround for brotli negotiation. - Adds unit tests, recorded tests (with sanitization), live smoke test, and scenario-based samples + sample README.
Reviewed changes
Copilot reviewed 59 out of 63 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| sdk/voiceagents/azure-ai-voiceagents/tsp-location.yaml | Tracks source spec location for generation/regeneration. |
| sdk/voiceagents/azure-ai-voiceagents/tests/unit/test_configuration.py | Unit tests for configuration defaults/required params. |
| sdk/voiceagents/azure-ai-voiceagents/tests/unit/test_client_construction.py | Unit tests for sync/async client construction and operation groups. |
| sdk/voiceagents/azure-ai-voiceagents/tests/unit/test_brotli_workaround.py | Unit tests validating async brotli/aiohttp transport workaround behavior. |
| sdk/voiceagents/azure-ai-voiceagents/tests/unit/conftest.py | Disables recorded-test proxy startup for unit-test runs. |
| sdk/voiceagents/azure-ai-voiceagents/tests/recording/test_voice_agents_client_async.py | Recorded async functional tests for read-only operations. |
| sdk/voiceagents/azure-ai-voiceagents/tests/recording/test_voice_agents_client.py | Recorded sync functional tests for read-only operations. |
| sdk/voiceagents/azure-ai-voiceagents/tests/recording/conftest.py | Adds extra URI sanitization for project name in recordings. |
| sdk/voiceagents/azure-ai-voiceagents/tests/recording/_preparer.py | Shared preparer/sanitized env var loader for recorded/live tests. |
| sdk/voiceagents/azure-ai-voiceagents/tests/live/test_smoke_live.py | Always-live smoke test to catch auth/wire/serialization issues. |
| sdk/voiceagents/azure-ai-voiceagents/tests/live/conftest.py | Disables recorded-test proxy startup for live-test runs. |
| sdk/voiceagents/azure-ai-voiceagents/tests/conftest.py | Starts the test-proxy for recorded tests. |
| sdk/voiceagents/azure-ai-voiceagents/samples/quickstart/sample_quickstart_async.py | End-to-end quickstart: create temp agent + realtime audio session + cleanup. |
| sdk/voiceagents/azure-ai-voiceagents/samples/management/sample_read_conversation_audio.py | Demonstrates reading and streaming persisted conversation audio to WAV. |
| sdk/voiceagents/azure-ai-voiceagents/samples/management/sample_read_conversation.py | Demonstrates reading persisted conversation envelope/items/responses. |
| sdk/voiceagents/azure-ai-voiceagents/samples/management/sample_manage_voice_agent_versions.py | Demonstrates creating/listing/fetching voice agent versions (incl drafts). |
| sdk/voiceagents/azure-ai-voiceagents/samples/management/sample_generate_voice_agent.py | Demonstrates guided-authoring agent generation and cleanup. |
| sdk/voiceagents/azure-ai-voiceagents/samples/management/sample_create_voice_agent_with_tools.py | Demonstrates richer agent definitions (tools + audio config + BYOM). |
| sdk/voiceagents/azure-ai-voiceagents/samples/management/sample_create_and_manage_voice_agent_async.py | Async management lifecycle sample: create/get/list/delete. |
| sdk/voiceagents/azure-ai-voiceagents/samples/management/sample_create_and_manage_voice_agent.py | Sync management lifecycle sample incl update and enable/disable. |
| sdk/voiceagents/azure-ai-voiceagents/samples/live/sample_live_text_conversation_async.py | Live typed conversation + optional audio playback + readback. |
| sdk/voiceagents/azure-ai-voiceagents/samples/live/sample_live_audio_conversation_async.py | Live mic/speaker conversation + barge-in + readback. |
| sdk/voiceagents/azure-ai-voiceagents/samples/README.md | Scenario-organized samples index + setup/troubleshooting guidance. |
| sdk/voiceagents/azure-ai-voiceagents/pytest.ini | Configures pytest asyncio integration (asyncio_mode=auto). |
| sdk/voiceagents/azure-ai-voiceagents/pyrightconfig.json | Pyright configuration for local development/type-checking. |
| sdk/voiceagents/azure-ai-voiceagents/pyproject.toml | Package metadata and dependencies for azure-ai-voiceagents. |
| sdk/voiceagents/azure-ai-voiceagents/dev_requirements.txt | Dev dependencies including local azure-core/azure-identity and aiohttp. |
| sdk/voiceagents/azure-ai-voiceagents/azure_ai_voiceagents-1.0.0b1/azure/ai/voiceagents/_configuration.py | Snapshot of generated configuration under versioned folder. |
| sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/py.typed | PEP 561 typing marker. |
| sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/operations/_patch.py | Customization hook for generated operations (sync). |
| sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/operations/init.py | Exposes sync operation groups and patch hook. |
| sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/models/_patch.py | Customization hook for generated models. |
| sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/models/_enums.py | Generated enums supporting voice agents + realtime schemas. |
| sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/models/init.py | Public models/enums surface exports. |
| sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/aio/operations/_patch.py | Customization hook for generated operations (async). |
| sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/aio/operations/init.py | Exposes async operation groups and patch hook. |
| sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/aio/_realtime.py | Hand-written async realtime WebSocket client and event typing. |
| sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/aio/_patch.py | Async client patch: adds realtime namespace + brotli workaround. |
| sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/aio/_configuration.py | Generated async configuration. |
| sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/aio/_client.py | Generated async HTTP client and operation group wiring. |
| sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/aio/init.py | Async package exports and patch hook. |
| sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/_version.py | Package version constant. |
| sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/_utils/init.py | Generated utils package init. |
| sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/_unions.py | Generated public type aliases/unions. |
| sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/_patch.py | Sync customization hook placeholder. |
| sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/_configuration.py | Generated sync configuration. |
| sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/_client.py | Generated sync HTTP client and operation group wiring. |
| sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/init.py | Sync package exports and patch hook + version. |
| sdk/voiceagents/azure-ai-voiceagents/azure/ai/init.py | Namespace package marker for azure.ai. |
| sdk/voiceagents/azure-ai-voiceagents/azure/init.py | Namespace package marker for azure. |
| sdk/voiceagents/azure-ai-voiceagents/assets.json | Azure SDK assets tag configuration for CI. |
| sdk/voiceagents/azure-ai-voiceagents/apiview-properties.json | APIView cross-language mapping metadata. |
| sdk/voiceagents/azure-ai-voiceagents/_metadata.json | Tracks API version metadata for generation. |
| sdk/voiceagents/azure-ai-voiceagents/README.md | Package README scaffold. |
| sdk/voiceagents/azure-ai-voiceagents/MANIFEST.in | Source distribution inclusions (tests/samples/py.typed, etc.). |
| sdk/voiceagents/azure-ai-voiceagents/LICENSE | MIT license text. |
| sdk/voiceagents/azure-ai-voiceagents/CHANGELOG.md | Initial changelog entry for version b1. |
Suppressed comments (3)
sdk/voiceagents/azure-ai-voiceagents/tsp-location.yaml:1
- The PR description is still the template (missing a real summary of changes, links to relevant issues/spec PRs, and checklist updates). Please replace the placeholder description with a concise overview of what this PR adds (new SDK package, realtime WebSocket client, samples/tests) and link the spec change PR/commit referenced in
tsp-location.yaml.
sdk/voiceagents/azure-ai-voiceagents/tests/unit/test_configuration.py:1 - This test doesn’t actually validate overriding behavior because it passes the same value as the default (
\"v1\"). Consider changing it to pass a different value (orNoneif supported by the client) so the test can detect regressions where the override is ignored.
sdk/voiceagents/azure-ai-voiceagents/samples/management/sample_create_and_manage_voice_agent.py:1 - Using a fixed, non-namespaced
agent_namerisks collisions across repeated runs and (more importantly) can inadvertently delete/modify a real agent if a user already has an agent with that name. Safer pattern for samples is to generate a unique name (e.g., including a UUID suffix) and only delete the resource that the sample created.
There was a problem hiding this comment.
Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.
Note
This error may be related to your runner configuration. You can now configure runners for Copilot code review separately from Copilot cloud agent by creating a copilot-code-review.yml file with your setup steps. Read the docs for details.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 63 out of 67 changed files in this pull request and generated 2 comments.
Suppressed comments (8)
sdk/voiceagents/ci.yml:1
- The PR description is still the template text (it asks to 'add an informative description' and link issues), but the change set is substantial (new SDK + CI + tests + samples). Please update the PR description to summarize the intent/scope and link any relevant spec/issue/PR references so reviewers can validate the changes against requirements.
sdk/voiceagents/azure-ai-voiceagents/pyproject.toml:1 - Excluding the
azureandazure.aipackages from package discovery is likely to produce an invalid wheel where the namespace package initializers (azure/__init__.py,azure/ai/__init__.py) are not installed, breaking imports in environments that rely on pkgutil-style namespace packaging. Recommended fix: remove\"azure\"and\"azure.ai\"from the exclude list (or switch to an explicit include pattern forazure*packages consistent with other Azure SDK Python packages).
sdk/voiceagents/azure-ai-voiceagents/samples/live/sample_live_audio_conversation_async.py:1 - The callback can return fewer than
wantedbytes when it hits the end-of-stream marker (if not data: break). pyaudio callbacks must return exactly the requested frame size; otherwise playback can glitch or error. Instead ofbreak, pad the remainder with silence (or returnpaCompletewith a correctly-sized buffer) to satisfy pyaudio’s size contract.
sdk/voiceagents/azure-ai-voiceagents/tests/unit/test_configuration.py:1 - This test name claims the API version is 'overridden', but it sets the value to the default (
\"v1\"), so it doesn’t actually verify override behavior. Either rename the test to reflect what it asserts (e.g., thatapi_versionis stored), or setapi_versionto a non-default value (if supported by the client) to validate that overriding works.
sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/aio/_realtime.py:648 - Passing the WebSocket subprotocol by manually setting
Sec-WebSocket-Protocolis fragile because many WS clients (including aiohttp) expect to manage/validate this header via theprotocols=[...]argument. Preferws_connect(..., protocols=[\"realtime\"], ...)and remove the manual header to avoid handshake issues and ensure the negotiated subprotocol is tracked correctly by the client.
headers: Dict[str, str] = {
"Authorization": f"Bearer {token.token}",
"Foundry-Features": str(foundry_features),
"Sec-WebSocket-Protocol": "realtime",
}
sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/aio/_realtime.py:655
- Passing the WebSocket subprotocol by manually setting
Sec-WebSocket-Protocolis fragile because many WS clients (including aiohttp) expect to manage/validate this header via theprotocols=[...]argument. Preferws_connect(..., protocols=[\"realtime\"], ...)and remove the manual header to avoid handshake issues and ensure the negotiated subprotocol is tracked correctly by the client.
connection = await session.ws_connect(url, headers=headers, params=params, **self._kwargs)
sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/_configuration.py:36
- The docstring says the default
api_versionisNone, but the implementation defaults it to\"v1\". Please align the docstring with the actual behavior (and consider applying the same fix in the async configuration file as well) to avoid confusing SDK consumers.
:keyword api_version: The API version to use for this operation. Known values are "v1" and
None. Default value is None. If not set, the operation's default API version will be used. Note
that overriding this default value may result in unsupported behavior.
sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/_configuration.py:41
- The docstring says the default
api_versionisNone, but the implementation defaults it to\"v1\". Please align the docstring with the actual behavior (and consider applying the same fix in the async configuration file as well) to avoid confusing SDK consumers.
def __init__(self, endpoint: str, credential: "TokenCredential", **kwargs: Any) -> None:
api_version: str = kwargs.pop("api_version", "v1")
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 63 out of 67 changed files in this pull request and generated 3 comments.
Suppressed comments (6)
sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/aio/_realtime.py:51
- The exported connection's public methods and attributes use
ClientEvent,ServerEvent,ConversationItem, and the resource helper classes in their annotations, but this module andaio/_patch.pyexport only the three connection classes. Consumers therefore see public annotations that can only be imported from the private_realtimemodule. Re-export all types used by this public surface fromazure.ai.voiceagents.aio.
__all__ = [
"AsyncRealtime",
"AsyncRealtimeConnection",
"AsyncRealtimeConnectionManager",
]
sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/aio/_patch.py:45
- Constructing
aiohttp.ClientSessionhere eagerly requires a running event loop and binds the client to that loop. This makes otherwise valid async-client construction outsideasyncio.run()fail before any request. Set the defaultAccept-Encodingthrough the headers policy instead soAioHttpTransportcan retain its lazy session creation.
kwargs["transport"] = AioHttpTransport(
session=aiohttp.ClientSession(auto_decompress=False, headers={"Accept-Encoding": "gzip, deflate"})
)
sdk/voiceagents/azure-ai-voiceagents/samples/live/sample_live_audio_conversation_async.py:138
- Barge-in does not discard a partially consumed chunk: each callback copies bytes from
remainingbefore checking that chunk's sequence against_playback_base. A large delta can therefore continue playing across callbacks afterskip_pending_audio(). Track the sequence associated withremainingand invalidate it before slicing whenever it is older than the playback base.
sdk/voiceagents/azure-ai-voiceagents/samples/quickstart/sample_quickstart_async.py:100 - Barge-in does not discard a partially consumed chunk: bytes are copied from
remainingbefore the callback checks sequence validity. If a delta spans multiple callback buffers, stale audio continues playing afterskip_pending_audio(). Associateremainingwith its sequence and clear it before slicing when that sequence predates_playback_base.
sdk/voiceagents/azure-ai-voiceagents/tests/unit/test_configuration.py:47 - This test passes the same value as the default, so it still passes if the
api_versionoverride is ignored. Use a distinct sentinel value to verify that the keyword is actually honored.
sdk/voiceagents/azure-ai-voiceagents/samples/live/sample_live_text_conversation_async.py:179 - After a timeout, the response remains active and its eventual events stay queued. On the next turn,
pump()can consume the previous response'sresponse.doneand return before the new response completes, or the service can reject the new response while the old one is active. Cancel the timed-out response and drain/match its terminal event before accepting another prompt.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 63 out of 67 changed files in this pull request and generated 2 comments.
Suppressed comments (8)
sdk/voiceagents/azure-ai-voiceagents/pyproject.toml:13
- This new package is missing both
api.mdandapi.metadata.yml. The repository API consistency gate explicitly marks an affected package missing either file as a failure (.github/workflows/src/api-md-consistency/find_mismatches.js:76-92). Generate and commit both files withazpysdk apistub azure-ai-voiceagents.
sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/aio/_patch.py:43 - Creating
aiohttp.ClientSessionin the client constructor makesVoiceAgentsClient(...)require a running event loop and binds the transport to that loop. This breaks the normal pattern of constructing an async SDK client beforeasyncio.run(...)(the new test even documents this limitation). Create/configure the session lazily when the transport opens instead.
kwargs["transport"] = AioHttpTransport(
session=aiohttp.ClientSession(auto_decompress=False, headers={"Accept-Encoding": "gzip, deflate"})
)
sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/aio/_realtime.py:242
agent_nameis inserted into the URL as raw path text, unlike the generated operation which URL-serializes this path parameter. Reserved characters can therefore change the route instead of identifying the requested agent. Percent-encode the path segment before interpolation.
return f"{base}/agents/{agent_name}/endpoint/protocols/voice"
sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/aio/_patch.py:65
- The public annotations/docstrings refer to
azure.ai.voiceagents.aio.ClientEventandServerEvent, but these aliases are defined only in the private_realtimemodule and are not re-exported here. Those documented imports therefore fail; include both aliases in the public aio surface.
__all__: list[str] = [
"VoiceAgentsClient",
"AsyncRealtime",
"AsyncRealtimeConnection",
"AsyncRealtimeConnectionManager",
] # Add all objects you want publicly available to users at this package level
sdk/voiceagents/azure-ai-voiceagents/samples/quickstart/sample_quickstart_async.py:115
- The callback consumes
remainingbefore checking its sequence against_playback_base. Afterskip_pending_audio()advances the base during barge-in, bytes left from the old response are still played on the next callback, so interruption does not actually drop all pending audio. Track the sequence associated withremainingand clear it before consuming stale bytes.
sdk/voiceagents/azure-ai-voiceagents/samples/live/sample_live_audio_conversation_async.py:153 - The callback consumes
remainingbefore checking its sequence against_playback_base. After barge-in advances the base, bytes left from the previous response are still played on the next callback, contradicting the promised immediate drop of pending audio. Track the sequence associated withremainingand discard stale bytes before playback.
sdk/voiceagents/azure-ai-voiceagents/tests/unit/test_configuration.py:47 - This test supplies the same
v1value as the default, so it still passes if the override is ignored. Use a non-default sentinel to exercise the behavior named by the test.
sdk/voiceagents/azure-ai-voiceagents/azure/ai/voiceagents/aio/_realtime.py:522 - The hand-written realtime implementation has no deterministic unit coverage for frame serialization/deserialization, typed-event mapping and unknown-event fallback, close/error handling, or resource helpers; the live smoke test covers only one service path. Add mocked WebSocket/session tests for these public behaviors so regressions do not require a gated live environment to detect.
async def recv(self) -> ServerEvent:
This comment has been minimized.
This comment has been minimized.
…hony/WebRTC/sub-agent voice features, fix missing preview-header wiring
- Regenerate SDK from azure-rest-api-specs commit 1070c74ae519b6f86540bbd44ea295ff12642e60;
update tsp-location.yaml.saved accordingly.
- New voice-agent features from this commit (purely additive, no removed/renamed classes):
- Telephony bindings for Teams Phone/Twilio on �gents.* (create/list/get/update/delete
binding, list/get/transfer/end call, get/replace transfer targets - 11 new methods).
- Optional WebRTC transport for realtime sessions (VoiceAgentTransport.WEBRTC) with SDP
signaling events.
- New top-level �gent_endpoint_conversations operation group (generated-audio reads),
distinct from the unchanged �eta.agent_endpoint_conversations.
- Sub-agent consultation (VoiceAgentDefinition.subagent_config) and conversation_engine
delegation to a hosted agent.
- list_memories() unbound-variable bug fixed upstream: verified the fix, removed the
now-obsolete PostEmitter.ps1 fixup (kept an explanatory comment for future regression
detection).
- Fixed a real functional bug: the new telephony and agent_endpoint_conversations methods
require the Foundry-Features: VoiceAgents=V1Preview opt-in header per TypeSpec, but had no
header-injection wiring (would fail with preview_feature_required). Added header injection
(gated on �llow_preview, matching the existing generate_agent pattern) via 11 new method
overrides in _patch_agents.py/_patch_agents_async.py and new
_patch_agent_endpoint_conversations.py/_async.py files for the 2 new conversation methods.
Also fixed a generator bug where replace_telephony_transfer_targets's 2nd/3rd @overload
signatures had etag/match_condition types swapped.
- Registered 6 new realtime event types (1 client + 5 server, for RTC signaling and sub-agent
consultation) in _realtime.py/aio/_realtime.py.
- Added 13 new unit tests in tests/foundry_features_header/ covering the header-injection fix
for all new methods.
- Added tests/agents/test_voice_agent_telephony.py/_async.py (6 methods) covering telephony
bindings/calls/transfer-targets and generated-audio not-found paths. Currently skipped: the
telephony routes are defined in TypeSpec but not yet deployed on the live test service
(confirmed via empty-body 404s vs a real app-level 404's full JSON error body), and the
generated-audio not-found path hits the same pre-existing conversation-ID validation quirk as
the already-documented beta.agent_endpoint_conversations limitation.
- Updated docs/public-methods.md (170->183 methods) and CHANGELOG.md.
- Regenerated api.md/api.metadata.yml.
- Validated: full test suite (1026 passed, 111 skipped, 0 failed) run fresh in one pass, plus
live e2e validation of 10 of 11 voice-agent samples against the real service, including both
live-streaming samples (text conversation sync+async, function tool) which exercise realtime
WebSocket sessions, tool-calling, and conversation persistence/readback end-to-end. Confirmed
the regeneration is reproducible by re-running tsp-client update + PostEmitter.ps1 from
scratch and diffing against the working tree (identical result).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
Resolve sample-runner hangs, truncated audio frames, missing telephony coverage, and inaccurate WebSocket documentation.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (2)
sdk/ai/azure-ai-projects/azure/ai/projects/_realtime.py:786
- The public documentation says a
ws://override is accepted, butRealtimeConnectionManager.enter()rejects every URL that does not start withwss://. Document this aswss://only so callers are not promised an option that always raisesValueError.
:keyword connection_url: Full ``wss://``/``ws://`` URL that overrides the route computed
from the client endpoint. Query parameters are still appended. Default value is None.
sdk/ai/azure-ai-projects/azure/ai/projects/aio/_realtime.py:792
- The public documentation says a
ws://override is accepted, butAsyncRealtimeConnectionManager.enter()rejects every URL that does not start withwss://. Document this aswss://only so callers are not promised an option that always raisesValueError.
:keyword connection_url: Full ``wss://``/``ws://`` URL that overrides the route computed
from the client endpoint. Query parameters are still appended. Default value is None.
- Files reviewed: 67/71 changed files
- Comments generated: 5
- Review effort level: Balanced
…pupr Resolved conflicts in azure-ai-projects between this branch's regeneration from TypeSpec commit 1070c74ae519b6f86540bbd44ea295ff12642e60 (telephony, WebRTC, sub-agent consultation, generated-audio conversation reads) and main's independent regeneration/hand-written additions (agent_insight_monitors patch classes, ShellToolboxTool, WebIQPreviewTool, Hosted Agent session configuration, routines.create_or_update authorization). Resolution strategy: - Fully generated files (_operations.py x2, _models.py, _enums.py, models/__init__.py): took this branch's side after verifying, at the class and method level, that it is a strict superset of main's content (zero classes/methods present on main but absent here). - Hand-written orchestration files (operations/_patch.py and aio equivalent): merged both sides' additions (this branch's AgentEndpointConversationsOperations wiring + main's BetaAgentInsightMonitorsOperations wiring); removed a resulting duplicate import of BetaAgentInsightMonitorsOperations from the generated module now that it's patched. - CHANGELOG.md: merged both sides' entries; corrected an inaccurate entry (the new �uthorization parameter is on .beta.routines.create_or_update, not .beta.routines.dispatch as this branch's changelog had said). - tsp-location.yaml: adopted main's convention of tracking the file directly (main had renamed away from the .saved split specifically to avoid breaking the release build), keeping this branch's commit 1070c74ae519b6f86540bbd44ea295ff12642e60. - api.md/api.metadata.yml: regenerated fresh via �zpysdk apistub . against the resolved source rather than hand-merging generated markdown. - docs/public-methods.md: kept this branch's version; verified method counts are still accurate post-merge (no method-set changes from main's patch). - Fixed two duplicate dict keys (�gent_insight_monitors in both models/_patch.py's _BETA_OPERATION_FEATURE_HEADERS and foundry_features_header_test_base.py's EXPECTED_FOUNDRY_FEATURES) that git's line-based auto-merge introduced silently (both entries had identical values, so this was not a functional bug, just redundant code). Validated: full test suite re-run after resolution (1026 passed, 111 skipped, 0 failed) - identical results to before the merge, confirming no regressions in either branch's contributions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved moderate issues affect realtime behavior, sample automation, dependencies, API metadata, and telephony coverage.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (7)
eng/tools/azure-sdk-tools/azpysdk/samples.py:92
- The samples runner recursively executes every Python file not listed here. The two new read-conversation samples require a pre-existing persisted
FOUNDRY_VOICE_CONVERSATION_IDand do not create one, so the automated samples check cannot run them reliably. Ignore those two files as well, or make them self-contained.
"azure-ai-projects": [
# These interactively read from stdin via input(), which raises EOFError when this
# runner executes the file non-interactively.
"sample_voice_agent_live_text_conversation.py",
"sample_voice_agent_live_text_conversation_async.py",
],
scripts/devops_tasks/test_run_samples.py:96
- Keep this legacy runner's ignore list aligned with the azpysdk runner. It also recursively executes every Python sample, so the two read-conversation samples will fail without a valid pre-existing
FOUNDRY_VOICE_CONVERSATION_ID.
"azure-ai-projects": [
# These interactively read from stdin via input(), which raises EOFError when this
# runner executes the file non-interactively.
"sample_voice_agent_live_text_conversation.py",
"sample_voice_agent_live_text_conversation_async.py",
],
sdk/ai/azure-ai-projects/docs/public-methods.md:63
- The legend says hand-written methods carry
*, and both of these methods are overridden in_patch_agent_endpoint_conversations.py; omitting the markers makes this generated inventory inaccurate.
sdk/ai/azure-ai-projects/docs/public-methods.md:162 begin_create_runis still implemented by the customBetaAgentInsightMonitorsOperationsinoperations/_patch_agent_insights.py, so removing its*contradicts this document's hand-written-method legend.
sdk/ai/azure-ai-projects/tests/agents/test_voice_agent_telephony.py:82- Every test in this new module is skipped, so none of the telephony request serialization, response handling, or generated-audio behavior is exercised in CI. Before merging the new API surface, enable these tests or add transport-mocked coverage that does not depend on undeployed service routes.
sdk/ai/azure-ai-projects/tests/agents/test_voice_agent_telephony_async.py:82 - The async counterpart is also entirely skipped, leaving the new async telephony and generated-audio paths without executable coverage. Enable these cases or replace them with transport-mocked tests before merging.
sdk/ai/azure-ai-projects/tsp-location.yaml:2 - This regeneration advances the TypeSpec commit, but the PR description is still the template and provides no link to the corresponding API-spec change. Please add the source spec PR/commit context so reviewers can validate the generated API against its requirements.
- Files reviewed: 66/70 changed files
- Comments generated: 7
- Review effort level: Balanced
The previous regeneration used a cached wheel in .venv_apistub/.staging predating some merge-resolution fixes, causing api.md to omit AgentInsightRunLROPoller/AsyncAgentInsightRunLROPoller and the base class of BetaAgentInsightMonitorsOperations, even though the actual source was always correct. Cleared the stale cache and regenerated fresh; verified a full line-by-line diff against main's api.md now shows zero API elements present in main but absent here. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved moderate issues affect preview gating, compatibility, sample automation, API metadata, linting, and test coverage.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (10)
eng/tools/azure-sdk-tools/azpysdk/samples.py:91
- This ignore list is incomplete for the newly added voice samples. The sample runner executes every unlisted
*.py; the read-conversation samples requireFOUNDRY_VOICE_AGENT_NAMEandFOUNDRY_VOICE_CONVERSATION_ID, which no test configuration supplies, and the live-audio sample runs until Ctrl-C when PyAudio is available. Add all three so the automated samples check does not fail or hang.
"azure-ai-projects": [
# These interactively read from stdin via input(), which raises EOFError when this
# runner executes the file non-interactively.
"sample_voice_agent_live_text_conversation.py",
"sample_voice_agent_live_text_conversation_async.py",
scripts/devops_tasks/test_run_samples.py:95
- Keep this legacy sample runner's ignore list aligned with the azpysdk runner. Otherwise it will execute the two read-conversation samples without their required pre-existing IDs, and can run the live-audio sample indefinitely when PyAudio is installed.
"azure-ai-projects": [
# These interactively read from stdin via input(), which raises EOFError when this
# runner executes the file non-interactively.
"sample_voice_agent_live_text_conversation.py",
"sample_voice_agent_live_text_conversation_async.py",
sdk/ai/azure-ai-projects/PostEmitter.ps1:40
- Deleting
azure.ai.projects.typesremoves an existing, non-private import path, so users importing its generated TypedDicts will getModuleNotFoundErrorafter upgrading. Retain a compatibility module (and deprecate it if needed) or correct its generation rather than removing it silently; this also conflicts with the PR checklist's no-breaking-changes claim.
$typesFile = 'azure\ai\projects\types.py'
if (Test-Path $typesFile) {
Remove-Item $typesFile -Force
sdk/ai/azure-ai-projects/api.metadata.yml:3
- This metadata was generated with parser 0.3.30, but the repository pins
apiview-stub-generator==0.3.31ineng/apiview_reqs.txt:18. Regenerateapi.mdand its metadata with the pinned parser; otherwise the committed parser version/hash will not match the repository's API snapshot tooling.
parserVersion: 0.3.30
sdk/ai/azure-ai-projects/docs/public-methods.md:10
- The updated claim that this document lists all 183 public methods omits the newly exported realtime API entirely (
realtime.connect, connectionsend/recv/close, and the session/conversation/audio/response helpers). Add that namespace and recalculate the summary so the public-surface inventory matches the API introduced by this PR.
sdk/ai/azure-ai-projects/docs/public-methods.md:63 - These methods are implemented by the new hand-written
AgentEndpointConversationsOperationssubclass, but the document says hand-written methods carry an asterisk. Mark both entries consistently so the API inventory remains accurate.
sdk/ai/azure-ai-projects/docs/public-methods.md:162 - Removing the asterisk makes this inventory claim
begin_create_runis generated, but it is still overridden inoperations/_patch_agent_insights.py:63. Keep the hand-written marker.
sdk/ai/azure-ai-projects/tests/agents/test_realtime_client.py:28 RealtimeServerEventErroris never referenced in this test module, so the newly added file introduces an unused-import pylint failure. Remove it from the import list.
sdk/ai/azure-ai-projects/tests/agents/test_voice_agent_telephony.py:82- All tests in this new telephony/generated-audio module are unconditionally skipped, so these new operation paths receive no request/response or error-handling coverage in CI. Add transport-mocked or recorded coverage that can run without the unavailable service routes instead of committing only disabled placeholders.
sdk/ai/azure-ai-projects/tests/agents/test_voice_agent_telephony_async.py:82 - All tests in this async telephony/generated-audio module are unconditionally skipped, leaving the new async operation paths unexecuted in CI. Add async transport-mocked or recorded tests that can run independently of deployment availability rather than relying only on header-injection tests.
- Files reviewed: 66/70 changed files
- Comments generated: 2
- Review effort level: Balanced
…ple/test fixes
Security:
- _assert_trusted_connection_url (sync + async _realtime.py) now compares
normalized (host, port) tuples with scheme-default-port resolution instead
of hostname alone, so a connection_url override targeting the same host on
a different, non-default port (a different origin) is correctly rejected
instead of receiving the live Authorization token.
Protocol/correctness fixes:
- Async realtime client now passes protocols=("realtime",) to aiohttp's
ws_connect() instead of a raw Sec-WebSocket-Protocol header, which aiohttp
never validates/negotiates on its own. Guarded against a caller-kwarg
collision on "protocols".
- Removed the dead/misleading http:// -> ws:// translation in _to_ws_url
(both sync and async): enter() unconditionally rejects any non-wss:// URL,
so that path could never actually be used to connect.
- Live-audio sample (sample_voice_agent_live_audio_conversation_async.py):
- End-of-stream playback callback branch now pads to the exact frame size
pyaudio requested instead of returning a short buffer.
- speech_started no longer calls response.cancel() when no response is
active (fixes a false-positive service error on the very first user turn).
- Mic capture callback now bounds concurrent in-flight sends to 1 and drops
(rather than unboundedly scheduling) frames while a send is still
in-flight, reporting the dropped-frame count at shutdown.
Test/tooling/doc fixes:
- Added test_voice_samples parametrization (tests/samples/test_samples.py,
test_samples_async.py) so samples/agents/voice/ is discovered by the
package's recorded sample tests (previously not wired up at all).
- Added the live-audio sample to IGNORED_SAMPLES in both
eng/tools/azure-sdk-tools/azpysdk/samples.py and
scripts/devops_tasks/test_run_samples.py: it runs until Ctrl-C and would
hang indefinitely under the non-interactive sample-runner.
- Pinned dev_requirements.txt's websockets to >=13.0 to match the realtime
extra's minimum version.
- Regenerated api.metadata.yml with the pinned apiview-stub-generator==0.3.31
(was stale at 0.3.30 from a cached build).
- Removed an unused RealtimeServerEventError import in test_realtime_client.py.
- Added regression tests: port-mismatch trusted-connection-url rejection,
explicit-default-port acceptance, protocols kwarg override, and non-https
scheme left unchanged in _to_ws_url.
Verified: full test suite passes (1029 passed, 113 skipped, 0 failed).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
Critical sample-runner failures and moderate API/header issues must be resolved before approval.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (8)
Previously missed (1) — in code that hasn't changed since the last review.
sdk/ai/azure-ai-projects/azure/ai/projects/models/_patch.py:81
- Routing this new group through
_OperationMethodHeaderProxyexposes its immutable-header fallback: if a caller passes a read-only mapping withoutFoundry-Features, the proxy catches the assignment failure and replaces the mapping with only the preview header, silently dropping all caller headers. Update the proxy fallback to merge{**headers, Foundry-Features: value};_AcceptEncodingIdentityProxyalready demonstrates the preserving behavior.
sdk/ai/azure-ai-projects/CHANGELOG.md:9
- This describes a standard agent
updateflow, butAgentsOperationsexposescreate_versionandupdate_details; there is noagents.updatemethod. Since editing the definition is done by publishing another version, the release note currently directs users to a nonexistent API.
* Added guided authoring via `project_client.agents.generate_agent(GenerateVoiceAgentRequest(kind=AgentKind.VOICE, ...))`, which returns a service-generated starter definition that can be edited afterward through the standard `create_version`/`update` flow.
sdk/ai/azure-ai-projects/docs/public-methods.md:63
- These methods are implemented as handwritten overrides in
operations/_patch_agent_endpoint_conversations.py, but the document's legend requires handwritten methods to carry*. Without the markers, this inventory incorrectly presents both as generated methods.
sdk/ai/azure-ai-projects/docs/public-methods.md:162 begin_create_runis still implemented by the handwritten_patch_agent_insights.pyoverride, so removing its*makes this inventory contradict its own legend.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_generate.py:13- The client has no
agents.updatemethod, so the documentedcreate_version/updateflow is misleading. Voice-agent definitions are changed by creating another immutable version.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_live_audio_conversation_async.py:32 - The sample's installation instructions are missing
python-dotenv, which is a required direct import on line 53 and is not a package dependency. A clean environment following this command cannot run the sample.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_live_text_conversation.py:30 - The setup command omits
python-dotenv, but this sample importsload_dotenvunconditionally. A user following these instructions in a clean environment will fail withModuleNotFoundErrorbefore the sample starts.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_live_text_conversation_async.py:27 - The setup command omits
python-dotenv, althoughload_dotenvis imported unconditionally below. Following the documented install command in a clean environment therefore makes the sample fail at startup.
- Files reviewed: 68/72 changed files
- Comments generated: 2
- Review effort level: Balanced
| "azure-ai-projects": [ | ||
| # These interactively read from stdin via input(), which raises EOFError when this | ||
| # runner executes the file non-interactively. | ||
| "sample_voice_agent_live_text_conversation.py", | ||
| "sample_voice_agent_live_text_conversation_async.py", | ||
| # Runs until Ctrl-C (continuous microphone capture/playback); would hang indefinitely | ||
| # under this non-interactive runner whenever PyAudio and live credentials are available. | ||
| "sample_voice_agent_live_audio_conversation_async.py", | ||
| ], |
… identification fix - _realtime.py/aio: add User-Agent + x-ms-client-sdk identification (ports fix from azure-ai-voicelive PR #48848), with case-insensitive header collision guard so a caller-supplied extra_headers User-Agent (any casing) is not duplicated - test_realtime_client(_async).py: add regression tests for identification headers and case-insensitive override behavior - tests/agents/test_voice_agent_realtime_live(_async).py: new live-only tests for voice agent realtime session lifecycle, text-to-audio/transcript turns, and function tool-call round trip - tests/agents/test_voice_agent_conversations(_async).py: new recorded tests for beta.agent_endpoint_conversations REST surface, with a live-only setup step to obtain a sanitized conversation_id for playback - assets.json: pin new recordings via test-proxy push (tag ..._d354d861da) - test-resources.bicep/test-resources-post.ps1/tests.yml: new live-test CI infrastructure (Foundry account/project + gpt-realtime model deployment), following the azure-ai-voicelive package pattern - CHANGELOG.md: document the identification fix under Bugs Fixed Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
Moderate issues remain in live-test provisioning, deployment configuration, and executable test coverage.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (16)
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_basic.py:24
- Voice-agent lifecycle APIs are introduced in 2.6.0, but this command permits 2.0.0. Raise the minimum so the models and operations used by the sample are present.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_basic_async.py:18 - Voice-agent lifecycle APIs are introduced in 2.6.0, but this command permits 2.0.0. Raise the minimum so the async sample installs a compatible SDK.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_generate.py:20 generate_agentfor voice agents is added in 2.6.0, so the current minimum can install an SDK that lacks the imported request type and method. Require 2.6.0.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_live_function_tool.py:23- The realtime voice-agent API used by this sample is introduced in 2.6.0, but this command permits 2.0.0. Raise the minimum so
client.realtimeand the event models are available.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_live_text_conversation.py:30 - The
realtimeextra andclient.realtimeAPI are introduced in 2.6.0, but this command accepts 2.0.0. Users following it can install an older SDK with no realtime namespace; require 2.6.0.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_live_text_conversation_async.py:27 - The
realtimeextra and async realtime API are introduced in 2.6.0, but this command accepts 2.0.0. Require 2.6.0 so the documented install includes the APIs used below.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_read_conversation.py:22 - The beta voice-conversation operation group is added in 2.6.0, so allowing 2.0.0 makes these instructions install versions without
beta.agent_endpoint_conversations. Raise the minimum to 2.6.0.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_read_conversation_audio.py:26 - The beta voice-conversation audio APIs are added in 2.6.0, so allowing 2.0.0 can install an SDK without these methods. Raise the documented minimum to 2.6.0.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_versions.py:19 - Voice-agent APIs are introduced in 2.6.0 (
CHANGELOG.md:3-17), but this command permits 2.0.0, whereVoiceAgentDefinitiondoes not provide this surface. Require 2.6.0 in the setup command.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_with_tools.py:25 - Voice-agent APIs are introduced in 2.6.0 (
CHANGELOG.md:3-17), but this command permits 2.0.0, where these models are unavailable. Require 2.6.0 so the documented setup installs a compatible SDK.
sdk/ai/azure-ai-projects/tests/agents/test_voice_agent_crud.py:33 - This limitation contradicts the new
test_voice_agent_conversations.py, which creates a persisted realtime conversation ID and then reads it throughbeta.agent_endpoint_conversations. Update this note now that read-back is covered separately.
sdk/ai/azure-ai-projects/tests/agents/test_voice_agent_crud_async.py:34 - This limitation contradicts the new async conversation test, which creates a persisted realtime conversation ID and reads it through this REST operation group. Replace the stale service-bug note with a reference to the dedicated coverage.
sdk/ai/azure-ai-projects/tests/agents/test_voice_agent_telephony.py:34 - Every test in this new sync test module is unconditionally skipped, leaving the telephony and generated-audio operation behavior without executable functional coverage; the feature-header tests only validate header injection. Add transport-mocked tests or enable these scenarios before the API is considered covered.
sdk/ai/azure-ai-projects/tests/agents/test_voice_agent_telephony.py:62 - This says realtime-generated conversation IDs are rejected, but the new
test_voice_agent_conversations.pyexercises exactly that setup and read-back path. Update this bullet to point to the dedicated test instead of documenting a conflicting limitation.
sdk/ai/azure-ai-projects/tests/agents/test_voice_agent_telephony_async.py:34 - Every test in this new async test module is unconditionally skipped, leaving the async telephony and generated-audio operation behavior without executable functional coverage; the feature-header tests only validate header injection. Add transport-mocked tests or enable these scenarios before the API is considered covered.
sdk/ai/azure-ai-projects/tsp-location.yaml:2 - This regeneration pin changes the source specification, but the PR description is still the unfilled template and does not link the corresponding
azure-rest-api-specsPR. Replace the template with the voice-agent scope and the source-spec PR so reviewers can validate these generated API changes.
- Files reviewed: 75/79 changed files
- Comments generated: 6
- Review effort level: Balanced
| if (-not $ready) { | ||
| Write-Warning "The '$deploymentName' deployment did not finish provisioning in time. Live voice-agent tests may fail until it finishes." | ||
| } |
| TestResourceDirectories: | ||
| - ai/azure-ai-projects | ||
| EnvVars: | ||
| AZURE_TEST_RUN_LIVE: 'true' |
| agent_name=agent_name, | ||
| definition=VoiceAgentDefinition( | ||
| model_type=VoiceModelType.MANAGED, | ||
| model="gpt-realtime", |
| agent_name=agent_name, | ||
| definition=VoiceAgentDefinition( | ||
| model_type=VoiceModelType.MANAGED, | ||
| model="gpt-realtime", |
| # PR #48484: recording not yet available for these REST-only samples. | ||
| "sample_voice_agent_basic.py", | ||
| "sample_voice_agent_generate.py", | ||
| "sample_voice_agent_versions.py", | ||
| "sample_voice_agent_with_tools.py", |
| "sample_voice_agent_live_text_conversation_async.py", | ||
| "sample_voice_agent_live_audio_conversation_async.py", | ||
| # PR #48484: recording not yet available for this REST-only sample. | ||
| "sample_voice_agent_basic_async.py", |
…pupr Resolves conflicts in sdk/ai/azure-ai-projects: - CHANGELOG.md: combined voice-agent entries with main's content-safety moderation, ShellToolboxTool/WebIQPreviewTool, external_web_access, and sample-update entries (deduplicated bullets that existed on both sides); consolidated to a single Bugs Fixed section per release. - tests/foundry_features_header/foundry_features_header_test_base.py: the expected Foundry-Features value for .agents.* methods now includes BOTH VoiceAgents=V1Preview (ours) and ModelRouterControls=V1Preview (main's), matching the already-correctly-merged _AGENT_OPERATION_FEATURE_HEADERS constant in azure/ai/projects/models/_patch.py. - assets.json: our recordings tag and main's recordings tag had diverged (disjoint file sets - our 8 new voice-agent recordings vs main's 71 updated sample/telemetry recordings). Restored main's tag, layered our voice-agent recordings on top, and pushed a new combined tag so both sides' recorded tests have working cassettes. - tsp-location.yaml/.saved: main renamed this file to tsp-location.yaml.saved; followed main's convention for consistency. - api.metadata.yml, apiview-properties.json, docs/public-methods.md: kept ours for now; will be regenerated via �zpysdk apistub . immediately after this merge to reflect the fully-merged API surface. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…merge Follow-up to the merge commit: these are generated artifacts that were resolved with a placeholder during conflict resolution. Regenerated via `azpysdk apistub .` (api.md, apiview-properties.json - unchanged) and via a fresh runtime introspection of AIProjectClient (docs/public-methods.md) so they correctly reflect the fully-merged API surface (voice agents + main's independent additions). Also corrected api.metadata.yml's apiMdSha256, which the apistub tool did not update to match the regenerated api.md. Verified: full test suite passes (1038 passed, 119 skipped, 0 failed), including the foundry_features_header tests and the recorded voice-agent conversation tests against the newly-combined assets recordings tag. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
Multiple moderate issues remain in sample execution, live-test configuration, realtime handling, and test coverage.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (9)
eng/tools/azure-sdk-tools/azpysdk/samples.py:96
- This ignore list still allows both read-conversation samples to run, although they unconditionally read
FOUNDRY_VOICE_CONVERSATION_IDand the new test resources cannot provide a pre-existing conversation ID. Becauseazpysdk samplesexecutes every unignored Python sample, the samples check will fail withKeyError; add both read samples to this list as the package-level sample tests already do.
"sample_voice_agent_live_audio_conversation_async.py",
scripts/devops_tasks/test_run_samples.py:98
- This legacy runner also executes every unignored Python sample, so the two read-conversation samples will fail when
FOUNDRY_VOICE_CONVERSATION_IDis absent. Keep this duplicate ignore table aligned with the azpysdk table and exclude both state-dependent samples.
"sample_voice_agent_live_audio_conversation_async.py",
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_read_conversation.py:29
- The included live conversation samples obtain the persisted ID from the
session.createdevent, notconversation.created. Referencing the latter sends users looking for an event this client intentionally leaves untyped; update the instruction to match the demonstrated API.
sdk/ai/azure-ai-projects/tests.yml:11 - This switches the entire
azure-ai-projectstest run to live mode, but the accompanying Bicep template explicitly provisions only the voice-agent surface and omits resources needed by the package's existing datasets, evaluations, fine-tuning, storage, and connection tests. The manual pipeline will therefore run unrelated recorded tests against an incomplete live environment; filter the test job to dedicated voice markers/tests or provision the complete package resource set.
sdk/ai/azure-ai-projects/tests/agents/test_voice_agent_realtime_live.py:222 - This live test bypasses the configured
FOUNDRY_VOICE_MODEL_NAMEused by the other tests in this class. Any test deployment whose resource name is not literallygpt-realtimewill fail before reaching the WebSocket behavior being tested. Use the prepared deployment name instead.
sdk/ai/azure-ai-projects/tests/agents/test_voice_agent_realtime_live_async.py:219 - The async function-tool test also hardcodes the model resource name instead of using the deployment supplied by
servicePreparer. This makes the test fail in otherwise valid environments that deploy the realtime model under another name.
sdk/ai/azure-ai-projects/tests/agents/test_voice_agent_telephony.py:82 - Every test in this new module is unconditionally skipped, so none of the telephony request paths, response deserialization, or generated-audio operations execute in CI. Header-proxy tests alone cannot validate those contracts; add transport-mocked/recorded coverage that can run now, and keep only genuinely service-dependent success scenarios skipped.
sdk/ai/azure-ai-projects/tests/samples/test_samples.py:409 - After
get_sample_pathsfilters out_async.py, this blacklist excludes every remaining voice sample, so this parametrized test has zero runnable cases. Commit recordings for at least the REST-only samples (or omit this no-op test until they are available) so the newly added samples receive actual execution coverage.
sdk/ai/azure-ai-projects/tests/samples/test_samples_async.py:328 - These three entries are all of the async voice samples discovered by
get_async_sample_paths, so this new test parametrizes no runnable case. Add a recording for the REST-only async sample (or defer this no-op test) rather than presenting an empty sample test suite.
- Files reviewed: 74/78 changed files
- Comments generated: 3
- Review effort level: Balanced
[Pilot] PR Pipeline Failure AnalysisWhat failedAzure Pipeline build 6787439 ( Relevant pipeline outputRecommended next steps
Automated fix: Requested
|
…e PR review comments CI fixes (build 6787439 Analyze stage): - cspell: add PSTN/pstn (telephony acronym) to the allowed words list - mypy/pyright: fix a genuine TypeSpec-emitter bug where the generated replace_telephony_transfer_targets JSON/IO[bytes]-body @overload stubs had etag/match_condition types swapped vs. the real implementation, in both sync and async _operations.py; also add a PostEmitter.ps1 fixup so this self-heals on future regenerations - pylint: fix C0411 wrong-import-order in _realtime.py/aio/_realtime.py (the UserAgentPolicy import was placed after local imports) PR #48484 review comment fixes: - Add the two persisted-conversation voice samples to IGNORED_SAMPLES in both sample-runner copies (they require a pre-existing FOUNDRY_VOICE_CONVERSATION_ID that automation doesn't provide) - test-resources-post.ps1: fail resource provisioning immediately on a deployment-readiness timeout instead of warning and continuing into live tests against a not-ready model - tests.yml: restrict the live-test pipeline to voice-specific tests via a new live_test_only marker + TestMarkArgument, since this pipeline's Bicep only provisions the voice model, not the full package's resource set - test_voice_agent_realtime_live(_async).py: use the prepared foundry_voice_model_name instead of a hardcoded "gpt-realtime" deployment name - _realtime.py: fix a real bug in the sync WebSocket connect -- disable websockets' own default User-Agent (user_agent_header=None) and drop a caller-supplied subprotocols kwarg to prevent a collision with the fixed "realtime" subprotocol, matching the async implementation's existing handling; add 2 regression tests - test_voice_agent_conversations(_async).py: make conversation completion a hard requirement for the audio assertions instead of a silent skip, so a future re-recording can't hide a regression in all four audio methods Verified: 1042 passed, 119 skipped, 0 failed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
Multiple moderate issues leave async error handling, model selection, and voice test coverage incomplete.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (5)
Previously missed (2) — in code that hasn't changed since the last review.
sdk/ai/azure-ai-projects/tests/agents/test_voice_agent_conversations.py:246
- This loop can fall through after every item returns 404, so the test passes without finding any item audio even though the preceding comment says per-item audio is a hard requirement. Use the loop's
elsebranch to fail when no iteration reachesbreak.
sdk/ai/azure-ai-projects/tests/agents/test_voice_agent_conversations_async.py:239 - This loop can exhaust all items after 404 responses and still let the test pass, leaving both per-item audio methods effectively unverified. Fail via a
for/elsewhen no item reaches thisbreak.
sdk/ai/azure-ai-projects/CHANGELOG.md:9
agentshas no publicupdatemethod (the generated surface exposescreate_versionandupdate_details), and voice-agent definitions are updated by creating a new immutable version. Referring users tocreate_version/updatetherefore points them to a nonexistent API.
* Added guided authoring via `project_client.agents.generate_agent(GenerateVoiceAgentRequest(kind=AgentKind.VOICE, ...))`, which returns a service-generated starter definition that can be edited afterward through the standard `create_version`/`update` flow.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_read_conversation.py:29
- The referenced live-audio sample obtains the persisted ID from
RealtimeServerEventSessionCreated, not from aconversation.createdevent. The current instruction sends users looking for an event that the sample never handles.
sdk/ai/azure-ai-projects/tests/agents/test_voice_agent_telephony.py:82 - All three tests in this new module are unconditionally skipped, so CI never exercises telephony response deserialization, service error handling, or generated-audio error mapping. The header-capture suite stops at request transmission; please add transport-mocked or recorded response tests that can run until the service routes are available.
- Files reviewed: 75/79 changed files
- Comments generated: 2
- Review effort level: Balanced
…odel output sample_voice_agent_generate.py, sample_voice_agent_live_function_tool.py, sample_voice_agent_live_text_conversation(_async).py, and sample_voice_agent_live_audio_conversation_async.py print agent/LLM-generated text (instructions, transcripts) that can contain characters (curly quotes, em-dashes, etc.) outside some legacy, non-Unicode console encodings. When stdout isn't a real interactive console (for example piped or redirected on Windows, falling back to cp1252), a plain print() of that text can raise UnicodeEncodeError and crash the sample outright -- reproduced live in sample_voice_agent_live_audio_conversation_async.py. Fix is scoped locally to each risky print() call site via a small _safe_print helper (duplicated per file, matching this samples folder's existing convention of self-contained, standalone scripts): try a normal print() first, and only on UnicodeEncodeError fall back to replacing the unsupported characters. This is not a global sys.stdout.reconfigure(): this package's own sample_executor.py runs these samples in-process via exec_module() for tests/samples/test_samples.py, so any global stdout mutation at module level would leak into every other sample executed afterward in the same pytest worker. The local, per-call fallback has no effect outside its own print statement. Verified live against the real service, including re-running the exact sample/agent that originally crashed: no exception in any case, and zero data loss (verified via PYTHONUTF8=1, matching how a modern terminal behaves) when the console can actually represent the text; only the pathological legacy-codepage-without-a-real-console case substitutes a placeholder character instead of crashing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Replace hardcoded agent names with FOUNDRY_VOICE_AGENT_NAME env var (sample_voice_agent_versions.py, sample_voice_agent_with_tools.py) - Use FOUNDRY_VOICE_MODEL env var instead of hardcoded model name (sample_voice_agent_live_function_tool.py) - Use typed isinstance checks instead of dict/getattr dual-path access for conversation items and tools, since the SDK deserializes these to real typed model instances, not raw mappings (sample_voice_agent_live_function_tool.py, sample_voice_agent_with_tools.py) - Remove unnecessary discriminator kwarg and its type: ignore suppression when constructing VoiceAgentMcpTool (sample_voice_agent_with_tools.py) - Update docstrings for the newly-documented environment variables All 3 changes verified end-to-end against the live service. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
One critical live-test provisioning failure and three moderate preview/sample issues remain unresolved.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (2)
sdk/ai/azure-ai-projects/azure/ai/projects/_patch.py:265
- This top-level preview surface bypasses the client's documented
allow_previewopt-in:Realtime.connect()always sendsVoiceAgents=V1Preview, even when the client was constructed with the defaultallow_preview=False. Unlike.beta,client.realtimeis a top-level API, and every added sample passesallow_preview=True, so accessing it without that consent should fail rather than silently enabling preview behavior. Apply the same guard to the async property.
@property
def realtime(self) -> Realtime:
"""Realtime streaming entry point for voice agents.
:return: The realtime namespace, exposing ``connect(...)``.
:rtype: ~azure.ai.projects.Realtime
"""
if self._realtime is None:
self._realtime = Realtime(self)
sdk/ai/azure-ai-projects/azure/ai/projects/aio/_patch.py:210
- The async top-level realtime surface also silently opts callers into
VoiceAgents=V1Previeweven whenallow_previewis left at its documented default ofFalse. This differs from other top-level preview APIs and makes the explicit opt-in ineffective; mirror the sync guard here.
@property
def realtime(self) -> AsyncRealtime:
"""Realtime streaming entry point for voice agents.
:return: The realtime namespace, exposing ``connect(...)``.
:rtype: ~azure.ai.projects.aio.AsyncRealtime
"""
if self._realtime is None:
self._realtime = AsyncRealtime(self)
- Files reviewed: 75/79 changed files
- Comments generated: 2
- Review effort level: Balanced
| elif isinstance(event, RealtimeServerEventResponseDone): | ||
| # A response.done that isn't a function call is the final answer for this turn. | ||
| if not any( | ||
| isinstance(item, RealtimeConversationItemFunctionCall) for item in (event.response.output or []) | ||
| ): | ||
| return |
…safety check - tests.yml: add Location: eastus2. The shared archetype-sdk-tests template defaults this cloud's region to westus when unset, but gpt-realtime (GlobalStandard, 2025-08-28) is only deployable in eastus2/centralus/ canadacentral per the official Azure OpenAI region-availability docs, so resource provisioning was failing before any live test could run. - sample_voice_agent_live_function_tool.py: restore the dict/getattr dual-path check for identifying a function-call item in response.done's output list, in place of a pure isinstance() check introduced by an earlier cleanup pass. response.output is a documented open/extensible union; an item kind not yet mapped by this SDK version can surface as a plain mapping instead of a typed model, and the isinstance-only check would silently mistake the first tool-call turn for the final answer, closing the connection before the tool result is ever sent. Matches the same defensive pattern already used by the SDK's own test_voice_agent_realtime_live.py live test. Both changes verified: tests.yml against a live re-run of the affected pytest suite; the sample against a fresh live get_weather tool-call round-trip. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
A critical bearer-token authentication defect and unresolved realtime sequencing, sample-runner, and test-coverage issues block approval.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (6)
Previously missed (4) — in code that hasn't changed since the last review.
sdk/ai/azure-ai-projects/tests/agents/test_voice_agent_conversations.py:226
- If every item returns 404, this loop falls through and the test passes without ever exercising
get_agent_conversation_item_audio_content, despite the preceding comment making per-item audio coverage a hard requirement. Track whether an item with audio was found and fail after the loop when none was found, so a cassette cannot silently omit this API coverage.
sdk/ai/azure-ai-projects/tests/agents/test_voice_agent_conversations_async.py:218 - If every item returns 404, this loop falls through and the test passes without ever exercising
get_agent_conversation_item_audio_content, despite the preceding comment making per-item audio coverage a hard requirement. Track whether an item with audio was found and fail after the loop when none was found, so a cassette cannot silently omit this API coverage.
sdk/ai/azure-ai-projects/tests/agents/test_voice_agent_realtime_live.py:267 - The follow-up response is created before the current function-call response emits
response.done. The realtime protocol can reject this as a concurrent active response; the existing Voice Live test waits forresponse.donebefore adding the tool output and callingresponse.create(sdk/voicelive/azure-ai-voicelive/tests/live/test_live_realtime_tools.py:271-281). Defer these operations until the function-call response completes.
sdk/ai/azure-ai-projects/tests/agents/test_voice_agent_realtime_live_async.py:265 - The follow-up response is created before the current function-call response emits
response.done. The realtime protocol can reject this as a concurrent active response; the existing Voice Live test waits forresponse.donebefore adding the tool output and callingresponse.create(sdk/voicelive/azure-ai-voicelive/tests/live/test_live_realtime_tools.py:271-281). Defer these operations until the function-call response completes.
sdk/ai/azure-ai-projects/tests/samples/test_samples.py:390
- This parameterization currently discovers no tests: every synchronous
sample_*.pyinsamples/agents/voiceis present insamples_to_skip. Pytest therefore reports only an empty-parameter skip, so this method provides no sample execution coverage. Add a recording for at least the REST-only samples (or remove the placeholder test until one is runnable).
sdk/ai/azure-ai-projects/tests/samples/test_samples_async.py:320 - This parameterization currently discovers no tests: all three asynchronous
sample_*.pyfiles insamples/agents/voiceare listed insamples_to_skip. The new test is therefore always an empty-parameter skip and exercises no sample. Add a recording for the REST-only basic sample (or remove the placeholder until it is runnable).
- Files reviewed: 75/79 changed files
- Comments generated: 4
- Review effort level: Balanced
| _args, kwargs = fake_session.ws_connect.call_args | ||
| assert _args[0].startswith("wss://my-account.services.ai.azure.com") | ||
| assert kwargs["params"]["api-version"] == "v1" | ||
| assert kwargs["headers"]["Authorization"] == "Bearer fake-token" |
| "sample_voice_agent_live_text_conversation_async.py", | ||
| # Runs until Ctrl-C (continuous microphone capture/playback); would hang indefinitely | ||
| # under this non-interactive runner whenever PyAudio and live credentials are available. | ||
| "sample_voice_agent_live_audio_conversation_async.py", |
| "sample_voice_agent_live_text_conversation_async.py", | ||
| # Runs until Ctrl-C (continuous microphone capture/playback); would hang indefinitely | ||
| # under this non-interactive runner whenever PyAudio and live credentials are available. | ||
| "sample_voice_agent_live_audio_conversation_async.py", |
| conn.conversation.item.create( | ||
| item=RealtimeConversationItemFunctionCallOutput(call_id=event.call_id, output=result) | ||
| ) | ||
| conn.response.create() |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…pupr Resolves conflicts in api.metadata.yml, assets.json, and docs/public-methods.md. Since main already shipped 2.6.0 without Voice Agents, retargets Voice Agents work to a new 2.7.0b1 (beta) CHANGELOG section / package version instead of folding it into the already-released 2.6.0 section, leaving main's 2.6.0 CHANGELOG content and all prior versions untouched. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
Preview opt-in, realtime response sequencing, and executable test-coverage issues remain unresolved.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (8)
sdk/ai/azure-ai-projects/CHANGELOG.md:9
.agents.update()was removed from this package; the existing changelog explicitly directs users tocreate_version()instead (CHANGELOG.md:406-407). Referring to anupdateflow here sends users to a nonexistent API.
* Added guided authoring via `project_client.agents.generate_agent(GenerateVoiceAgentRequest(kind=AgentKind.VOICE, ...))`, which returns a service-generated starter definition that can be edited afterward through the standard `create_version`/`update` flow.
sdk/ai/azure-ai-projects/azure/ai/projects/_patch.py:269
- This top-level preview entry point bypasses the client's explicit preview opt-in.
allow_previewdefaults toFalse, butRealtime.connect()defaultsfoundry_featurestoVoiceAgents=V1Previewand the connection manager always sends that header, soclient.realtime.connect(...)opts in even when the caller did not. Gate this property/connection onself._config.allow_preview, or omit the preview header unless the client was opted in.
@property
def realtime(self) -> Realtime:
"""Realtime streaming entry point for voice agents.
:return: The realtime namespace, exposing ``connect(...)``.
:rtype: ~azure.ai.projects.Realtime
"""
if self._realtime is None:
self._realtime = Realtime(self)
return self._realtime
sdk/ai/azure-ai-projects/azure/ai/projects/aio/_patch.py:215
- The async realtime entry point also bypasses the client's explicit preview opt-in:
AsyncRealtime.connect()suppliesVoiceAgents=V1Previewunconditionally, even whenallow_preview=False. Make the async path enforce the same opt-in contract as the other top-level preview APIs.
@property
def realtime(self) -> AsyncRealtime:
"""Realtime streaming entry point for voice agents.
:return: The realtime namespace, exposing ``connect(...)``.
:rtype: ~azure.ai.projects.aio.AsyncRealtime
"""
if self._realtime is None:
self._realtime = AsyncRealtime(self)
return self._realtime
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_live_function_tool.py:129
response.function_call_arguments.donecompletes the arguments, but the current response is still active until its subsequentresponse.done. Startingresponse.create()here can be rejected as a concurrent response; the repository's VoiceLive flow waits forresponse.donebefore adding the tool output and creating the follow-up response (sdk/voicelive/azure-ai-voicelive/tests/live/test_live_realtime_tools.py:271-281). Defer the output/follow-up until that event.
sdk/ai/azure-ai-projects/tests/agents/test_voice_agent_telephony.py:33- Every test in this new module is unconditionally skipped, so none of the advertised telephony, transfer-target, or generated-audio behavior is exercised in CI. Please add transport-mocked/recorded coverage for request serialization and response handling, or defer these tests until they can run.
sdk/ai/azure-ai-projects/tests/agents/test_voice_agent_telephony_async.py:33 - Every async test in this new module is unconditionally skipped, so the async telephony and generated-audio paths receive no executable coverage. Please add transport-mocked/recorded cases or defer these placeholders until they can run.
sdk/ai/azure-ai-projects/tests/samples/test_samples.py:409 - This blacklist excludes every synchronous
sample_*.pycurrently present undersamples/agents/voice, so parametrization produces no runnable cases and this test adds no sample coverage. Record the REST-only samples (or otherwise provide executable fixtures) and remove them from this list.
sdk/ai/azure-ai-projects/tests/samples/test_samples_async.py:328 - These entries, together with the WebSocket skip above, exclude all three asynchronous voice samples, leaving this parametrized test with zero runnable cases. Add a recording/fixture for the REST-only sample and stop skipping it so the async sample suite exercises at least one new sample.
- Files reviewed: 77/81 changed files
- Comments generated: 3
- Review effort level: Balanced
| conn.conversation.item.create( | ||
| item=RealtimeConversationItemFunctionCallOutput(call_id=event.call_id, output=result) | ||
| ) | ||
| conn.response.create() |
| await conn.conversation.item.create( | ||
| item=RealtimeConversationItemFunctionCallOutput(call_id=event.call_id, output=result) | ||
| ) | ||
| await conn.response.create() |
| 3) FOUNDRY_VOICE_CONVERSATION_ID - The id of a persisted conversation | ||
| (captured from the `conversation.created` event during a live session, | ||
| see sample_voice_agent_live_audio_conversation_async.py). |
There was a problem hiding this comment.
🔵 Needs a closer look
Unresolved moderate issues affect public API usability, sample execution, documentation, and telephony test coverage.
Review details
Suppressed comments (8)
eng/tools/azure-sdk-tools/azpysdk/samples.py:93
- This ignore list omits
sample_voice_agent_live_function_tool.py. That sample also opens a realclient.realtimeWebSocket (and the package sample suite skips it for that reason), so the azpysdk sample check will execute it non-interactively and attempt a live connection. Add it beside the other realtime samples.
"sample_voice_agent_live_text_conversation.py",
"sample_voice_agent_live_text_conversation_async.py",
scripts/devops_tasks/test_run_samples.py:95
- This runner has the same missing exclusion for
sample_voice_agent_live_function_tool.py. Since that sample requires an uncaptured live WebSocket, running it in this non-interactive sample job will fail instead of exercising a replayable sample.
"sample_voice_agent_live_text_conversation.py",
"sample_voice_agent_live_text_conversation_async.py",
sdk/ai/azure-ai-projects/.env.template:27
- This comment is inaccurate:
foundry_voice_model_nameis also consumed by the conversation setup, telephony tests, and realtime live tests, not only the CRUD tests. Update it so contributors know which tests require this environment variable.
# Read by the recorded voice-agent CRUD tests only (tests/test_base.py), not by any sample.
FOUNDRY_VOICE_MODEL_NAME=
sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/init.py:22
- The async
VoiceAgentWebSocketOperationsexport has no correspondingAIProjectClient.voice_agent_web_socketattribute either, despite the generated class directing users there. Remove this unusable public surface or expose a functional async operation group consistently with the intendedasync_client.realtimeAPI.
from ._operations import VoiceAgentWebSocketOperations # type: ignore
sdk/ai/azure-ai-projects/azure/ai/projects/operations/init.py:22
VoiceAgentWebSocketOperationsis exported as public API, butAIProjectClientnever creates the documentedvoice_agent_web_socketattribute; the supported implementation isclient.realtime. Users following this generated operation class's documentation therefore getAttributeError. Hide this generated WebSocket operation group or wire it to a usable client surface consistently.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_read_conversation.py:29- This instruction names a
conversation.createdevent, but the referenced live sample obtains the ID fromRealtimeServerEventSessionCreated(session.created). Following the current text leaves users waiting for an event this client does not handle; point them tosession.createdinstead.
sdk/ai/azure-ai-projects/tests/agents/test_voice_agent_telephony.py:37 - Every test in this newly added module is unconditionally skipped, so the sync telephony and generated-audio APIs receive no executable functional coverage. Before this feature is merged, add transport-mocked/recorded coverage that runs in CI (or enable these tests once the routes are available); placeholder tests cannot detect regressions.
sdk/ai/azure-ai-projects/tests/agents/test_voice_agent_telephony_async.py:37 - Every test in this newly added async module is unconditionally skipped, so the async telephony and generated-audio APIs receive no executable functional coverage. Before this feature is merged, add transport-mocked/recorded coverage that runs in CI (or enable these tests once the routes are available); placeholder tests cannot detect regressions.
- Files reviewed: 77/81 changed files
- Comments generated: 0 new
- Review effort level: Balanced
Regenerate from azure-rest-api-specs commit b538ac90619e094630e3c773d5231070809caf48 and wire preview headers for sync and async agent telephony operations. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🔵 Needs a closer look
Broad preview SDK changes retain unresolved realtime URL-encoding and sample-correctness issues.
Review details
Suppressed comments (4)
sdk/ai/azure-ai-projects/docs/public-methods.md:15
- The new
agent_endpoint_conversationsandagent_telephonymethods are counted as stable solely because they are top-level, but this PR identifies voice agents as preview and gates these calls onVoiceAgents=V1Preview/allow_preview. Calling all 97 methods “stable” misstates their support status; updateGeneratePublicMethods.ps1to distinguish top-level placement from API stability, then regenerate this document.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_live_text_conversation.py:30 - The setup command omits
python-dotenv, although this sample importsdotenvbelow. In a clean environment following these instructions, the sample fails before it can run.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_live_text_conversation_async.py:27 - The setup command omits
python-dotenv, although this sample importsdotenvbelow. In a clean environment following these instructions, the sample fails before it can run.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_read_conversation.py:29 - The referenced live-audio sample reads this ID from
RealtimeServerEventSessionCreated, whose wire event issession.created; it does not capture aconversation.createdevent. Naming the wrong event sends users looking for an event the example never handles.
- Files reviewed: 79/83 changed files
- Comments generated: 5
- Review effort level: Balanced
| base = endpoint.rstrip("/") | ||
| if base.startswith("https://"): | ||
| base = "wss://" + base[len("https://") :] | ||
| return f"{base}/agents/{agent_name}/endpoint/protocols/voice" |
| base = endpoint.rstrip("/") | ||
| if base.startswith("https://"): | ||
| base = "wss://" + base[len("https://") :] | ||
| return f"{base}/agents/{agent_name}/endpoint/protocols/voice" |
| project_client.agents.create_version( | ||
| agent_name=agent_name, | ||
| definition=VoiceAgentDefinition( | ||
| model_type=definition.model_type, # type: ignore[attr-defined] | ||
| model=definition.model, # type: ignore[attr-defined] | ||
| instructions=definition.instructions, # type: ignore[attr-defined] | ||
| store=True, | ||
| ), | ||
| ) |
| await project_client.agents.create_version( | ||
| agent_name=agent_name, | ||
| definition=VoiceAgentDefinition( | ||
| model_type=definition.model_type, # type: ignore[attr-defined] | ||
| model=definition.model, # type: ignore[attr-defined] | ||
| instructions=definition.instructions, # type: ignore[attr-defined] | ||
| store=True, | ||
| ), | ||
| ) |
| FOUNDRY_PROJECT_ENDPOINT= | ||
| FOUNDRY_PROJECT_API_KEY= | ||
| FOUNDRY_MODEL_NAME= | ||
| # Read by the recorded voice-agent CRUD tests only (tests/test_base.py), not by any sample. |
Description
Please add an informative description that covers that changes made by the pull request and link all relevant issues.
If an SDK is being regenerated based on a new API spec, a link to the pull request containing these API spec changes should be included above.
All SDK Contribution checklist:
General Guidelines and Best Practices
Testing Guidelines