Skip to content

[azure-ai-projects] Add Voice Agents realtime client, samples, and tests aligned with .beta structure - #48965

Draft
xitzhang (xitzhang) wants to merge 9 commits into
feature/azure-ai-projects/vnextfrom
xitzhang/voice-agents-beta
Draft

xitzhang (xitzhang) wants to merge 9 commits into
feature/azure-ai-projects/vnextfrom
xitzhang/voice-agents-beta

Conversation

@xitzhang

Copy link
Copy Markdown
Member

Summary

Adds Voice Agents to �zure-ai-projects, aligned with the .beta naming/structure already established on this branch ( eature/azure-ai-projects/vnext picked up the generated Voice Agents surface via #48950). This PR adds the pieces needed to make it a complete, usable feature: the hand-written realtime WebSocket client, samples, tests, and docs.

Related to #47803 (tracking �next -> main). cc Darren Cohen (@dargilco)

What's included

  • client.beta.realtime / �sync_client.beta.realtime: hand-written WebSocket client (Realtime/AsyncRealtime, RealtimeConnection(Manager)) exposed as a property on BetaOperations, exported from �zure.ai.projects.operations / �zure.ai.projects.aio.operations (matching how other .beta-only classes are exported).
  • 11 samples under samples/agents/voice/: CRUD lifecycle, guided generation (.beta.agents.generate), versioning, tools, live text/audio conversations, function-tool calling, and reading back persisted conversations/audio via .beta.agent_endpoint_conversations.
  • 14 test files under ests/agents/ and ests/foundry_features_header/: CRUD, telephony, telephony campaigns, conversations, realtime client (mocked + live), and telephony protocol tests.
  • Test infra: conftest.py sanitizers, est_base.py env var, and a NON_OPERATION_BETA_ATTRIBUTES exclusion in the generic .beta header-injection test (
    ealtime is a hand-written WebSocket entry point, not a generated REST operation, so it needs its own dedicated header test instead -- see est_realtime_client.py).
  • PostEmitter.ps1: regression guard so a future sp-client update can't silently overwrite _realtime.py's SDK client-identification fix (Add Voice Live SDK client identification #48848) without failing the emit step.
  • pyproject.toml: optional
    ealtime extra (websockets / �iohttp).
  • CHANGELOG.md, README.md, .env.template, dev_requirements.txt updated.

Renames applied while porting

This branch's TypeSpec commit turned out to be newer than the source content this was ported from, and had renamed several methods beyond just .beta nesting (verified against this branch's own generated code and docs/public-methods.md):

  • �gent_endpoint_conversations: dropped the �gent_conversation infix and renamed content methods to download (e.g. get_agent_conversation_item -> get_item, get_agent_conversation_item_audio_content -> download_item_audio).
  • �gent_telephony: dropped the redundant elephony_ infix (e.g. create_telephony_call_job -> create_call_job, �egin_validate_telephony_campaign -> �egin_validate_campaign).
  • �gents.generate_agent -> �gents.generate, and telephony binding/call methods moved from top-level client.agents to client.beta.agents.

Validation

  • �lack / pylint / mypy / pyright: all clean.
  • Full test suite: 219 passed / 74 skipped / 0 failed outside voice; voice + header suite 732 passed / 49 skipped / 8 failed -- all 8 failures are brand-new tests with no recording yet (not a regression; this package's convention is to keep new tests enabled so PR validation surfaces missing recordings).
  • Live end-to-end tested all 11 samples against a real Foundry project with a real gpt-realtime deployment: real HTTP status codes for REST CRUD, real multi-turn realtime conversations with byte-accurate audio sizing (format/sample-rate/channels/duration), real function-tool invocation (verified get_weather called and incorporated into the reply), and real conversation/audio persistence + readback.

…ta structure

feature/azure-ai-projects/vnext already has the generated Voice Agents surface
(.beta.agent_endpoint_conversations, .beta.agent_telephony, .beta.agents
telephony binding/call/generate methods, .beta.voice_agent_web_socket) via
PR #48950. This change adds the missing hand-written realtime WebSocket
client and the surrounding samples/tests/docs to make Voice Agents a complete,
usable feature, all under the .beta naming convention:

- azure/ai/projects/_realtime.py and aio/_realtime.py: hand-written realtime
  WebSocket client (Realtime/AsyncRealtime, RealtimeConnection(Manager)),
  exposed as client.beta.realtime / async_client.beta.realtime via a new
  property on BetaOperations. Exported from azure.ai.projects.operations /
  azure.ai.projects.aio.operations (not the top-level package), matching how
  other .beta-only classes are exported.
- 11 samples under samples/agents/voice/: CRUD lifecycle, guided generation,
  versioning, tools, live text/audio conversations, function-tool calling,
  and reading back persisted conversations/audio.
- 14 test files under tests/agents/ and tests/foundry_features_header/:
  CRUD, telephony, telephony campaigns, conversations, realtime client
  (mocked + live), and telephony protocol tests.
- Supporting test infra: conftest.py Foundry-Features/Accept sanitizers,
  test_base.py foundry_voice_model_name, and a NON_OPERATION_BETA_ATTRIBUTES
  exclusion in the generic .beta header-injection test (realtime is a
  hand-written WebSocket entry point, not a generated REST operation, so it
  can't be exercised by that generic mechanism -- it has its own dedicated
  header test in test_realtime_client.py).
- PostEmitter.ps1: regression guard so a future tsp-client update can't
  silently overwrite _realtime.py's SDK client-identification fix (PR #48848)
  without failing the emit step.
- pyproject.toml: optional 
ealtime extra (websockets / aiohttp).
- CHANGELOG.md, README.md, .env.template, dev_requirements.txt updated.

Renames applied while porting (vnext's TypeSpec commit is newer than the
source branch this was ported from, and renamed several methods beyond just
.beta nesting -- verified against vnext's own generated code and
docs/public-methods.md):
- agent_endpoint_conversations: dropped the "agent_conversation" infix and
  renamed *_content methods to download_* (e.g. get_agent_conversation_item
  -> get_item, get_agent_conversation_item_audio_content ->
  download_item_audio).
- agent_telephony: dropped the redundant "telephony_" infix (e.g.
  create_telephony_call_job -> create_call_job, begin_validate_telephony_campaign
  -> begin_validate_campaign).
- agents.generate_agent -> agents.generate, and telephony binding/call
  methods moved from top-level client.agents to client.beta.agents.

Validated: black/pylint/mypy/pyright all clean. Full test suite: 219
passed/74 skipped/0 failed outside voice; voice+header suite 732 passed/49
skipped/8 failed (all 8 are brand-new tests with no recording yet, not a
regression). Live-tested all 11 samples end-to-end against a real Foundry
project with a real gpt-realtime deployment: real HTTP status codes, real
multi-turn realtime conversations with byte-accurate audio sizing, real
function-tool invocation, and real conversation/audio persistence+readback.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-pipelines

Copy link
Copy Markdown
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.

@github-actions

This comment has been minimized.

Comment thread sdk/ai/azure-ai-projects/PostEmitter.ps1 Outdated
Comment thread sdk/ai/azure-ai-projects/pyproject.toml Outdated
model=model,
instructions="You are a friendly voice assistant. Keep replies short and natural.",
audio=VoiceAgentAudioConfig(
output=VoiceAgentAudioOutputConfig(voice="en-US-AvaNeural", voice_type=VoiceType.AZURE_STANDARD),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Regarding voice="en-US-AvaNeural" I expected to see a selection from an enum instead of writing a string. Do we defined all voices as a union in TypeSpec? If not, why?

@xitzhang xitzhang (xitzhang) Sep 10, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I checked the generated model: voice is intentionally Optional[str], while voice_type is already an extensible VoiceType enum. I think service added this is also to avoid unnecessary API version changes when voices are added or removed. Since this comes from TypeSpec, we can revisit it at the spec level if needed.

DefaultAzureCredential() as credential,
AIProjectClient(endpoint=endpoint, credential=credential, allow_preview=True) as project_client,
):
agent = project_client.beta.agents.generate(GenerateVoiceAgentRequest(kind=AgentKind.VOICE, name=agent_name))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

".agents.generate" is a too generic name. We'll see where it lands in our sub-client discussions. Depending on what sub-client it's on, we may or may not need a more descriptive name. If it's ".beta.voice-agent.generate" then the name is probably okay.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Also can we eliminate kind as parameter?

@xitzhang xitzhang (xitzhang) Sep 10, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Makes sense -- this one's out of my hands in this PR though: .beta.agents.generate is already the shape that landed in the generated code this branch picked up (from #48950). I’ll summarize the fixes related to the TypeSpec.

@xitzhang xitzhang (xitzhang) Sep 11, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Also can we eliminate kind as parameter?

Given the design goal of generate, Dan’s view is that it shouldn’t be limited to voice and may support broader generative scenarios in the future. Since generate is intended as a simple way to deploy different kinds of agents, it may make sense to keep kind here.

DefaultAzureCredential() as credential,
AIProjectClient(endpoint=endpoint, credential=credential, allow_preview=True) as project_client,
):
agent = project_client.beta.agents.generate(GenerateVoiceAgentRequest(kind=AgentKind.VOICE, name=agent_name))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Also can we eliminate kind as parameter?

# definition as-is (instead of reconstructing a new one from a few fields) so audio,
# greeting, tools, and any other service-selected settings are preserved.
definition.store = True # type: ignore[attr-defined]
project_client.agents.create_version(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

should create_version internally calls generate, and make generate private?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good question! I'd keep them separate — generate is for AI-assisted scaffolding, create_version needs to stay generic across all agent kinds. Also I will use create agent api here, not generate and change version. Will update samples

Comment thread sdk/ai/azure-ai-projects/azure/ai/projects/_realtime.py Outdated
Comment thread sdk/ai/azure-ai-projects/azure/ai/projects/_realtime.py Outdated
api_version: Optional[str] = None,
credential_scopes: Optional[List[str]] = None,
extra_query: Optional[Mapping[str, str]] = None,
extra_headers: Optional[Mapping[str, str]] = None,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Darren Cohen (@dargilco) should extra headers and extra query part of kwargs for our standard?

Review feedback fixes:
- CSpell: add "redef" to sdk/ai/cspell.yaml (fixes CI failure on the
  type: ignore[no-redef] comment in
  sample_voice_agent_live_audio_conversation_async.py).
- PostEmitter.ps1: remove the _realtime.py regression guard -- verified
  empirically (ran a real tsp-client update against the pinned commit; the
  hand-written files came back byte-identical) that tsp-client update does
  not touch files it doesn't generate, so the guard was unnecessary.
- pyproject.toml: rename the "realtime" optional-dependency extra to
  "voice" (matches how it'll be documented for voice agents); update the
  2 samples that referenced [realtime] to [voice].
- Samples: pin azure-ai-projects>=2.7.0 (drop the b1/--pre prerelease
  pins -- this package no longer ships beta releases) across all 11 voice
  samples; use the [voice] extra instead of manually listing aiohttp in
  the 2 samples that need it.
- _realtime.py / aio/_realtime.py:
  - Remove the foundry_features parameter from
    RealtimeConnectionManager/Realtime.connect/AsyncRealtime.connect --
    the realtime route is voice-agent-specific, so the header value is
    always the same and callers should not need (or be able) to override
    it. The value is now a hardcoded module constant.
  - Fix structured_inputs' type: it was Optional[str], silently requiring
    callers to pre-serialize their own JSON string with no documentation
    of the expected shape. Retyped to Optional[Mapping[str, Any]],
    matching the analogous generated model field
    (CreateTelephonyCallJobRequest.structured_inputs: dict[str, any]),
    and now serialized internally via SdkJSONEncoder.
  - Updated test_realtime_client.py/_async.py's _make_manager() helpers
    to match (foundry_features removed; the header-value assertions still
    pass since it's now a module constant rather than a per-call override).

Test recordings:
- Generated live recordings for the 8 new voice-agent tests that had none
  yet (test_voice_agent_crud(_async).py x6, test_read_conversation(_async)
  x2), against a real Foundry project with a real gpt-realtime deployment.
  Verified sanitization (endpoint/auth stripped) and re-verified end-to-end
  in playback mode after a fresh assets restore from the new tag.
- Pushed the new recordings to Azure/azure-sdk-assets (tag
  python/ai/azure-ai-projects_59c7584f68) via the GitHub Git Data REST API,
  since a direct git push to that repo hangs in this environment; updated
  assets.json accordingly.

Validated: black/pylint/mypy clean; full existing test suite unaffected
(740 passed, 49 skipped, 0 failed, up from 732 passed/8 failed).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@glharper Glenn Harper (glharper) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Comments 2-6 from the local review, checked against the current PR revision.

Comment thread sdk/ai/azure-ai-projects/azure/ai/projects/_realtime.py Outdated
Comment thread sdk/ai/azure-ai-projects/azure/ai/projects/_realtime.py Outdated
Comment on lines +201 to +204
except TimeoutError:
print("Timed out waiting for the agent's reply.")
conn.response.cancel()
return

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

5. [P2] Drain a cancelled response before accepting the next text turn

After a reply times out, the samples send response.cancel() and return to prompting without consuming the cancelled response's terminal event. The next turn's event pump returns on any RealtimeServerEventResponseDone, without matching the response ID. A late completion for the cancelled turn therefore ends the next turn's pump before the new reply is displayed, leaving the stream out of step with the user. The same issue exists in the async text sample.

Evidence: Deterministic sync and async runs supplied a first-turn timeout, the first response's cancelled response.done, and the second response's transcript/completion. Both issued two response requests but failed to display the second reply; the async run left its transcript and completion unread.

Suggested fix: Consume cancellation through the matching terminal event before reusing the stream, and correlate completion events with the active response ID. If cancellation cannot be confirmed within a bounded wait, end the session rather than accept another turn on an unsynchronized stream. Apply the same handling to the async greeting-timeout path.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed in both the sync and async samples (including the async greeting-timeout path). Each turn now tracks its response id from response.created, and after a timeout+cancel, a new bounded drain step consumes that response's terminal event (correlated by id) before the next turn starts — so a late completion can no longer be mistaken for the next turn's reply. If it can't be confirmed in time, the sample now ends the session cleanly instead of continuing on a stream it can't trust.

Comment on lines +224 to +226
except HttpResponseError as e:
if e.status_code == 404:
continue

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

6. [P2] Require a successful per-item audio retrieval in the conversation tests

Both tests tolerate every per-item audio request returning 404 without requiring a single successful audio retrieval. Their setup requests a stored audio response and requires a completed conversation with a merged recording, but a broken per-item audio route can still pass the test without ever reaching download_item_audio(). Recording that behavior would preserve the false-positive result in playback. The same issue exists in the async test.

Evidence: Running both unchanged test bodies with mocked completed conversations containing user and assistant-audio items passed despite two item-audio 404s and zero item-audio download calls in each run. This reproduction bypassed live setup and recording decorators; it did not contact the service.

Suggested fix: Continue tolerating 404 for genuinely non-audio items, but require at least one successful audio-item metadata retrieval and a nonempty download for Foundry-managed storage.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed in both the sync and async test — now tracks whether any item successfully retrieved audio and asserts that after the loop, so a fully-broken get_item_audio/download_item_audio route can no longer pass silently.

Xiting Zhang and others added 6 commits September 10, 2026 19:40
…nt samples to use create_version directly

- _realtime.py / aio/_realtime.py: send structured_inputs as the documented
  structured_input query parameter instead of a custom header; distinguish
  graceful WebSocket closure from abnormal closure/transport errors so
  `for event in conn:` no longer silently swallows real failures.
- sample_voice_agent_live_audio_conversation_async.py: always clear buffered
  local playback audio on barge-in, independent of whether a server response
  is still active.
- sample_voice_agent_live_text_conversation.py / _async.py: drain a cancelled
  response's terminal event (correlated by response id) before starting the
  next turn, so a late completion can't be mistaken for the next reply.
- test_voice_agent_conversations.py / _async.py: require at least one
  successful per-item audio retrieval instead of tolerating an all-404 run.
- test_realtime_client.py / _async.py: add regression tests for the
  structured_input query parameter and the graceful-vs-abnormal closure
  distinction.
- sample_voice_agent_live_audio_conversation_async.py, sample_voice_agent_live_text_conversation.py,
  sample_voice_agent_live_text_conversation_async.py: replace the generate()-then-patch-store
  two-step pattern with a single direct VoiceAgentDefinition(..., store=True) + create_version()
  call, matching sample_voice_agent_basic.py. Live-tested all three end-to-end.
- GeneratePublicMethods.ps1 / docs/public-methods.md / api.md / api.metadata.yml:
  fix the generator to recognize the hand-written beta.realtime sub-client
  (a plain property, not a generated *Operations group) and regenerate.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
A parallel merge from feature/azure-ai-projects/vnext brought in a docstring
bullet-list join fix (for a Sphinx warning) that pushed one line over
pylint's 120-char limit. Re-wrap with correct RST continuation indentation;
verified clean with docutils (no Sphinx warnings) and pylint (10.00/10).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… into xitzhang/voice-agents-beta

Realigns hand-written realtime client code with the new voice_agents sub-client
hierarchy merged from vnext (PR #49003): beta.realtime -> beta.voice_agents.realtime,
beta.agent_endpoint_conversations -> beta.voice_agents.conversations,
beta.agent_telephony/agents.*_telephony_* -> beta.voice_agents.telephony,
beta.agents.generate -> beta.agents.create_from_prompt. Removes the now-dropped
agent_version_override handshake parameter, updates all samples/tests/docs to match,
and regenerates docs/public-methods.md and api.md.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Realtime/AsyncRealtime and their _ConfigProvider docstrings incorrectly said
  they could be constructed from either the top-level client or .beta.voice_agents;
  in practice only BetaVoiceAgentsOperations ever constructs them. Corrected the
  docstrings/type hints to match.
- Reformatted 4 telephony test files with black (eng/black-pyproject.toml) after
  the longer beta.voice_agents.telephony identifier pushed some lines past 120 chars.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Renames the 6 hand-written voice-agent realtime classes to align with the
generated Beta<Group>Operations naming convention used throughout the rest of
the .beta.voice_agents.* hierarchy (BetaVoiceAgentsOperations,
BetaVoiceAgentsConversationsOperations, BetaVoiceAgentsTelephonyOperations):

- Realtime -> BetaRealtime
- RealtimeConnection -> BetaRealtimeConnection
- RealtimeConnectionManager -> BetaRealtimeConnectionManager
- AsyncRealtime -> AsyncBetaRealtime
- AsyncRealtimeConnection -> AsyncBetaRealtimeConnection
- AsyncRealtimeConnectionManager -> AsyncBetaRealtimeConnectionManager

Updated everywhere these are referenced: class definitions and __all__ in
_realtime.py/aio/_realtime.py, imports/type-hints/__all__ in
operations/_patch.py and its async twin, the hand-written-subclient detection
set in docs/GeneratePublicMethodsDoc.ps1, samples that import/type-hint the
connection classes, the realtime unit test suites, a docstring comment in
foundry_features_header_test_base.py, and CHANGELOG.md. Regenerated
docs/public-methods.md and api.md/api.metadata.yml to match.

Generated model files (_enums.py/_models.py) were left untouched -- their
"Realtime" mentions are generic OpenAI Realtime API prose, not references to
these classes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

This comment has been minimized.

@github-actions

github-actions Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor
[Pilot] PR Pipeline Failure Analysis

What failed

Azure Pipeline build 6835391 (python - pullrequest) failed on all 8 platform jobs (macos311, ubuntu2404_310, ubuntu2404_310_coverage, Ubuntu2404_313, Ubuntu2404_314, windows2022_312). Two independent problems were found:

  1. Mypy (Build Analyze job)azure-ai-projects mypy check failed with exit code 1 (2 errors); azure-ai-agents passed clean.
  2. Missing test recordings (all 8 platform test jobs, sdist + whl) — the same 2 sample tests fail identically everywhere.
Relevant pipeline output
azure/ai/projects/operations/_patch.py:139: error: Incompatible types in assignment (expression has type "BetaRealtime", base class "BetaVoiceAgentsOperations" defined the type as "BetaVoiceAgentsRealtimeOperations")  [assignment]
azure/ai/projects/aio/operations/_patch.py:59: error: Incompatible types in assignment (expression has type "AsyncBetaRealtime", base class "BetaVoiceAgentsOperations" defined the type as "BetaVoiceAgentsRealtimeOperations")  [assignment]
Found 2 errors in 2 files (checked 54 source files)
mypy check completed with exit code 1

PACKAGE                                      CHECK  STATUS  DURATION(s)
/mnt/vss/_work/1/s/sdk/ai/azure-ai-agents    mypy  OK             20.33
/mnt/vss/_work/1/s/sdk/ai/azure-ai-projects  mypy  FAIL(1)        29.34

--- Test failures (repeated on every platform, sdist + whl) ---
sdk.ai.azure-ai-projects.tests.samples.test_samples.TestSamples.test_agent_insights_samples[sample_agent_insights_on_demand]
sdk.ai.azure-ai-projects.tests.samples.test_samples.TestSamples.test_agent_insights_samples[sample_agent_insights_scheduled]

azure.core.exceptions.HttpResponseError: {"Message":"Recording file path .../tests/recordings/samples/test_samples.pyTestSamplestest_agent_insights_samples[sample_agent_insights_on_demand].json does not exist.","Status":"NotFound"}

Recommended next steps

  • Mypy (fixable): In sdk/ai/azure-ai-projects/azure/ai/projects/operations/_patch.py:139 and sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_patch.py:59, the BetaVoiceAgentsOperations base class declares the realtime attribute (or equivalent) as type BetaVoiceAgentsRealtimeOperations, but the patch overrides it with BetaRealtime (sync) / AsyncBetaRealtime (async) instances, which mypy considers incompatible. Fix by either updating the base class's declared type to match the hand-written BetaRealtime/AsyncBetaRealtime types, or adding an explicit type annotation/cast at the assignment site so mypy recognizes the override as intentional. Verify with: azpysdk mypy . from sdk/ai/azure-ai-projects.
  • Missing recordings (not fixable by code change): test_agent_insights_samples[sample_agent_insights_on_demand] and [sample_agent_insights_scheduled] are new sample tests with no committed recording JSON. This is expected per the PR description ("all 8 failures are brand-new tests with no recording yet ... convention is to keep new tests enabled so PR validation surfaces missing recordings"). Recordings need to be generated (live-recorded) and committed under sdk/ai/azure-ai-projects/tests/recordings/samples/.
  • See https://aka.ms/ci-fix

Automated fix: Fix found, view and apply fix

Generated by Pipeline Analysis Next Steps · auto · 154.2 AIC · ⌖ 2.01 AIC · ⊞ 9.2K ·

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants