Skip to content

Decouple AgentServer responses from generated model internals#47995

Open
Shivakishore14 wants to merge 19 commits into
mainfrom
sshiva/agentserver-typeddict-local
Open

Decouple AgentServer responses from generated model internals#47995
Shivakishore14 wants to merge 19 commits into
mainfrom
sshiva/agentserver-typeddict-local

Conversation

@Shivakishore14

@Shivakishore14 Shivakishore14 commented Jul 10, 2026

Copy link
Copy Markdown
Member

Summary

  • Regenerate AgentServer response contracts as local TypedDict/dict-native models from the sdk-service-agentserver-contracts TypeSpec path.
  • Keep tsp-location.yaml aligned with the SDK main layout and update only the spec commit to 8bfd173c3afb9c85495293bffc04f6dcd4295548 from Azure/azure-rest-api-specs branch rapida/add-agentserver-view.
  • Keep runtime code decoupled from generated model internals while preserving generated validators and API docs.
  • Address review feedback for dict-native response models: complete ID generation coverage, preserve wire field names, filter storage-only SSE fields, and restore ResponseIncompleteReason as a public compatibility enum.

Depends on

  • Azure/azure-rest-api-specs branch rapida/add-agentserver-view at commit 8bfd173c3afb9c85495293bffc04f6dcd4295548

Validation

  • tsp-client sync
  • make generate-contracts
  • .venv/bin/azpysdk pyright .
  • .venv/bin/azpysdk apistub .
  • .venv/bin/azpysdk pylint .
  • .venv/bin/python -m black --check azure/ai/agentserver/responses/_id_generator.py azure/ai/agentserver/responses/hosting/_validation.py azure/ai/agentserver/responses/models/__init__.py azure/ai/agentserver/responses/streaming/_sse.py tests/unit/test_id_generator.py tests/unit/test_sse_writer.py
  • .venv/bin/python -m pytest tests/unit/test_id_generator.py tests/unit/test_sse_writer.py tests/e2e/test_sample_e2e.py -q59 passed, 1 skipped, 1 warning

Move response contracts to local TypedDict wire payloads and remove runtime reliance on generated model constructors, serialization helpers, and nested generated SDK model paths.

Keep validation behind a stable local wrapper and update tests to exercise dict-native payloads instead of generated model runtime callability.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions github-actions Bot added the Hosted Agents sdk/agentserver/* label Jul 10, 2026
Shivakishore14 and others added 4 commits July 10, 2026 12:44
Use the source-built TypeSpec Python emitter TypedDict output as the model source instead of the localized bridge artifact.

Normalize the emitted package into the local AgentServer generated boundary and remove fake model_base/_models compatibility shims.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pin AgentServer TypeSpec generation to the source PR that removes stale OpenAI usage decorators and enables Python TypeDict generation.

Replace the old finalization script with a minimal contract extractor, regenerate API docs and model contracts, and remove unused _types.py output.

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

Copilot-Session: 4ead3de5-a3b3-4d3a-bf93-a4ee397d7498
Regenerate AgentServer response TypedDict contracts, validators, and API docs from the current AgentServer service contract path. Point tsp-location.yaml at the fresh spec PR commit and compile from the clean synced Foundry/src root.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4ead3de5-a3b3-4d3a-bf93-a4ee397d7498
Shivakishore14 and others added 7 commits July 16, 2026 06:54
Inline the single-use wire field mutation helper and remove a thin Foundry serializer wrapper that only delegated to to_wire_dict.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4ead3de5-a3b3-4d3a-bf93-a4ee397d7498
Generate the TypedDict enum fallback at the root _generated package so validators use the same _enums import shape as latest main.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4ead3de5-a3b3-4d3a-bf93-a4ee397d7498
Point AgentServer Responses generation metadata at the latest spec PR commit after CI-only validation fixes.

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

Copilot-Session: 4ead3de5-a3b3-4d3a-bf93-a4ee397d7498
Address runtime dict-native response compatibility, static analysis, spelling, and Sphinx documentation failures for the AgentServer Responses package.

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

Copilot-Session: 4ead3de5-a3b3-4d3a-bf93-a4ee397d7498
Update samples to use TypedDict-safe access and required discriminator fields so package Pyright validation passes.

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

Copilot-Session: 4ead3de5-a3b3-4d3a-bf93-a4ee397d7498
@Shivakishore14
Shivakishore14 marked this pull request as ready for review July 17, 2026 08:09
Copilot AI review requested due to automatic review settings July 17, 2026 08:09
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
9 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Migrates AgentServer response contracts from generated runtime model classes to local TypedDict-backed wire dictionaries.

Changes:

  • Regenerates contracts and validators from the dependent TypeSpec specification.
  • Updates runtime, storage, streaming, samples, and tests for dictionary-native payloads.
  • Adds extraction tooling and removes obsolete generated-model shims.

Reviewed changes

Copilot reviewed 95 out of 101 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
type_spec/tsp-location.yaml Updates TypeSpec source and commit.
tests/unit/test_validation.py Tests dictionary-native validation errors.
tests/unit/test_string_content_expansion.py Updates content expansion tests.
tests/unit/test_sse_writer.py Uses dictionary SSE events.
tests/unit/test_session_and_response_id_resolution.py Simplifies parsed request fixture.
tests/unit/test_runtime_state.py Uses TypedDict response snapshots.
tests/unit/test_response_execution.py Updates response execution fixture.
tests/unit/test_response_event_stream_builder.py Tests dictionary event streams.
tests/unit/test_resolve_input_items_for_persistence.py Updates persistence fixtures.
tests/unit/test_input_items_provider_behavior.py Uses TypedDict responses.
tests/unit/test_in_memory_provider_crud.py Tests dictionary storage behavior.
tests/unit/test_id_generator.py Tests discriminator-based ID dispatch.
tests/unit/test_generated_payload_validation.py Uses validator wrapper.
tests/unit/test_foundry_storage_provider.py Updates storage payload fixtures.
tests/unit/test_event_stream_generators.py Verifies dictionary events.
tests/unit/test_emit_return_types.py Checks event wire discriminators.
tests/unit/test_builders.py Updates builder assertions.
tests/interop/test_sdk_round_trip.py Uses mapping-style requests.
tests/interop/test_openai_wire_compliance.py Updates wire-contract assertions.
tests/e2e/test_proxy_e2e.py Uses dictionary requests upstream.
tests/contract/test_stream_provider_fallback.py Uses public model exports.
tests/contract/test_stream_event_lifecycle.py Uses public model exports.
tests/contract/test_response_invariants.py Reads dictionary agent references.
tests/contract/test_bg_isolation_propagation.py Uses public model exports.
samples/sample_16_structured_outputs.py Builds structured-output dictionaries.
samples/sample_15_annotations.py Builds annotation dictionaries.
samples/sample_14_file_inputs.py Reads file input mappings.
samples/sample_13_image_input.py Reads image input mappings.
samples/sample_11_non_streaming_upstream.py Forwards dictionary inputs.
samples/sample_10_streaming_upstream.py Builds dictionary snapshots.
samples/sample_07_customization.py Demonstrates mapping access.
samples/sample_05_conversation_history.py Reads dictionary history.
samples/sample_04_function_calling.py Detects calls by discriminator.
samples/sample_03_full_control.py Mutates response mappings.
pyproject.toml Packages generated typing marker.
Makefile Generates and extracts TypedDict contracts.
cspell.json Adds generated terminology.
streaming/_text_response.py Uses public wire types.
streaming/_state_machine.py Uses public enums and mappings.
streaming/_sse.py Encodes mapping-only events.
streaming/_builders/_reasoning.py Returns TypedDict events.
streaming/_builders/_function.py Uses public wire contracts.
streaming/_builders/_base.py Validates dictionary item payloads.
store/_memory.py Persists dictionary snapshots.
store/_foundry_serializer.py Serializes wire dictionaries.
store/_foundry_provider.py Uses public model aliases.
store/_base.py Updates provider protocol types.
models/runtime.py Stores dictionary execution state.
models/errors.py Builds dictionary error envelopes.
models/_wire.py Adds wire normalization helpers.
models/_validators.py Wraps generated validation.
models/_generated/sdk/models/models/_patch.py Removes legacy customizations.
models/_generated/sdk/models/_types.py Removes legacy unions.
models/_generated/sdk/models/__init__.py Removes legacy package surface.
models/_generated/py.typed Marks generated contracts typed.
models/_generated/models/_patch.py Adds generated patch scaffold.
models/_generated/models/__init__.py Initializes patch surface.
models/_generated/_unions.py Adds generated unions.
models/_generated/_patch.py Removes compatibility shim.
models/_generated/_models.py Removes compatibility shim.
models/_generated/__init__.py Exports TypedDicts and enum shims.
models/__init__.py Builds the public model surface.
hosting/_validation.py Validates and returns wire dictionaries.
hosting/_runtime_state.py Copies dictionary snapshots.
hosting/_routing.py Updates handler contract types.
hosting/_request_parsing.py Resolves identity from mappings.
hosting/_observability.py Copies mapping-based tags.
hosting/_execution_context.py Uses public model types.
hosting/_event_subject.py Publishes dictionary events.
hosting/_endpoint_handler.py Normalizes dictionary HTTP payloads.
_response_context.py Resolves dictionary input items.
_id_generator.py Dispatches IDs by wire discriminator.
api.metadata.yml Updates API snapshot metadata.
_scripts/validator_emitter.py Resolves Literal enum values.
_scripts/validation-overlay.yaml Makes function-call IDs optional.
_scripts/generated_shims/sdk_models__init__.py Removes obsolete shim.
_scripts/generated_shims/models_patch.py Removes obsolete customization.
_scripts/generated_shims/_patch.py Removes obsolete patch shim.
_scripts/generated_shims/_models.py Removes obsolete model shim.
_scripts/generated_shims/_enums.py Removes obsolete enum shim.
_scripts/generated_shims/__init__.py Removes obsolete package shim.
_scripts/extract_model_contracts.py Extracts generated TypedDict contracts.
Comments suppressed due to low confidence (1)

sdk/agentserver/azure-ai-agentserver-responses/azure/ai/agentserver/responses/models/init.py:44

  • The new export construction drops the previously public ResponseIncompleteReason enum, while ResponseEventStream.emit_incomplete() still documents azure.ai.agentserver.responses.models.ResponseIncompleteReason. Either restore this hand-written enum in the public model surface or remove/update the stale reference and explicitly account for the breaking API change.
__all__ = [
    "ResponseStatus",
    "TerminalResponseStatus",
    "get_content_expanded",
    "get_conversation_expanded",
    "get_conversation_id",
    "get_input_expanded",
    "get_tool_choice_expanded",
    *_generated_all,

assert completed["response"]["status"] == "completed"
assert completed["response"]["usage"]["total_tokens"] == 3
assert isinstance(completed["response"]["completed_at"], int)
assert completed["response"]["completed_at"] is not None
Comment thread sdk/agentserver/azure-ai-agentserver-responses/type_spec/tsp-location.yaml Outdated
Regenerate AgentServer response contracts from the rapida/add-agentserver-view spec branch and restore the SDK TypeSpec pointer layout to the main SDK shape with only the commit updated.

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

Copilot-Session: 4ead3de5-a3b3-4d3a-bf93-a4ee397d7498
Copilot AI review requested due to automatic review settings July 17, 2026 12:49

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 96 out of 101 changed files in this pull request and generated 6 comments.

Fix review feedback for dict-native response models by completing ID generation coverage, preserving wire field names, filtering storage-only SSE fields, and restoring ResponseIncompleteReason as a public compatibility enum.

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

Copilot-Session: 4ead3de5-a3b3-4d3a-bf93-a4ee397d7498
Copilot AI review requested due to automatic review settings July 20, 2026 10:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 96 out of 101 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

sdk/agentserver/azure-ai-agentserver-responses/type_spec/tsp-location.yaml:2

  • The pinned source does not match this PR's stated dependency. Azure/azure-rest-api-specs#44689 changes sdk-service-agents-contracts in commit 7691586c..., whereas this selects the older sdk-service-agentserver-contracts tree at an unrelated April commit. Regeneration therefore will not consume the contract this PR depends on.

Comment thread sdk/agentserver/azure-ai-agentserver-responses/Makefile
Comment thread sdk/agentserver/azure-ai-agentserver-responses/Makefile
Sanitize generated model docstrings that Sphinx treats as warnings, narrow public model exports to actual generated types, and add package spellcheck words for generated response ID prefixes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4ead3de5-a3b3-4d3a-bf93-a4ee397d7498
Copilot AI review requested due to automatic review settings July 20, 2026 13:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 96 out of 101 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

sdk/agentserver/azure-ai-agentserver-responses/tests/unit/test_response_event_stream_builder.py:148

  • This weakened assertion hides that emit_completed() currently returns a datetime in completed_at, while the new ResponseObject TypedDict and wire contract require an integer Unix timestamp; created_at has the same mismatch. Because public emit_* methods now advertise dict-native wire payloads, convert these fields before returning the event and keep the integer assertion.

Avoid using generated enum fallback objects in runtime code by comparing against the stable wire string values directly, and annotate the ID dispatch table for mypy. Regenerate API stubs after the public export cleanup.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4ead3de5-a3b3-4d3a-bf93-a4ee397d7498
Copilot AI review requested due to automatic review settings July 20, 2026 14:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 96 out of 101 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (2)

sdk/agentserver/azure-ai-agentserver-responses/azure/ai/agentserver/responses/_response_context.py:145

  • This now collects text from every content-part discriminator. ReasoningTextContent also has a text field, so get_input_text() can expose reasoning text even though its contract says it extracts message input text. Restrict extraction to the intended input_text/resolved output_text parts.
            if _is_wire_type(item, "message") or _get_field(item, "content") is not None:
                for part in _get_field(item, "content") or []:
                    text = _get_field(part, "text")
                    if text is not None:
                        texts.append(text)

sdk/agentserver/azure-ai-agentserver-responses/azure/ai/agentserver/responses/models/init.py:41

  • models.__all__ is now built only from TypedDict/union modules, so generated public compatibility enums such as MessageRole, ToolType, and ResponseStreamEventType disappear from star imports and from api.md, even though they are imported into the module and existing callers use them. Include the generated enum compatibility names when constructing the public export list.
_generated_all = [
    name
    for module in (_generated_types, _generated_unions)
    for name in dir(module)
    if not name.startswith("_")
    and name not in _TYPE_EXPORT_EXCLUDES
    and isinstance(getattr(module, name), type)
]

Handle scale service tier validation, tighten input text extraction, preserve required statuses on search output items, reject output-only item types from input conversion, and keep generated union aliases public without exposing enum literal aliases.

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

Copilot-Session: 4ead3de5-a3b3-4d3a-bf93-a4ee397d7498
Copilot AI review requested due to automatic review settings July 20, 2026 15:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 98 out of 103 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (2)

sdk/agentserver/azure-ai-agentserver-responses/tests/unit/test_response_event_stream_builder.py:148

  • This relaxed assertion hides a wire-contract regression: ResponseObject.completed_at is Optional[int], but emit_completed() currently leaves a datetime in the returned dict and only converts it later during SSE/HTTP serialization. Public builder methods now promise dict-native wire payloads, so direct consumers receive a value that contradicts the generated TypedDict. Convert timestamps when constructing the event and retain the integer assertion here.
    sdk/agentserver/azure-ai-agentserver-responses/azure/ai/agentserver/responses/models/init.py:48
  • The new __all__ only collects TypedDict classes and Union aliases, so every generated compatibility enum such as MessageRole, ResponseStreamEventType, and ServiceTierEnum is omitted. The previous generated __all__ exported these names; wildcard imports and API stub generation therefore lose a large part of the public model surface even though _generated.__init__ still creates the compatibility enum objects. Include those generated enum exports when building __all__.
_generated_all = [
    name
    for module in (_generated_types, _generated_unions)
    for name in dir(module)
    if not name.startswith("_")
    and name not in _TYPE_EXPORT_EXCLUDES
    and _is_public_generated_export(getattr(module, name))
]

Use a correctly spelled invalid enum member name in the generated enum fallback regression test so CSpell does not flag the test-only typo.

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

Copilot-Session: 4ead3de5-a3b3-4d3a-bf93-a4ee397d7498
Copilot AI review requested due to automatic review settings July 21, 2026 09:16

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 98 out of 103 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

sdk/agentserver/azure-ai-agentserver-responses/tests/unit/test_response_event_stream_builder.py:148

  • This weakened assertion hides a wire-contract regression: ResponseObject.completed_at is typed and documented as a Unix int, but ResponseEventStream._set_terminal_fields() now leaves a datetime in the returned dict because materialize_wire_payload() does not convert it. SSE encoding happens to convert it later, but callers of the public emit_completed() API receive a value that violates ResponseCompletedEvent. Keep the integer assertion and convert created_at/completed_at when constructing the dict-native event payloads.

Comment on lines +31 to +34
"class _EnumMemberFallback(str):\n"
" @property\n"
" def value(self) -> str:\n"
" return str(self)\n\n\n"
Generate runtime enum classes from literal aliases so enum members preserve isinstance and iteration semantics, and materialize response timestamps as Unix integers in emitted wire payloads.

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

Copilot-Session: 4ead3de5-a3b3-4d3a-bf93-a4ee397d7498
Copilot AI review requested due to automatic review settings July 21, 2026 10:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 98 out of 103 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

sdk/agentserver/azure-ai-agentserver-responses/azure/ai/agentserver/responses/models/init.py:47

  • The generated root intentionally rebinds every Literal alias (for example MessageRole and AnnotationType) to a compatibility enum, but this filter inspects the original value in types.py, so all of those enums are excluded from models.__all__. This breaks from azure.ai.agentserver.responses.models import * and removes the enum declarations from api.md (only ResponseIncompleteReason remains). Inspect the value already imported into this module, or explicitly include the generated enum aliases.
    and _is_public_generated_export(getattr(module, name))

for ev in events:
copy = deepcopy(ev)
copy = dict(deepcopy(ev))
copy.setdefault("_saved_at", now)
Comment on lines +33 to +35
# All events must be dict-native ResponseStreamEvent wire payloads.
for event in events:
assert isinstance(event, ResponseStreamEvent), f"Expected ResponseStreamEvent, got {type(event)}"
assert isinstance(events[0], ResponseCreatedEvent)
assert isinstance(events[1], ResponseInProgressEvent)
assert isinstance(events[2], ResponseCompletedEvent)
assert isinstance(event, dict), f"Expected ResponseStreamEvent dict, got {type(event)}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Hosted Agents sdk/agentserver/*

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants