[Do not merge][Debug] Preview for voiceagent - #48484
[Do not merge][Debug] Preview for voiceagent#48484xitzhang (xitzhang) wants to merge 57 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.
This comment has been minimized.
This comment has been minimized.
- Fix RST bullet-list continuation-line indentation in VoiceAudioOutputConfig (types.py + models/_models.py) and VoiceConversationStatus (models/_enums.py), fixing sphinx -W docs build failure (3 docutils warnings -> 0) - Fix generate_agent single-overload merge + VoiceResponse Optional-narrowing (previously fixed, re-dropped by main merge, now re-fixed) -- resolved 4 of 12 pyright errors - Fix begin_create_optimization_job/begin_create_generation_job job parameter type in _patch_agents.py, _patch_datasets.py, _patch_evaluators.py (+ async): was typed as generic JSON alias, but generated base class expects the specific _types.<Job> TypedDict -- resolves remaining pyright/mypy arg-type and override-incompatible errors - Re-add all corresponding PostEmitter.ps1 fixes so they survive future regens - Verified CI-exact clean: pyright 0 errors, mypy (--ignore-missing-imports) 0 errors, pylint (repo pylintrc) 10.00/10
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 59 out of 64 changed files in this pull request and generated no new comments.
Suppressed comments (8)
sdk/ai/azure-ai-projects/PostEmitter.ps1:73
- The generated method must always return an SSE byte stream, but this replacement honors
stream=False. A caller passingstream=Falsenow takes the non-streamingSessionLogEventdeserialization path, contradicting the comment and breaking the sample contract. Consume the caller value to avoid the duplicate keyword, but set_streamtoTrueunconditionally in both generated files.
if ($inFunc -and $lines[$i] -match '^\s*_stream = (True|kwargs\.pop\(.+\))\s*$') {
$indent = ([regex]::Match($lines[$i], '^\s*')).Value
$lines[$i] = $indent + '_stream = kwargs.pop("stream", True)'
sdk/ai/azure-ai-projects/PostEmitter.ps1:33
- This step does not remove the unusable operation group from the public surface: both
operations/__init__.pyfiles still import it and include it in__all__, andapi.mdstill exposesVoiceAgentWebSocketOperations.connect_voice_agent. Remove those exports/mappings as part of this post-generation customization; otherwise users can still import the operation that this block says must not be public.
This issue also appears on line 71 of the same file.
# Remove the generated `voice_agent_web_socket` operation group from the client's public surface
# entirely (import, docstring, and __init__ assignment). The generated operation only performs a
# plain HTTP GET (no WebSocket upgrade handshake) and discards the connection - it's not a usable
# client and was never meant to be public (the real voice-agent WebSocket client is `.realtime`).
$files = 'azure\ai\projects\_client.py', 'azure\ai\projects\aio\_client.py'
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_live_audio_conversation_async.py:190
- Bumping
_playback_basedoes not discard theremainingbytes already removed from the queue. The callback emitsremainingbefore checking sequence numbers, so barge-in can continue playing the current buffered chunk despite the stated immediate-stop behavior. Track the sequence associated withremaining(or clear it through thread-safe shared state) whenskip_pending_audio()runs.
sdk/ai/azure-ai-projects/pyproject.toml:48 - The
realtimeextra only installs the sync transport. The newly exposed async realtime client lazily importsaiohttpand otherwise raises at connection time, sopip install azure-ai-projects[realtime]does not install everything needed for the feature. Includeaiohttpin this extra (the repository'sazure-core[aio]convention usesaiohttp>=3.0).
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_live_text_conversation.py:182 _RESPONSE_TIMEOUTis never applied here:pump()iterates untilresponse.doneor an error and can block forever if the service stops producing events without closing the socket. The async counterpart enforces this 45-second limit. Add equivalent bounded receive behavior for the sync path instead of callingpump()without a timeout.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_live_function_tool.py:88- The 45-second timeout declared above is never used by this receive loop. If the server neither emits a terminal event nor closes the socket, the sample hangs indefinitely. Apply a bounded receive/turn timeout, as the async live-text sample does.
sdk/ai/azure-ai-projects/azure/ai/projects/_patch.py:264 - The public
client.realtimesurface and its hand-written sync/async WebSocket connection logic are not exercised anywhere undertests/; the added tests only cover HTTP CRUD and header injection. Add unit tests with fake WebSocket transports for URL/query construction, authentication and preview headers, event serialization/deserialization, connection closure, and sync/async error paths before exposing this transport.
@property
def realtime(self) -> Realtime:
sdk/ai/azure-ai-projects/.env.template:26
- The new samples read
FOUNDRY_VOICE_MODEL, while this template only definesFOUNDRY_VOICE_MODEL_NAME. Users following the template will have their configured deployment silently ignored and the samples will fall back togpt-realtime. Add the sample-facing variable as well (the_NAMEform is still needed by the test preparer).
FOUNDRY_VOICE_MODEL_NAME=
This comment has been minimized.
This comment has been minimized.
…archy) - VoiceMessageItem class and VoiceConversationItemType enum removed; voice conversation item classes (VoiceSystemMessageItem, VoiceUserMessageItem, VoiceAssistantMessageItem, VoiceFunctionCallItem, VoiceFunctionCallOutputItem, VoiceMcp*Item) now extend the corresponding OpenAI Realtime conversation-item classes directly. VoiceConversationItem is now a Union type alias instead of a model class. - New RealtimeConversationItem, RealtimeConversationItemMessage(System/User/Assistant), RealtimeConversationItemFunctionCall(Output), RealtimeMCPListTools, RealtimeMCPToolCall, RealtimeMCPApprovalRequest/Response classes and RealtimeConversationItemType enum exposed. - Reapplied PostEmitter.ps1 fixes that failed to auto-apply this run: docstring indentation for VoiceConversationStatus/VoiceAudioOutputConfig, and VoiceResponse id/conversation_id reportIncompatibleVariableOverride type:ignore. - Updated tsp-location.yaml.saved to the new commit hash. Verified: pyright 0 errors, mypy clean, pylint 10.00/10, sphinx docs build succeeds. No sample/test changes needed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| conn.response.create() | ||
| pump() |
| out = remaining[:wanted] | ||
| remaining = remaining[wanted:] |
| @property | ||
| def realtime(self) -> Realtime: |
| | Sessions | [Manage hosted sessions](https://learn.microsoft.com/azure/foundry/agents/how-to/manage-hosted-sessions?pivots=python) | `samples/hosted_agents/` | | ||
| | Skills (preview) | | `samples/skills/` | | ||
| | Toolboxes | [Curate intent-based toolbox in Foundry](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/toolbox?pivots=python) | `samples/hosted_agents/`, `samples/toolboxes/` | | ||
| | Voice agents (preview) | [Use the GPT Realtime API for speech and audio](https://learn.microsoft.com/azure/foundry/openai/how-to/realtime-audio) | `samples/agents/voice/` | |
[Pilot] PR Pipeline Failure AnalysisWhat failedPipeline: azure-sdk/public build #6732020 — failed Check: Pyright static type check for Three type errors were found in the new voice agent sample files under
Note: Relevant pipeline outputRecommended next steps
Automated fix: Requested
|
… opt-in, session file IO[bytes] uploads) - Add foundry_features_query opt-in parameter (_AgentDefinitionOptInKeys.VOICE_AGENTS_V1_PREVIEW) to the voice agent WebSocket connect operation - Widen AgentsOperations.upload_session_file to accept IO[bytes] in addition to bytes - Simplify several create/patch body overloads to Union[JSON, IO[bytes]], dropping now-unused typed-dict overloads - Reword output_modalities docstring - Bump version to 2.6.0 and update CHANGELOG Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Copilot resolve the merge conflicts in this pull request |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 58 out of 62 changed files in this pull request and generated 7 comments.
Suppressed comments (7)
sdk/ai/azure-ai-projects/pyproject.toml:48
- The
realtimeextra installs onlywebsockets, butasync_client.realtimerequiresaiohttp, which is not a package dependency. A cleanazure-ai-projects[realtime]installation therefore supports the sync API but fails when opening an async realtime connection.
sdk/ai/azure-ai-projects/azure/ai/projects/aio/_patch.py:84 - If callers provide an immutable headers mapping, this fallback replaces it with a one-entry dictionary and silently drops every caller-supplied header. Preserve the original mapping while adding
Accept-Encodingso correlation, conditional, and custom headers still reach the request.
try:
headers[_ACCEPT_ENCODING_HEADER_NAME] = _ACCEPT_ENCODING_IDENTITY_VALUE
except Exception: # pylint: disable=broad-except
kwargs["headers"] = {_ACCEPT_ENCODING_HEADER_NAME: _ACCEPT_ENCODING_IDENTITY_VALUE}
sdk/ai/azure-ai-projects/PostEmitter.ps1:73
- This pops the keyword but still honors
stream=False, contradicting the stated requirement that this SSE operation must always stream. A caller passingstream=Falsewill restore the buffered-response path and can break the iterator contract; consume the caller value and then set_stream = Trueunconditionally.
if ($inFunc -and $lines[$i] -match '^\s*_stream = (True|kwargs\.pop\(.+\))\s*$') {
$indent = ([regex]::Match($lines[$i], '^\s*')).Value
$lines[$i] = $indent + '_stream = kwargs.pop("stream", True)'
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_live_audio_conversation_async.py:146
- Barge-in does not actually discard a partially consumed chunk: these lines play
remainingbefore consulting any sequence number, whileskip_pending_audio()only advances_playback_base. If a delta is larger than one callback buffer, its remainder continues playing after speech starts. Track the sequence associated withremaining(or clear it through a thread-safe signal) before emitting these bytes.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_live_text_conversation.py:67 _RESPONSE_TIMEOUTis never used:pump()iterates until a terminal event, so a live connection that produces noresponse.donecan block this interactive sample indefinitely despite the documented 45-second limit. Apply the timeout to receive/pump or remove the misleading guarantee.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_live_function_tool.py:56- This timeout constant is unused; the subsequent
for event in connhas no deadline and can hang forever if the service never emits a final event. Wire the timeout into the sync receive loop rather than advertising a limit that is not enforced.
sdk/ai/azure-ai-projects/CHANGELOG.md:17 - The dependency note says
websocketsis required for both entry points, but the async implementation usesaiohttp. Update this entry together with therealtimeextra so the release notes describe both transport dependencies accurately.
* Added an optional dependency on `websockets`, required only when using the new `client.realtime` / `async_client.realtime` voice agent streaming APIs.
…pupr # Conflicts: # sdk/ai/azure-ai-projects/CHANGELOG.md # sdk/ai/azure-ai-projects/assets.json Co-authored-by: xitzhang <11403681+xitzhang@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 57 out of 61 changed files in this pull request and generated 5 comments.
Suppressed comments (10)
sdk/ai/azure-ai-projects/pyproject.toml:48
- The
realtimeextra installs onlywebsockets, butasync_client.realtimeimportsaiohttpand raises at runtime when it is absent (aio/_realtime.py:690-695). Installing the advertised extra therefore does not make the async API usable; include its runtime dependency.
sdk/ai/azure-ai-projects/azure/ai/projects/aio/_patch.py:84 - When callers supply an immutable header mapping, this fallback replaces it with a dictionary containing only
Accept-Encoding, silently dropping authorization, tracing, and other custom headers. Copy the original mapping before adding the workaround header.
elif not _has_header_case_insensitive(headers, _ACCEPT_ENCODING_HEADER_NAME):
try:
headers[_ACCEPT_ENCODING_HEADER_NAME] = _ACCEPT_ENCODING_IDENTITY_VALUE
except Exception: # pylint: disable=broad-except
kwargs["headers"] = {_ACCEPT_ENCODING_HEADER_NAME: _ACCEPT_ENCODING_IDENTITY_VALUE}
sdk/ai/azure-ai-projects/azure/ai/projects/operations/init.py:17
- This re-exports the generated
VoiceAgentWebSocketOperations, even thoughPostEmitter.ps1:29-32states that this unusable HTTP implementation must be removed from the public surface in favor of.realtime. Update post-generation customization to remove both this import and its__all__entry as well.
from ._operations import VoiceAgentWebSocketOperations # type: ignore
sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/init.py:17
- The async operations package still publicly exports the generated
VoiceAgentWebSocketOperations, contrary toPostEmitter.ps1:29-32, which identifies it as unusable and intended to be removed in favor of.realtime. Remove this import and its__all__entry through the post-generation customization.
from ._operations import VoiceAgentWebSocketOperations # type: ignore
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_live_text_conversation.py:153
_RESPONSE_TIMEOUTis declared but never applied:pump()iterates indefinitely if the service stalls beforeresponse.done, so this interactive sample can hang despite claiming a 45-second timeout. Add timeout support to the sync receive path and enforce it here, matching the async sample.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_live_function_tool.py:88- The advertised 45-second response timeout is unused. If the tool call or final
response.donenever arrives, this loop blocks forever; enforce the timeout through the sync realtime receive API.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_live_audio_conversation_async.py:190 remainingis callback-local and is consumed before the queue is checked, whileskip_pending_audio()only advances_playback_base. After barge-in, a previously dequeued large chunk can therefore continue playing fromremainingeven though all queued sequence numbers were invalidated. Track and invalidate the remainder's sequence (or explicitly clear it through thread-safe shared state) when skipping.
sdk/ai/azure-ai-projects/CHANGELOG.md:10- The changelog advertises a
connection.itemhelper, butRealtimeConnectionexposes items underconnection.conversation.item; following the documented API raisesAttributeError. Correct the public usage guidance.
* Added a new `client.realtime` / `async_client.realtime` entry point for realtime speech-to-speech streaming. Use `with client.realtime.connect(agent_name=...) as connection:` to open a WebSocket connection, `connection.send(...)` to send strongly-typed client events (or use the `connection.response`, `connection.item`, and `connection.session` helpers), and iterate over `connection` to receive strongly-typed server events (`VoiceAgentServerEvent*`, `RealtimeServerEvent*`). The new types `Realtime`, `RealtimeConnection`, and `RealtimeConnectionManager` (and their async equivalents `AsyncRealtime`, `AsyncRealtimeConnection`, `AsyncRealtimeConnectionManager`) are exported from `azure.ai.projects` / `azure.ai.projects.aio`. Requires the optional `websockets` package.
sdk/ai/azure-ai-projects/azure/ai/projects/models/init.py:282
PickPropertiesVoiceAudioConfigexposes a TypeSpec utility-generated implementation detail as a public model name. This is not a meaningful customer-facing type; assign the picked shape a deliberate name upstream or suppress it from the generated public exports.
PickPropertiesVoiceAudioConfig,
sdk/ai/azure-ai-projects/azure/ai/projects/models/init.py:686
- This adds the private
_AgentDefinitionOptInKeysenum to the generated models export list and__all__, turning an underscore-prefixed implementation detail into public API. The realtime implementation already imports it directly from_enums; keep it out ofazure.ai.projects.models.
_AgentDefinitionOptInKeys,
… insights/Microsoft365 publishing, fix beta operation-group restructure
- Regenerate SDK from azure-rest-api-specs commit 2e1e4f1d8a43ce114b3a3532d25a34fe1c2fa915
(voice-agent helper-type Voice*->VoiceAgent* rename pass, new agent-insights and
agents-microsoft365 TypeSpec directories); update tsp-location.yaml.saved accordingly.
- Delete stale types.py (dead TypedDict mirror under generate-typeddict: false that never
reflected current models); retype its 6 dependent _patch_*.py overloads to use the
generated JSON alias instead. Automate this deletion in PostEmitter.ps1 going forward.
- Fix recurring _unions.py forward-ref bug for VoiceAgentSessionResponse/Update in
models/_models.py, now automated as a PostEmitter.ps1 fixup.
- Update _realtime.py/aio/_realtime.py and affected samples/tests for the Voice*->
VoiceAgent*/Realtime* rename pass and removed message-item classes (now sent as raw dicts).
- Handle agent_endpoint_conversations and voice_agent_web_socket moving from top-level
client attributes to nested .beta sub-clients upstream, and the new agent_insight_monitors
beta sub-client:
- Add agent_endpoint_conversations/agent_insight_monitors to _BETA_OPERATION_FEATURE_HEADERS
so they get Foundry-Features header injection via the existing generic mechanism.
- Remove now-dead top-level header-injection code in _patch.py/aio/_patch.py; fix the
accept-encoding-identity workaround to target the new self.beta location (with a
hasattr(self, "beta") guard for tests that mock out the generated __init__ - caught by
running the full test suite).
- Relocate the voice_agent_web_socket hide-from-public-surface PostEmitter.ps1 fixup.
- Update 5 samples' client.agent_endpoint_conversations -> client.beta.agent_endpoint_conversations.
- Update foundry_features_header tests; retire the now-redundant dedicated
agent_endpoint_conversations header tests in favor of the generic beta-operations
discovery test, which now covers it (and agent_insight_monitors) automatically.
- Update docs/public-methods.md (cross-checked against runtime reality) and CHANGELOG.md.
- Regenerate api.md/api.metadata.yml.
- Validated: full test suite (826 passed, 105 skipped, 4 pre-existing unrelated failures
from missing test recordings), plus all 11 voice-agent samples run live end-to-end.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 54 out of 58 changed files in this pull request and generated 7 comments.
Suppressed comments (6)
sdk/ai/azure-ai-projects/pyproject.toml:48
- The
realtimeextra does not installaiohttp, althoughAsyncRealtimeConnectionManager.enter()imports it at runtime. A user installingazure-ai-projects[realtime]can therefore use the sync client but gets aRuntimeErrorfrom the advertised async realtime entry point. Include the async transport dependency in this extra.
sdk/ai/azure-ai-projects/azure/ai/projects/aio/_patch.py:83 - If a caller supplies an immutable header mapping, this fallback replaces the entire mapping with only
Accept-Encoding, silently dropping every caller-provided header. Copy the mapping before adding the forced value so custom headers are preserved.
except Exception: # pylint: disable=broad-except
kwargs["headers"] = {_ACCEPT_ENCODING_HEADER_NAME: _ACCEPT_ENCODING_IDENTITY_VALUE}
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_live_function_tool.py:23
- This sample uses the synchronous realtime WebSocket client, but the installation command omits the
realtimeextra. In a clean environment it fails with the client's “requires websockets” runtime error before demonstrating the tool flow.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_live_text_conversation.py:181 - The declared 45-second response timeout is never applied:
pump()iterates throughconn.recv()with no timeout, so a dropped or stalled response can block this interactive sample indefinitely. Expose/use a timeout-capable sync receive path, analogous to the async sample'sasyncio.wait_for.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_live_function_tool.py:86 _RESPONSE_TIMEOUTis never used, and this iterator waits forever if the service does not emit the expected final event. Apply a bounded receive/iteration timeout so this sample does not hang on a stalled WebSocket response.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_live_audio_conversation_async.py:146- A dequeued audio chunk loses its sequence number once its tail is stored in
remaining. Afterskip_pending_audio()advances_playback_base, the callback copies that stale tail intooutbefore checking any sequence, so barge-in can continue playing the old reply. Track the sequence forremainingand discard it when it predates_playback_base.
| print(f"Agent: {event.transcript}") | ||
|
|
||
| while True: | ||
| prompt = input("You: ").strip() |
| try: | ||
| await asyncio.wait_for(pump(), timeout=_RESPONSE_TIMEOUT) | ||
| except asyncio.TimeoutError: | ||
| print("Timed out waiting for the agent's reply.") |
|
|
||
| while True: | ||
| # input() blocks, so read it off the loop in a worker thread. | ||
| prompt = (await asyncio.to_thread(input, "You: ")).strip() |
| * Added Microsoft 365 agent publishing: | ||
| * `project_client.agents.publish_to_microsoft365(agent_name, publish_scope=...)` publishes a Foundry agent to Microsoft 365 / Microsoft Teams and returns a `Microsoft365PublishResult`. | ||
| * `project_client.agents.get_microsoft365_publish_defaults(agent_name)` returns default and previously-published values (`Microsoft365PublishDefaults`) used to pre-populate a publish request. | ||
| * `project_client.agents.get_microsoft365_package(agent_name)` downloads the Microsoft 365 app package for an agent. | ||
| * Added the supporting `Microsoft365PublishScope`, `Microsoft365PermissionScopes`, `ActivityProtocolAccessBoundary`, `PublishApprovalStatus`, and `DigitalWorkerType` enums. |
…ealtimeConversationItemMessage* classes, fix RecordedTransport.HTTPX2 rename, add voice-agent CRUD recordings - Regenerated from TypeSpec commit 3fe1059cb3bb4d6dc5cf62910c09c47b64a092ad (purely additive vs prior round) - Restored RealtimeConversationItemMessageSystem/User/Assistant classes (previously removed upstream, now reinstated) to the ConversationItem union in _realtime.py/aio/_realtime.py and 3 samples, replacing the raw-dict construction workaround with typed construction - Fixed RecordedTransport.HTTPX -> HTTPX2 in test_voice_agent_crud.py/_async.py (unrelated shared-tooling rename from an upstream merge that broke test collection) - Updated CHANGELOG.md wording and regenerated api.md/api.metadata.yml - Updated tsp-location.yaml.saved to the new commit hash (tsp-location.yaml itself is a transient, untracked local file used only to drive generation, not committed) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
Realtime dependencies, public exports, sample correctness, documentation, and test coverage have unresolved issues.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (6)
sdk/ai/azure-ai-projects/pyproject.toml:48
- The
realtimeextra installs onlywebsockets, butAsyncRealtimeConnectionManagerimportsaiohttpand raises at runtime when it is absent. As a result,pip install azure-ai-projects[realtime]does not make the advertised async realtime API usable. Includeaiohttpin this extra (and update the changelog wording, which currently sayswebsocketsis required for both clients).
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_with_tools.py:73 VoiceAgentDefinition.toolsacceptsVoiceAgentToolinstances, but this sample constructs the separate realtime-session modelRealtimeFunctionTooland suppresses the resulting type error. UseVoiceAgentFunctionToolhere and update the import so the sample demonstrates the supported voice-agent definition API without alist-itemignore.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_live_function_tool.py:126- This agent definition uses
RealtimeFunctionTool, althoughVoiceAgentDefinition.toolsis typed aslist[VoiceAgentTool]; thelist-itemsuppression hides that API mismatch. Replace it withVoiceAgentFunctionTooland update the import so users can copy a type-correct example.
sdk/ai/azure-ai-projects/azure/ai/projects/_patch.py:258 - The new hand-written WebSocket client is exposed publicly here, but there are no tests referencing
client.realtime,RealtimeConnection, or the corresponding async types. Add mocked sync and async transport tests for URL/header construction, event serialization/deserialization, connection closure, and error paths before publishing this transport surface.
@property
def realtime(self) -> Realtime:
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_live_text_conversation.py:68
_RESPONSE_TIMEOUTis never used in this synchronous sample:pump()iterates the connection without a deadline, so a stalled or lost response can block the sample indefinitely. Enforce a deadline here (and expose timeout support fromRealtimeConnection.recvif needed), as the async variant already does withasyncio.wait_for.
sdk/ai/azure-ai-projects/samples/agents/voice/sample_voice_agent_live_function_tool.py:57- This timeout constant is unused, and the subsequent
for event in connhas no deadline. If the service never emits the final event, the sample hangs indefinitely. Enforce this deadline here and add timeout support to the synchronous realtime receive path if necessary.
- Files reviewed: 53/57 changed files
- Comments generated: 5
- Review effort level: Balanced
| FOUNDRY_PROJECT_ENDPOINT= | ||
| FOUNDRY_PROJECT_API_KEY= | ||
| FOUNDRY_MODEL_NAME= | ||
| FOUNDRY_VOICE_MODEL_NAME= |
| @distributed_trace | ||
| def generate_agent(self, body: _models.GenerateVoiceAgentRequest, **kwargs: Any) -> _models.AgentDetails: # type: ignore[override] |
… asset gaps - Fixed genuine bugs found in review: immutable-headers fallback dropping caller headers (aio/_patch.py), connection_url query-delimiter corruption, stream=False defeating a hard-SSE-only operation (PostEmitter.ps1 + regenerated files), audio barge-in not discarding stale buffered chunks, missing aiohttp dependency in the [realtime] extra, missing __all__ exports for beta operation classes, _AgentDefinitionOptInKeys leaking as public API, wrong tool type in 2 samples (RealtimeFunctionTool -> VoiceAgentFunctionTool), 2 samples with interactive input() causing EOFError in the non-interactive sample-check runner (added to IGNORED_SAMPLES in both copies), unused _RESPONSE_TIMEOUT in 2 samples (added real recv(timeout=...) support to the SDK), async sample not cancelling the stale server response after a client-side timeout. - Corrected several stale/inaccurate CHANGELOG.md statements (connection.item -> connection.conversation.item, async transport is aiohttp not websockets). - Added test_generate_agent/_async (recorded) and 37 new transport-mocked unit tests across tests/agents/test_realtime_client.py/_async.py covering URL construction, auth headers, event serialization/dispatch, timeouts, and connection cleanup for the hand-written realtime WebSocket clients. - Fixed a docs generation (sphinx) failure: two docstrings in models/_models.py had un-indented bullet-list continuation lines that docutils flags as warnings-as-errors. Fixed directly and via a new PostEmitter.ps1 fixup so future regenerations don't reintroduce it. - Generated, verified, and pushed recordings for the 4 previously-failing voice-agent CRUD tests plus 2 new generate_agent tests to azure-sdk-assets; updated assets.json's Tag accordingly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
It introduces a breaking module removal, an incomplete credential-origin guard, and unbounded realtime audio scheduling.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
sdk/ai/azure-ai-projects/tsp-location.yaml.saved:2
- This regeneration pins a spec commit associated with Agent Insights (#45971) and also pulls in Agent Insights and Microsoft 365 API changes, while the PR title mentions only voice agents and the description is still the empty template. Update the description to explain the full generated scope and link every relevant azure-rest-api-specs PR so reviewers can validate the bundled API changes.
- Files reviewed: 58/62 changed files
- Comments generated: 3
- Review effort level: Balanced
| $typesFile = 'azure\ai\projects\types.py' | ||
| if (Test-Path $typesFile) { | ||
| Remove-Item $typesFile -Force |
| def test_matching_host_does_not_raise(self): | ||
| _assert_trusted_connection_url(f"wss://{'my-account.services.ai.azure.com'}/custom/path", _ENDPOINT) | ||
|
|
||
| def test_mismatched_host_raises_value_error(self): | ||
| with pytest.raises(ValueError): | ||
| _assert_trusted_connection_url("wss://evil.example.com/steal-token", _ENDPOINT) |
…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", | ||
| ], |
| "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", |
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